Extract and group together non-consecutive sub-busses from another multichannel bus

Let’s say I have a multichannel bus and I want to send copies of groups of non-consecutive channels from this one to other busses.

For the sake of simplicity let’s pretend my initial multichannel bus has 8 channels:

a = Bus.audio(s, 8); // bus channels: [0,1,2,3,4,5,6,7,8]

and I want

  1. channels 3,4,5,6 to converge inside b (a quadraphonic new bus);
  2. channels 0,1 and 7 to converge within a new bus c (of three channels);
  3. channels 2,8 to a second one d (a two channels bus);

Solving the first problem seems to me to be quite easy because I can use the ‘subBus’ method.
b = a.subBus(3, 4);

but I don’t have a precise idea on how to solve the other two problems.

c = ?
d = ?

Any suggestion?
Thank you very much

Multichannel buses in SuperCollider are by definition contiguous - a single multichannel bus that spans non-adjacent buses simply isn’t possible. If you want to address non-adjacent channels as a “unit” - e.g. for use in an Out ugen - you’ll need to pass these into your synth as arrayed controls, and construct your Out Ugens in a loop (because Out does multichannel expansion differently than other UGens).

SynthDef(\aggregateBuses, {
   var stereoIn, stereoSig;
   
   stereoIn = In.ar(\in.kr([9999, 9999])); // \in control takes two values
   stereoIn = \mapIn.ar([0, 0]); // bus map equivalent
   
   [\out.kr([9999, 9999]), stereoIn].flop.do(Out.ar(*_));
}).play

The you could set with e.g. synth.set(\inMap, [0, 7].collect(bus.subBus(_)).collect(_.asMap))

2 Likes

Thank you @scztt for your reply,

Indeed, I suspected that there was no out-of-the-box method for doing this but that it was necessary to go through an intermediate step (through a synth).

However, it would have been difficult for me to recreate the internal procedural structure of the synth with as much synthesis and elegance.
Thank you very much.

Below, just to have it handy for future reference, I leave the test code I prepared to pardon this mode that I was not familiar with.

s.boot;

// 1. create a 4 channels audio bus starting at index 10 (arbitrary)
a = Bus.new(\audio, 10, 4, s);

// 2. define the "aggregate bus" synth in charge of making the routing of the incoming audio signals
//     This synth is using the "in.kr" method (see below for the "map" method);
(
SynthDef(\aggregateBuses, {
   var stereoIn = In.ar(\in.kr([9999, 9999]));
   [\out.kr([9999, 9999]), stereoIn].flop.do(Out.ar(*_));
}).add;
)

// 3. and instantiate it
x = Synth(\aggregateBuses);

// 4. now play some audio through the 4-channels bus
({
Out.ar(a, [
		SinOsc.ar(100),
		LFPulse.ar(100).range(-1.0, 1.0),
		WhiteNoise.ar(),
		LFSaw.ar(100)
]);
}.play;
)

// 5. take a look at the 4-channel bus
a.scope;

// 6. inject channels 0 and 2 from the 4-channel bus to the stereo input of the "aggregate bus" synth
x.set(\in, [0, 2].collect(a.subBus(_)));

// 7. make the "aggregate bus" synth output to the first audio outputs of the audio interface
x.set(\out, [0,1]);

// 8. check the server audio output
s.scope;

// 9. you can change the sub-buses to inject inside the "aggregate bus" synth
//    and correctly see the output from the synth
x.set(\in, [0,0].collect(a.subBus(_)));
x.set(\in, [2,1].collect(a.subBus(_)));
x.set(\in, [3,2].collect(a.subBus(_)));

And below the “map” method:

s.boot;

// 1. create a 4 channels audio bus starting at index 10 (arbitrary)
a = Bus.new(\audio, 10, 4, s); // bus channels: [0,1,2,3,4,5,6,7,8]

// 2. define the "aggregate bus" synth
//    in charge of making the routing of the incoming audio signals
(
SynthDef(\aggregateBuses, {
   var stereoIn = \mapIn.ar([0, 0]);
   [\out.kr([9999, 9999]), stereoIn].flop.do(Out.ar(*_));
}).add;
)

// 3. and instantiate it
x = Synth(\aggregateBuses);

// 4. now play some audio through the 4-channels bus
({
Out.ar(a, [
		SinOsc.ar(100),
		LFPulse.ar(100).range(-1.0, 1.0),
		WhiteNoise.ar(),
		LFSaw.ar(100)
]);
}.play;
)

// 5. take a look at the 4-channel bus
a.scope;

// 6. inject channels 0 and 2 from the 4-channel bus to the stereo input of the "aggregate bus" synth
x.set(\mapIn, [0, 2].collect(a.subBus(_)).collect(_.asMap))

// 7. make the "aggregate bus" synth output to the first audio outputs of the audio interface
x.set(\out, [0,1]);

// 8. check the server audio output
s.scope;

// 9. you can change the sub-buses to inject inside the "aggregate bus" synth
//    and correctly see the output from the synth
x.set(\mapIn, [0,0].collect(a.subBus(_)).collect(_.asMap));
x.set(\mapIn, [2,1].collect(a.subBus(_)).collect(_.asMap));
x.set(\mapIn, [3,2].collect(a.subBus(_)).collect(_.asMap));
2 Likes