Hi all!

How do people do multichannel stuff?

To start with - say if I've got 4 channels, then I want d1 to go to 1st channel, d2 to go to 2nd, d3 to 3rd, etc...?

And i guess it would be much harder to spatialise it, so for example to have d1 moving around the room/through the different channels at different points..?

Thanks in advance!

Firstly, you'll want to look at separating audio outputs in superdirt and supercollider, as per:

Then you can use # orbit to choose your stereo output pairs - orbit is patternable as it turns out, so this puts output on a different stereo pair each cycle:

# orbit "<0 1 2>"

Then just route your sc outputs wherever you want them to appear

1 Like

Hey thanks.

I'm getting it ready to use 16 speakers - this is what I've done, could you check it please? These lines are what I've changed from the supercollider startup file

s.options.numOutputBusChannels = 16;

~dirt = SuperDirt(16, s);

~dirt.start(57120, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

So then I run this, if I wanted to send one pattern the first speaker I would write # orbit "0.0625"

then say if I wanted to send another pattern to the 12th speaker, I would write # orbit "0.75"

...if my maths is right?

Thanks again!

I initially thought this is more complicated than it needs to be, but by the end of this post I realised there were a few ways to skin this cat :wink: - here's what I initially thought you would do:

Option 1:
Inside s.reboot {

s.options.numOutputBusChannels = 16;

Then inside s.waitForBoot:

// leave this at 2 (stereo channel per orbit)
~dirt = SuperDirt(2, s); // two output channels, increase if you want to pan across more channels
~dirt.start(57120, [0, 2, 4, 6, 8, 10, 12, 14] );   // start listening on port 57120, create 8 stereo busses

then you have # orbit 0..7 each with a stereo pair of speakers (use # pan [0|1] to access individual speakers.

Option 2:
realistically, another option would be to make each orbit a single speaker, might look like:
leave sc output channels at 16 -> inside s.waitForBoot:

~dirt = SuperDirt(1, s); // mono output channel
~dirt.start(57120, [0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 12,13, 14,15] );   // start listening on port 57120, create 16 mono busses

Then you use # orbit 0..15 to access each individual speaker, # pan does nothing

Option 3:
then of course you could use a single orbit with 16 speakers which is what I think you've proposed. sc output channels stay at 16 -> inside s.waitForBoot:

~dirt = SuperDirt(16, s); // 16ch output
~dirt.start(57120, [0] );   // start listening on port 57120, create 16 mono busses

Then you use # orbit 0 to access the bank of speakers, and use divisions of 1/16 in # pan to access each individual speaker

Disclaimer: all of this is wholly untested - without knowing exactly what your plan is,it's hard to say which would work best but I feel like option 3 might be most flexible (I'm not sure if you can specify a pattern to play on multiple orbits for example, which you'd need to pan smoothly I think)

Ok, I will try all these and get back to you. I only have 1 hour in the spatial sound lab tomorrow to test it out so just wanted to pre empt some of my confusion......... Thank you so much

So with the option 3 as you wrote - not quite sure the difference between pan and orbit

are you saying to do the following to send this pattern to the 2nd speaker only (if my maths is right? 0 is first speaker, so second speaker is 0.0625?) -

d1 $ s "bd*8" # pan 0.0625

then I don't understand where # orbit 0 comes in?

Sorry if this is tedious, I'm very inexperienced with sound terms / speaker technical jargon & set ups etc. In absolute laymans terms would be great

yeah - here's a tip though, don't worry about your maths and use fractions for readability

d1 $ s "bd*8" # pan (1/16)

pan through the full range of speakers (adjust the fractions if you want to limit the speakers)

d1 $ s "bd*8" # pan (range (0/16) (16/16) (slow 8 saw))

a new and undocumented-ish feature in current tidal - using panbus on a long sample (note it goes from -1 to 1 instead of 0 to 1) so that it will pan even though you're only playing an event once every 4 cycles:

    $ s "[bev/4]"    
    # panbus 1 (range (-8/8) (8/8) (slow 4 saw))   
    # legato 1

well, this is where my lack of experience/knowledge with this comes in -
In a default setup, an orbit refers to a pair of stereo channels, there are multiple orbits which effectively map directly to each dN $
The orbits allow global effects (such as delay, reverb) to be applied in different amounts to different orbits.
In the config we've setup though, there is only a single orbit - I don't know if tidal will definitely just loop on the single available orbit, or whether it will send to non-existent orbits (I'd expect it'll do the former), but by defining # orbit 0 it was like a safeguard that it will go exactly where you wanted it to

Yes this would work fine. If you want to send a sound to a particular speaker by number without doing the maths, you can also use channel, e.g. d1 $ sound "bd" # channel "5" to go to the sixth speaker (since it starts counting from 0).

You can test this without having to be on an actual multichannel system. Just start superdirt with these settings and open a scope (click on numbers on bottom right, and "show scope"). Then run something like this and you should see the kick move around: d1 $ channel "0 .. 15" # sound "bd"

Because bd is a stereo sample, it will play across adjacent channels. There should be a way to handle how stereo samples are played but I think it's a bit buggy:

I wouldn't worry too much about orbits. With the above config you are creating 18 but you could stick with the usual 12 (which are assigned from d1 to d12) by replacing the dirt.start line with ~dirt.start(57120, 0 ! 12); (which would be the same as having twelve zeroes). That's a bit less resource intensive. You could reduce the number of orbits as cleary says if you have problems with cpu usage but I think the usage is low, and then you will have problems with using reverb and delays.

1 Like