Zack Scholl

zack.scholl@gmail.com

Producing multichannel synthesis with Linux.

 / #supercollider #til 

Its surprisingly easy to utilize SuperCollider's multichannel output with multiple speakers.

SuperCollider has a pretty incredible multichannel expansion system. It’s usually useful to use as a way to generate multiple channels that are later mixed down to one or two (for headphones), but they can be quickly used to more than two physical audio channels.

On Linux, using multiple audio channels is quick and easy. You can buy the cheap DACs that do “USB audio” (~$10) and plug them into your computer. Then setup a ~/.asoundrc file like the following (more info about this on the Jack audio page):

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

ctl.merge {
    type hw
    card 0
}

This defines a new sound card “merge” that is the combination of the the first two audio devices (computer speakers and USB audio by default). You can easily add more slaves and more bindings depeneding on which cards are plugged in. The hw:0/1 are based off the cat /proc/asound/cards output. Then you can simply run JACK using this merged soundcard (named “merge”):

> jackd -v -R -P 95 -d alsa -P merge -C hw:0

(Note that the capture is still specified as hw:0).

Then in SuperCollider, you can open it and boot it with some lines specifying the number of output bus channels (in the example above we only have 4, but it could be many):

s=Server.local;
s.options.numOutputBusChannels=4;
s.boot;

Now you can use things like PanAz to pan sounds across all four channels, e.g.

(
{
	var snd;
	snd = PanAz.ar(4,SinOsc.ar(220)*0.1,MouseX.kr(-1,1),orientation:0);
	snd = snd + PanAz.ar(4,SinOsc.ar(110)*0.1,MouseX.kr(-1,1),orientation:0.25);
	snd = snd + PanAz.ar(4,SinOsc.ar(880)*0.1,MouseX.kr(-1,1),orientation:0.5);
	snd = snd + PanAz.ar(4,SinOsc.ar(442)*0.1,MouseX.kr(-1,1),orientation:0.75);
	Out.ar(0,snd.poll);
}.play;
)

More info about this in The SuperCollider Book.