Multichannel: Best Practices

Hi -

I’m in a situation with an unpredictable multichannel audio interface. Every time I plug it in, channels 1-8 seem to come out of different ports. I’d like to do is create some code where I can calibrate my own audio outputs at the outset.

Let’s say the order of the speakers works out to be something like [4, 7, 6, 3, 5, 1, 2, 0].
I could output to the hardware buses in that order, but if I’m dealing with stereo audio files, they are going to continue to play on adjacent buses.

I’d like to know if others have solutions for establishing a fixed order at the outset of their work.

How about this… you could write the signals first to internal buses (with consecutive bus numbers for stereo, as you noted). Then, at the end of the node tree, use one or more synths to read the internal buses and re-order them to the hardware outputs.

Basically an abstraction layer: The musical code shouldn’t have to worry about the speaker arrangement. (If it does, you’re setting yourself up for headaches.)


1 Like

currently, I write a 16 channel piece and have stereo on my laptop. I use this:

	var projectNumChannels = 16;
	var projectNumOutputChannels = 2;
	var mixDown;
	mixDown = {
			var outputChannels;
			var hardwareOutChannels = s.options.numOutputBusChannels;
			var from = s.options.firstPrivateBus;
			var privateSize = projectNumChannels - hardwareOutChannels;
			var allChannels =, hardwareOutChannels).keep(projectNumChannels);
			if(projectNumChannels > hardwareOutChannels) { allChannels = allChannels ++, privateSize) };

			outputChannels = allChannels;

			if(projectNumOutputChannels != projectNumChannels) {
				//outputChannels =, allChannels)
				outputChannels = allChannels.clump(projectNumOutputChannels).sum;
			"outputChannels size: %".format(outputChannels.size).postln;
			outputChannels = outputChannels.extend(projectNumChannels,;, outputChannels);
		}.play(addAction: \addAfter);

		"\n: Server routes % channels to % output channels.\n"
		.format(projectNumChannels, projectNumOutputChannels).postln;
	s.tree = mixDown;

And when using 16 speakers, I just set projectNumOutputChannels = 16;

P.S. [edit] : I’ve added one line:, outputChannels.dump); this really makes sure that the input channels are not added to the existing ones.

P.P.S [edit]: we’ve just noticed: when the projectNumOutputChannels is larger than s.options.numOutputBusChannels, then you may get feedback, because there are the input busses in between. This is why it got a little bit more complicated.
Also, I am using variables instead of environment variables now.


In the past, I’ve used the MacOS say command to generate audio files saying the name of each speaker in a complex configuration (e.g. “left front” or “three”), and then made a simple Synth to play these out to the appropriate speakers. …And then annoyed people by playing this in a loop until I get the speakers routed correctly :slight_smile:

Julians solution - of a synth that does the rerouting at the end of your graph - is a good one.


Is it possible to do iteration of Ugens within s.tree?

I am trying to adjust the volume of an array of speakers:

~projectNumChannels = 64;
s.tree = {
		var master =, ~projectNumChannels);

		(5..64).do({arg i; master[i] = master[i]*0.5;});, master);
	}.play(addAction: \addAfter);


But it is returning the following error:

ERROR: Message ‘*’ not understood.

You need spaces…


var x=[3,4,5];x[1]=x[1]*0.5;x==[3,2,5]

perhaps connected to:

var x=[3,4,5];x[3]==nil

ps. the does not understand error should print who did not understand the message

1 Like

The array indices are 0 to 63, not up to 64.

So, (5…63) to skip the first 5 channels and process the remaining ones – or perhaps (4…63) to skip over the first 4 channels.


1 Like

Indeed!! Thanks! Every studio number its speakers from 1, I was 100% mislead by that…

Woops, my mistake, got languages mixed up :melting_face: