Ndef and PlayBuf question

Hi !
I keep exploring different ways to programming in SC. Ndef seems to be terrific for working and experimenting with multichannel fx (and a lot of others possibilities), but it still remains for me a very mysterious world. Here an example coming from The Supercollider Book and sligthly transformed. It works very well.

(SynthDef.new (\train, { |out, xfreq=15, sustain=1.0, amp=0.9, pan|
	Line.ar (1, 1, sustain, doneAction:2);
	OffsetOut.ar(out, PanAz.ar(6, Impulse.ar(xfreq), pan, orientation: 0)*amp);
}).add);

Ndef(\x).play(0, 6);

(Ndef(\x,
	Pbind(
		\instrument, \train,
		\xfreq, Pseq([50, Pwhite(30, 800, 1), 5, 14, 19], inf),
		\sustain, Pseq([Pwhite(0.01, 0.1, 1), 0.1, 1, 0.5, 0.5], inf),
		\pan, (Pwhite(0, 2.0, inf)),
		\amp, 0.5)));

Ndef(\y, {FreqShift.ar(Ndef(\x).ar, 500) }).play.fadeTime = 2;

Ndef(\z, {FreeVerb.ar(Ndef(\y).ar, 0.9, 0.99, 0.9, 1.5) }).play.fadeTime = 2;

Ndef(\z).stop;
Ndef(\y).stop;
Ndef(\x).release(5);

And now extrapolating this example, I would like to do something similar with a sampler:

b = (sample: Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav"));
(SynthDef.new(\granB, {
	arg durgrain = 1, atak = 0.5, dek = 0.5, curve = 0, buf, startPos = 0,  amp = 1;
	var sig, env;

	//----------------GRAIN
	sig = PlayBuf.ar(
		numChannels: 1,
		bufnum: buf,
		rate: \rate.ar(1.0),
		startPos: startPos * BufSampleRate.ir(buf));

	//----------------ENV
	env = EnvGen.ar(
		(Env.new(
			levels: [0, 1, 1, 0],
			times: [atak*durgrain, durgrain -(atak*durgrain + dek*durgrain), dek*durgrain],
			curve: [curve, 0 , curve * -1])),
		doneAction: Done.freeSelf);
	sig = sig * env;

	//----------------SPAT
	sig = PanAz.ar(6, sig, \pan.kr(0), orientation: 0);
	OffsetOut.ar(0, sig * amp);}
).add);


(Ndef (\player6p).play(0, 6));

(Ndef (\player6p,
	Pbind(
		\instrument, \granB ,
		\dur, 0.1,
		\buf, b.sample,
		\durgrain, 0.2,
		\startPos, (Pseries(0, 0.03, inf)) % b.sample.duration,
		\rate, 1,
		\amp, 0.3,
		\pan, Pseq((0..12), inf)/6,
	);
));

… so far so good, but this no longer works:

(Ndef (\to_shift, {FreqShift.ar(in: Ndef(\player6p).ar, freq: 500, mul: 1.0)}).play);

Could you explain me the reason ? I guess there would be something to do with the use of buffers with Ndef, but I didn’t find information about the better way to approach that. Thank you very much !

I’ve simplified my Pbind example a bit and corrected a mistake, maybe that will elicit more feedback. Perhaps this is an approach too absurd ? I’ve also seen that the use of Ndef instead of SynthDef is more common, but the use of patterns for Ndef instruments seem rather complex to understand. Perhaps the problem found in the sampler is not the use of buffers, but the management of outputs? The surprising thing is that the first example from The SC Book works fine…

Your grain synthdef has hardcoded an output bus of 0. This will not work with Ndef.

Add an out argument and use it in OffsetOut instead.

(Just to be sure, I checked the Getting Started tutorial about SynthDefs, and the examples on that page do model the use of an out argument. In any case, Out.ar(0, ...) is not an ideal coding pattern because many parts of SC assume that they will be able to direct the signal to a specific bus by using the out argument – so it’s a good habit to get into.)

hjh

Sometimes I feel so silly that I want to rip off an arm and hit myself in the head with it…

Thanks, you’re helping me a lot again, this forum is great.

Ndef works really well for the multichannel, I’m really impressed by the power and flexibility of the tool. I’ll keep exploring it. :pray: