Zack Scholl

zack.scholl@gmail.com

Producing multichannel audio synthesis with norns

 / #supercollider #til #norns 

A continuation of using multichannel audio, but with the norns.

I previously wrote a short tutorial for multichannel audio on a Linux computer with USB dongles and JACK. I recenty figured out how to easily do this with the norns sound computer.

To start, you just need USB audio adapters. It might be best to get ones that have a 48k sampling rate, as thats the norns sampling rate (others should work, but it will cost CPU to resample them). You can get these as cheap as $8.

After plugging in the adapters, the norns code needs to be slightly modified to utilize the extra audio channels. First add a file, ~/.asoundrc that has bindings for each device. Here is my file for two dongles, for a total of six channels:

pcm.merge {
    type multi;
    slaves.a.pcm hw:sndrpimonome
    slaves.a.channels 2;
    slaves.b.pcm hw:1
    slaves.b.channels 2;
    slaves.c.pcm hw:2
    slaves.c.channels 2;
    bindings.0.slave a;
    bindings.0.channel 0;
    bindings.1.slave a;
    bindings.1.channel 1;
    bindings.2.slave b;
    bindings.2.channel 0;
    bindings.3.slave b;
    bindings.3.channel 1;
    bindings.4.slave c;
    bindings.4.channel 0;
    bindings.5.slave c;
    bindings.5.channel 1;
}

ctl.merge {
    type hw
    card 0
}

You can remove slave c if you only have a single dongle, or you can add more slave X if you have more than two dongles.

In this example I am using six channels, so you’ll also need to specify this in the jack systemd file. You can edit this file with sudo:

> sudo vim /etc/systemd/system/norns-jack.service

Find the line that starts with ExecStart and change it to:

ExecStart=/usr/bin/jackd -R -P 95 -d alsa -P merge -C hw:sndrpimonome -r 48000 -n 3 -p 1024 -S -s -o 6 -i 2

The -o 6 specifies 6 channels. If you have more or less you can change this number.

Finally, we have to edit the crone service to have 6 channels (or however many you have). Edit the Crone.sc file:

> vim ~/norns/sc/core/Crone.sc

And add the following line:

server.options.numOutputBusChannels = 6;

after the line that says server.latency = 0.05;. This will make sure that SuperCollider utilizes as many buses for output as you specify.

Now you can restart norns.

Finally, you have to connect jack to the outputs. To do this, you can simply run jack_connect with as many new ports added. For these examples, I have six channels - four are extra - so I can attach them using:

jack_connect system:playback_3 SuperCollider:out_3
jack_connect system:playback_4 SuperCollider:out_4
jack_connect system:playback_5 SuperCollider:out_5
jack_connect system:playback_6 SuperCollider:out_6

This will connect the new channels (3-6) to SuperCollider.

That’s it! Now you can make SuperCollider synths that output through channels 1-6 using multiexpansion. For example, here’s a diff that changes the PolyPerc engine to use six channels to output, instead of 2:

diff --git a/sc/engines/Engine_PolyPerc.sc b/sc/engines/Engine_PolyPerc.sc
index 88362aca..436de50f 100644
--- a/sc/engines/Engine_PolyPerc.sc
+++ b/sc/engines/Engine_PolyPerc.sc
@@ -17,10 +17,10 @@ Engine_PolyPerc : CroneEngine {
                pg = ParGroup.tail(context.xg);
     SynthDef("PolyPerc", {
                        arg out, freq = 440, pw=pw, amp=amp, cutoff=cutoff, gain=gain, release=release, pan=pan;
-                       var snd = Pulse.ar(freq, pw);
+                       var snd = Pulse.ar([freq,freq*2,freq/2,freq/4,freq*1.5,freq*3], pw);
                        var filt = MoogFF.ar(snd,cutoff,gain);
                        var env = Env.perc(level: amp, releaseTime: release).kr(2);
-                       Out.ar(out, Pan2.ar((filt*env), pan));
+                       Out.ar(0, (filt*env));
                }).add;

Each speaker output (or three sets of headphones) will now all have different synthesized audio!