For JackTrip and JackTrip+Jamulus servers, all audio is processed using SuperCollider (supernova). It is configured to listen for Open Sound Control (OSC) messages on UDP port 57110. The supernova server is started with a number of input and output channels equal to the maximum number of clients supported by the server * 2 (Two channel or stereo audio is currently assumed). Please see this article for details on how we build SuperCollider from source code.
Jack connection patching is currently managed using this branch of the jack_autoconnect project. The jack connection client name (the part before ':') is used to group input and output channels associated with each unique client. Clients are assigned to reserved slots of channels on the SuperCollider server. A hash table is used to ensure that the same client, if it were to leave and reconnect later, will be reassigned to the same slots.
The sclang interpreter is run as a service to execute the audio server's mixing code. You can see and modify the source code by enabling the "Advanced" toggle under "Audio Mixing" in the Virtual Studio web interface:

The ~maxClients variable is pre-defined for the audio server, and represents the maximum number of clients it can support. This is calculated as (the number of logical processing cores + 1) * 6. This provides an extra 20% headroom above guidance. Note that the server will have ~maxClients*2 input connections and ~maxClients*2 output connections.
The VM image is created with a clone of the JackTrip Quark placed in the Extensions directory, and this clone is always updated whenever a new server is started and before the sclang service is run. Changing any mixing settings via the web interface will also cause it to check for updates.
The "main" branch of the GitHub repository is used when "Stable (Recommended)" is selected. The "develop" branch is used when "Bleeding Edge" is selected. You can also select any other branch that currently exists, which is especially useful for development and testing new code.
Note that the example above uses the "SimpleMix" class (the default). The JackTrip Quark also includes an "AutoPanMix" class that is used for auto panning and the creation of personal mixes for changing self volume levels. We welcome any updates and additional mixing classes from the open source community.
Note that SuperCollider allows for generation of any number of controls, which can be manipulated using OSC. Corresponding user interfaces can thus be built not just for simple mixing, but any kind of controls that plugin developers may envision. And OSC's broad adoption makes it possible to use a wide variety of interfaces and devices to manipulate these controls.
To learn more about leveraging the SuperCollider IDE to create mixing interfaces, see Graphical Mixing Interfaces with SuperCollider.
Metronome Example:
The code below can be modified and pasted into the "Advanced" section to run a metronome through the server. This code is meant as a starting point, please modify it to suit your needs!
Boilerplate Example for Metronome played through the server:
// output to allChannels
// change this array to only send metronome sounds to specific clients
~allChannels = Array.fill(~maxClients, { |n| n * 2; });
// from https://depts.washington.edu/dxscdoc/Help/Tutorials/Tutorial.html
// define a noise pulse
// CHANGE THE DEFAULT BPM VALUE BELOW TO CHANGE BPM
SynthDef("tish", { arg freq = 1200, bpm = 90;
var osc, trg;
trg = Decay2.ar(Impulse.ar(bpm/60,0,0.3), 0.01, 0.3);
osc = {WhiteNoise.ar(trg)}.dup;
Out.ar(~allChannels, osc);
}).send(s);
// from http://ccrma.stanford.edu/planetccrma/software/supercollider-en/four-beeps.html
// create a new SynthDef and send it to the server
SynthDef("beep", { arg amp=1.0, freq=440, i_dur=1.0;
var env, sine;
// i_* arguments are fixed at instantiation time and cannot be modulated
// doneAction 2 means free the synth node when the envelope has finished
env = Line.kr(1, 0, i_dur, doneAction: 2, mul: amp);
// the mul ugen input is usually more efficient than *
sine = SinOsc.ar(freq, mul: env);
// output to channels
Out.ar(~allChannels, [sine, sine]);
}).send(s);
// run this after the mix has started
~runAfter = {
// start the metronome
Synth("tish");
// play a beep when it starts
Synth("beep");
};
// Uncomment either the "AutoPanMix" line or the "SimpleMix" line based on which you want to use
//AutoPanMix(~maxClients).panSlots_(3).selfVolume_(1).masterVolume_(1.0).connect.start.after(~runAfter);
SimpleMix(~maxClients).masterVolume_(1.0).connect.start.after(~runAfter);
Comments
0 comments
Please sign in to leave a comment.