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.)
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 = In.ar(0, hardwareOutChannels).keep(projectNumChannels);
if(projectNumChannels > hardwareOutChannels) { allChannels = allChannels ++ In.ar(from, privateSize) };
outputChannels = allChannels;
if(projectNumOutputChannels != projectNumChannels) {
//outputChannels = SplayAz.ar(projectNumOutputChannels, allChannels)
outputChannels = allChannels.clump(projectNumOutputChannels).sum;
};
"outputChannels size: %".format(outputChannels.size).postln;
outputChannels = outputChannels.extend(projectNumChannels, Silent.ar);
ReplaceOut.ar(0, outputChannels);
}.play(addAction: \addAfter);
"\n: Server routes % channels to % output channels.\n"
.format(projectNumChannels, projectNumOutputChannels).postln;
};
mixDown.value;
s.tree = mixDown;
}.value;
)
And when using 16 speakers, I just set projectNumOutputChannels = 16;
P.S. [edit] : I’ve added one line: ReplaceOut.ar(0, 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
Julians solution - of a synth that does the rerouting at the end of your graph - is a good one.