Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<classpathentry kind="lib" path="library/processing-core.zip"/>
<classpathentry kind="lib" path="library/javamp3-1.0.4.jar"/>
<classpathentry kind="lib" path="library/jsyn-17.1.0.jar"/>
<classpathentry kind="lib" path="library/JAsioHost.jar"/>
<classpathentry kind="lib" path="library/junit-4.12.jar"/>
<classpathentry kind="lib" path="library/android.jar"/>
<classpathentry kind="lib" path="test/**/*.class"/>
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Set up build environment and dependencies
runs:
using: "composite"
steps:
- uses: actions/setup-java@v3
- uses: actions/setup-java@v6
with:
java-version: '17'
distribution: 'temurin'
Expand All @@ -12,7 +12,7 @@ runs:

# cache any custom dependencies (e.g. processing-core.zip) in the library/
# folder so that they don't have to be downloaded every time
- uses: actions/cache@v3
- uses: actions/cache@v6
with:
key: build-deps
path: library/
2 changes: 2 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v7
- name: Set up build environment and dependencies
uses: ./.github/actions/setup
- name: Compile
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v7
- name: Set up build environment and dependencies
uses: ./.github/actions/setup
- name: Build library with Ant
run: ant jar
- name: Run tests
run: ant test
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
uses: mikepenz/action-junit-report@v6
with:
report_paths: 'TEST-*.xml'
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v7
with:
name: sound-jar-${{ github.sha }}
path: library/sound.jar
Expand All @@ -27,7 +27,7 @@ jobs:
- name: Generate Javadoc
run: ant javadoc
- name: Upload GitHub Pages Artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v5
with:
path: reference/

Expand All @@ -50,4 +50,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v1
uses: actions/deploy-pages@v5
8 changes: 4 additions & 4 deletions .github/workflows/tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v7
with:
# need this for figuring out the branch name
# (see https://stackoverflow.com/questions/63745613/how-to-get-a-branch-name-on-github-action-when-push-on-a-tag)
Expand All @@ -28,7 +28,7 @@ jobs:
run: ant dist dist-android

- name: "v* tags only: create version release draft"
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/v')
with:
draft: true
Expand All @@ -39,7 +39,7 @@ jobs:
../sound.txt

- name: "`latest` tag only: build latest library download release"
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
if: github.ref == 'refs/tags/latest'
# just override the assets, otherwise leave the existing release unchanged
with:
Expand All @@ -48,7 +48,7 @@ jobs:
../sound.txt

- name: "all other tags: create preliminary test build release"
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
if: github.ref != 'refs/tags/latest' && !startsWith(github.ref, 'refs/tags/v')
with:
name: ${{ github.ref_name }} dev build
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
.DS_Store
TEST-*
tags*
.build-deps/
hs_err_pid*.log
25 changes: 25 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<pathelement location="${lib}/jsyn-17.1.0.jar" />
<pathelement location="${lib}/processing-core.zip" />
<pathelement location="${lib}/android.jar" />
<pathelement location="${lib}/JAsioHost.jar" />
</path>

<path id="classpath.testing">
Expand Down Expand Up @@ -66,10 +67,29 @@
</unzip>
</target>

<target name="checkjasio">
<available file="${lib}/JAsioHost.jar" property="hasjasiohost" />
</target>

<!-- JAsioHost provides the Java bindings for Windows' ASIO audio drivers,
it is used by the Sound library's MultiChannel.useJASIO() mode -->
<target name="jasio-deps" depends="checkjasio" unless="hasjasiohost" description="Build JAsioHost from the bundled sources">
<mkdir dir="bin-jasiohost" />
<javac source="1.8" target="1.8" srcdir="jasiohost-master/src" destdir="bin-jasiohost" encoding="UTF-8" includeAntRuntime="false" nowarn="true">
<include name="com/synthbot/jasiohost/*.java" />
</javac>
<jar destfile="${lib}/JAsioHost.jar" basedir="bin-jasiohost" />
<delete dir="bin-jasiohost" />
<copy todir="${lib}/windows-amd64" overwrite="never">
<fileset dir="jasiohost-master" includes="jasiohost32.dll jasiohost64.dll" />
</copy>
</target>

<target name="deps" description="Get library dependencies">
<antcall target="processing-deps" />
<antcall target="android-deps" />
<antcall target="bundled-deps" />
<antcall target="jasio-deps" />
</target>

<target name="compile" depends="deps" description="Compile sources">
Expand Down Expand Up @@ -113,6 +133,8 @@
<include name="${lib}/*.jnilib" />
<!-- all files inside per-architecture native library directories -->
<include name="${lib}/*-*/*" />
<!-- JAsioHost sources and license (LGPL requires they accompany the jar) -->
<include name="jasiohost-master/**" />

<exclude name="library/android.jar" />
<exclude name="${lib}/junit-*" />
Expand Down Expand Up @@ -140,6 +162,9 @@
<!-- also drop unnecessary jars to avoid duplicate class errors -->
<exclude name="${lib}/*spi*" />
<exclude name="${lib}/jportaudio.jar" />
<!-- ASIO is Windows-only -->
<exclude name="${lib}/JAsioHost.jar" />
<exclude name="jasiohost-master/**" />
</zipfileset>
</zip>
</target>
Expand Down
168 changes: 168 additions & 0 deletions examples/IO/AsioOutput/AsioOutput.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/**
* Play a different note on every output channel of an ASIO audio interface,
* bypassing the Windows audio stack for the lowest possible latency.
*
* ASIO support is powered by the JAsioHost bindings and has to be enabled with
* MultiChannel.useJASIO() before any other Sound library call. After the
* switch, all ASIO drivers registered in the system are listed in the console.
* This is a Windows-only feature: on other operating systems (or if no ASIO
* driver is installed) useJASIO() prints an error message and the sketch
* continues with the default audio drivers, so the same sketch runs everywhere.
*
* Tip: if you don't have a driver from your audio interface manufacturer
* installed, try the universal ASIO4ALL driver.
*/

import processing.sound.*;
import com.synthbot.jasiohost.AsioDriver;
import java.util.List;

SinOsc[] sines;
int[] notes;
float[] frequencies;
boolean usingASIO;

// Optional: select a specific ASIO driver by name, exactly as printed by the
// list below. Leave this empty to use the default ASIO output device.
// Example: String asioDriverName = "Focusrite USB ASIO";
String asioDriverName = "";

// Base note (MIDI note number) and scale used to spread different notes over
// the output channels. 48 = C3, 60 = C4.
int baseMidiNote = 48;
final int[] SCALE = {0, 2, 4, 7, 9}; // major pentatonic
final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

void setup() {
size(640, 360);
background(255);

// has to be the very first Sound library call of the sketch, before any
// other Sound library objects are created or devices are selected
usingASIO = MultiChannel.useJASIO();

if (usingASIO) {
// First list all registered ASIO drivers. We only read the names from the
// registry here: opening every driver one after another can crash some
// manufacturer ASIO drivers.
List<String> asioDrivers = AsioDriver.getDriverNames();
println("Available ASIO drivers:");
for (String name : asioDrivers) {
println(" " + name);
}

// Then select the driver you want to use (see asioDriverName above).
// If that driver is not installed/registered, fall back to the first one.
if (!asioDrivers.isEmpty()) {
try {
if (asioDriverName.length() > 0) {
if (!asioDrivers.contains(asioDriverName)) {
asioDriverName = asioDrivers.get(0);
println("ASIO driver not found, falling back to '" + asioDriverName + "'");
}
Sound.outputDevice(asioDriverName);
} else {
Sound.defaultOutputDevice();
}
} catch (RuntimeException e) {
println("Could not open ASIO output device: " + e.getMessage());
}
}
}

int channels = MultiChannel.availableChannels();
if (channels <= 0) {
println("No output channels available.");
return;
}

println("Playing a different note on each of the " + channels + " output channels"
+ (usingASIO ? " of '" + asioDriverName + "'" : " of the default output device"));

sines = new SinOsc[channels];
notes = new int[channels];
frequencies = new float[channels];

for (int i = 0; i < channels; i++) {
// route the next oscillator to output channel i
MultiChannel.activeChannel(i);

sines[i] = new SinOsc(this);
sines[i].amp(0.15f);
sines[i].play();
}

// leave multi-channel routing mode so any sounds created later use the
// normal stereo layout again; already-playing sines keep their channels
MultiChannel.activeChannel(-1);

updateFrequencies();
printChannelNotes();

textSize(12);
textAlign(CENTER, BOTTOM);
}

void draw() {
if (sines == null || sines.length == 0) {
return;
}

// transpose all notes together with the mouse
baseMidiNote = 36 + int(map(mouseX, 0, width, 0, 24));
updateFrequencies();

background(255);
drawChannelBars();

fill(0);
textSize(16);
textAlign(CENTER, TOP);
text(sines.length + " ASIO output channels", width / 2, 10);
}

void updateFrequencies() {
for (int i = 0; i < sines.length; i++) {
int octave = i / SCALE.length;
int note = baseMidiNote + SCALE[i % SCALE.length] + 12 * octave;
notes[i] = note;
frequencies[i] = midiToFrequency(note);
sines[i].freq(frequencies[i]);
}
}

void printChannelNotes() {
for (int i = 0; i < notes.length; i++) {
println(" channel " + i + ": " + noteName(notes[i]) + " (" + nf(frequencies[i], 1, 2) + " Hz)");
}
}

void drawChannelBars() {
float margin = 20;
float barWidth = (width - 2 * margin) / sines.length;
float minFrequency = midiToFrequency(24);
float maxFrequency = midiToFrequency(96);

for (int i = 0; i < sines.length; i++) {
float x = margin + i * barWidth;
float h = map(frequencies[i], minFrequency, maxFrequency, 20, height - 80);
fill(0, 120, 255);
rect(x + 2, height - 40 - h, barWidth - 4, h);

fill(0);
textSize(10);
textAlign(CENTER, BOTTOM);
text(i, x + barWidth / 2, height - 10);

textSize(11);
text(noteName(notes[i]), x + barWidth / 2, height - 45);
}
}

float midiToFrequency(int note) {
return (float) (440.0 * Math.pow(2.0, (note - 69) / 12.0));
}

String noteName(int note) {
return NOTE_NAMES[note % 12] + (note / 12 - 1);
}
7 changes: 7 additions & 0 deletions jasiohost-master/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="JAsioHost.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
2 changes: 2 additions & 0 deletions jasiohost-master/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin/
.DS_Store
17 changes: 17 additions & 0 deletions jasiohost-master/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>JAsioHost</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Loading