Directing samples to separate channels


#1

I have a problem with bus and samples:

// I create a 3-channel audio bus to record each of the 3 sound collections (\bouchon, \glou, \rireSynth) in a separate channel:
~recDisc = Bus.audio(s, 3);

// I create Dictionary "d" with three collections: \bouchon, \glou, \rireSynth:
(
d = Dictionary.new;
d.add(\bouchon ->
	"~/son/Sons/cuisine/boisson/bouchon01/bouchon*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
d.add(\glou ->
	"~/son/Sons/cuisine/boisson/glou01/glou*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
d.add(\rireSynth ->
	"~/son/Sons/humain01/rire/rireSynthetique01/rireSynthetique01*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
)
// I create the SynthDef to play the sounds:
(SynthDef(\bufplay, {
	|buf=0, rate=1, amp=1, pos|
	var sig;
	sig = PlayBuf.ar(numChannels:1,
		bufnum: buf,
		rate: BufRateScale.ir(buf)*rate,
		doneAction:2);
	sig = Pan2.ar(sig, pos)*amp;
	Out.ar(~recDisc, sig); // record
	Out.ar(0, sig); // monitor
}).add;
)
// I create a Synth that chooses a sound randomly in the three collections:
(
Synth(\bufplay, 
	[\buf, [
		d[\glou].choose.bufnum, 
		d[\bouchon].choose.bufnum,
		d[\rireSynth].choose.bufnum]
	.choose]);
)

// the problem is: how to make the sounds of the collection \glou go out to the bus ~recDisc.subBus(0), those of the collection \bouchon to ~recDisc.subBus(1), and those of \rireSynth to ~recDisc.subBus(2).

I can not find a solution. Someone would have any idea?


#2

Would it serve your purposes to just use an explicit out art? Or am I misunderstanding?

SynthDef(\bufPlay, {
    |out, buf=0, rate=1, amp=1, pos|
    // ...
   Out.ar(out, sig);
}).add;
~outs = ( bouchon: ~recDisc.subBus(0, 1), glou: ~recDisc.subBus(1, 1), rireSynth: ~recDisc.subBus(2, 1) )

(
var toPlay = d.keys.choose;
Synth(\bufPlay, args: [ 
    \buf, d[toPlay].choose, 
    \out, ~outs[toPlay]
]);

#3

Thank you, you understood correctly.
I am now trying to apply this to a Pbind rather than a Synth. I’m here, but it does not work:

// I create a 3-channel audio bus to record each of the 3 sound collections (\bouchon, \glou, \rireSynth) in a separate channel:
~recDisc = Bus.audio(s, 3);

// I create Dictionary "d" with three collections: \bouchon, \glou, \rire:
(
d = Dictionary.new;
d.add(\bouchon ->
	"~/son/Sons/cuisine/boisson/bouchon01/bouchon*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
d.add(\glou ->
	"~/son/Sons/cuisine/boisson/glou01/glou*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
d.add(\rire ->
	"~/son/Sons/humain01/rire/rireSynthetique01/rireSynthetique01*".pathMatch.collect({
		arg sf;
		Buffer.read(s, sf);
	});
);
)
// I create the SynthDef to play the sounds:
(
SynthDef(\bufplay, {
	arg buf=0, rate=1, amp=1.5, pos=0, out;
	var sig, monitor;
	sig = PlayBuf.ar(numChannels:1, bufnum:buf, rate:BufRateScale.ir(buf)*rate, doneAction:2);
	sig = sig*amp;
	Out.ar(out, sig); // record
	monitor = Pan2.ar(sig, pos);
	Out.ar(0, monitor); // monitoring
}).add;
)

(TempoClock.default.tempo = 200/60;
Pdef(\rythm01,
	Pbind( \instrument, \bufplay,
		\dur, Pseq([1, 1, 0.5, 0.5, 1], inf),
		\seqBuf, Pseq(["d[\bouchon]", "d[\rire]", "d[\glou]", "d[\glou]", "d[\rire]"],inf),
		\buf, Prand(Pkey(\seqBuf), repeats:inf),
		\out, Pfunc{|r| {switch(r[\seqBuf],
			d[\bouchon], {~recDisc.subBus(0,1)},
			d[\rire], {~recDisc.subBus(1,1)},
			d[\glou], {~recDisc.subBus(2,1)}
		)}},
		\amp, 1,
		\rate, Pexprand(0.90, 1.10, inf),
	));
)
r = Pdef(\rythm01);
r.play(quant:4);
r.pause;

When I play the Pdef (r.play), I have this error message:
ERROR: ListPattern (Prand) requires a non-empty collection; received a Pkey.


#4

A ListPattern’s collection can’t be changed without rebuilding the stream. This is easy to work around, though; just use Pfunc like you’re already doing for \out. Something like:

\buf, Pfunc({|r| r.seqBuf.choose })

In order for this Pattern to correctly return buffers and busses, you’ll also need to make two other small changes.

First, your \seqBuf pattern as given returns strings, while the “buf” parameter of your SynthDef expects buffers or buffer ids. Here’s one way you might fix this:

...
\seqBuf, Pseq([\bouchon, \rire, \glou, \glou, \rire], inf),
\buf, Pfunc({|r| d[r.seqBuf].choose }),
...

Second, your \out pattern returns a function which when evaluated returns a switch statement which returns one of three functions which when evaluated returns a bus. The “out” parameter of your SynthDef expects a bus or a bus id. To return the bus directly from the Pfunc, just remove some of the extra braces, and since your \seqBuf pattern is now returning symbols, change switch to test against these symbols:

...
\out, Pfunc({|r| switch(r.seqBuf,
    \bouchon, ~recDisc.subBus(0, 1),
    \rire, ~recDisc.subBus(1, 1),
    \glou, ~recDisc.subBus(2, 1)
)})
...

#5

Thank you so much. It works very well. There are a lot of subtleties in SuperCollider and I’m still almost a beginner.


#6

The stuff you’re attempting is already a little sophisticated, so you’re definitely well on your way.


#7

Thanks for the compliment, it’s nice to hear … but I know my limits and I only started programming for about four months.