SuperCollider for JackTrip

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 handled by additional software that runs inside our studio container image. 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 modify the source code used by enabling the "Developer Mode" toggle under "Soundscapes" in the JackTrip Web Interface:

01-SuperCollider for Virtual Studio

(Note: do not enable "Override SCLang" unless you are SuperCollider developer working on new source code)

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 "SimpleMixer" class (the default). We welcome any updates and additional mixing classes from the open source community. 

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 "SuperCollider Code (sclang)" section to run a metronome through the server. Do not click "Override SCLang" with this example. This code is meant as a starting point, please modify it to suit your needs!

Boilerplate Example for Metronome played through the server:

// Metronome rate in beats per minute
~rate = 120;

// Use this to control how loud it is (0=off, 0.5=50%, 2.0=200%)
~amp = 1.0;

// --------------------------------------------------------------
// DON'T CHANGE BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING! :)
// --------------------------------------------------------------

// output to allChannels
// change this array to only send metronome sounds to specific clients
~allChannels = Array.fill(~maxClients, { |n| n * 2; });

// Only send metronome sound to live musicians
Server.default = ~mixer.server;

// this creates the repeating metronome sound
// from https://depts.washington.edu/dxscdoc/Help/Tutorials/Tutorial.html
SynthDef("tish", { arg freq = 1200, bpm = 90, amp = 1.0;
var osc, trg;
trg = Decay2.ar(Impulse.ar(bpm/60,0,0.3), 0.01, 0.3);
osc = {WhiteNoise.ar(trg)}.dup;
osc = MulAdd(osc, amp);
Out.ar(~allChannels, osc);
}).play(args: [\bpm, ~rate, \amp, ~amp]);

// remove this part if you don't want it to beep when it starts
// from http://ccrma.stanford.edu/planetccrma/software/supercollider-en/four-beeps.html
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]);
}).play(args: [\amp, ~amp]);