Triggering complex Ndef with patterns

I’m trying to write a Ndef comprising a setsource pattern and drive this ensemble like a pattern.

Ideally something like this:

Ndef(\a).clear;
Ndef(\a).fadeTime=0.2;
Ndef(\a,\setsrc -> Pbind(\source,
	Pseq([
		{ |freq=440| SinOsc.ar(freq) * 0.1 },
		{ Pulse.ar(40 + [0,1]) * 0.1 },
	], 1),
	\dur, Pseq([2,2])
));
Pbind(\instrument, \a, \freq, Pseq([220,440,880]), \dur,6).play;

This fails at several levels:

  1. Pbind(\instrument, \a, is not allowed
  2. \setsource pattern starts immediately, not waiting for any “play” or “send” action.
  3. the \freq parameter is not received by the SinOsc
  4. the Ndef does not stop when its \setsource pattern is over (despite adding a EnvGate in the 2nd function)

For (1)+(2), based on the example here (that however I don’t understand why this code acts like a triggering pattern) I wrote this:

p=Pbind(\source,
	Pseq([
		{ |freq=440| SinOsc.ar(freq) * 0.1 }, 
		{ |gate=1| Pulse.ar(40 + [0,1]) * EnvGate.new(gate: gate) * 0.1 },
	], 1),
	\dur, Pseq([2,2])
);
Ndef(\a).clear;
Ndef(\a).fadeTime=0.2;
Ndef(\a).play;
Ndef(\a).put(0, \setsrc  -> Pn(p,4));

But (4) isn’t resolved.

I tried to rewrite the \setsource pattern like this without a lot of success:

p=Pbind(\source,
	Pseq([
		{ |freq=440| SinOsc.ar(freq) * 0.1 }, 
		{ |gate=1| Pulse.ar(40 + [0,1]) * EnvGate.new(gate: gate) * 0.1 },
		{ Ndef(\a).release(Ndef(\a).fadeTime);},
		// { Ndef(\a).stop(Ndef(\a).fadeTime); FreeSelf.kr(Impulse.ar(1)); }, // Self release
		// { Ndef(\a).release(Ndef(\a).fadeTime); FreeSelf.kr(Impulse.ar(1)); }, // Self release
		// { Ndef(\a).release(Ndef(\a).fadeTime); FreeSelf.kr(TDelay(Impulse.ar(1),Ndef(\a).fadeTime)); }, 
	], 1),
	\dur, Pseq([2,2],inf)
);

For solving (3) I tried this without many more success:

(
Ndef(\a).put(1, \xset -> Pbind(	\freq, Pseq([220,440,880]), \dur,4)); // Ceci retrigge le
Ndef(\a).put(0, \setsrc  -> Pn(p,4));
)

I’m new with Ndef. What am I doing wrong ?

The idea is that you can set the proxy’s source (that is, anything that you could write for “X” in Ndef(\name, X) from a pattern. The pattern is not meant to otherwise control the proxy.

An instrument in a pattern is a SynthDef not an Ndef.

That is intended behaviour, an Ndef always runs in the background, you just monitor it or not.

Your Pbind has no connection to the Ndef(\a) (see 1)

That is not the intended behavior either.

If you want to control stuff in sclang with patterns, the best way I think is to have events:

Pseq([(play: { "do something here".postln }, dur: 2), (play: { "do something else here".postln; }, dur: 1)]).play

Thanks. I guess I saw a Ndef differently as it is in reality.

I understand all you remarks except this one:

Why has this instruction no connection to the ‘Ndef(\a)’ ?

Ndef(\a).put(1, \xset -> Pbind(	\freq, Pseq([220,440,880]), \dur,4));

You can use \type, \phrase, \instrument \somePdef
(from Event Types helpfile:
phrase

instead of playing a single synth from a SynthDef with ~instrument, it looks up a Pdef and plays a cluster of sounds.)

Maybe this could be extended so it works for you?

1 Like

Indeed. Thanks. That’s right what I’m exploring now. I haven’t yet understand precisely how to control it. I’ll keep investigating.

I made it !! I’ve resolved all my issues.The sound isn’t nice, but it is for the sake of my demo.

(
SynthDef(\1,{ |freq=440, amp=0.2| 
	var env=EnvGen.kr(Env.asr(0.01,1,0.5),\gate.kr(1),doneAction:2);
	var sig=SinOsc.ar(freq) * amp * env;
	Out.ar(\out.ir(0),Pan2.ar(sig));
	}).add;
SynthDef(\2, { |atk=0.01, amp=0.2| 
	var env=EnvGen.kr(Env.asr(atk,1,0.1, -8),\gate.kr(1),doneAction:2);
	var sig=Pulse.ar(40 + [0,1]) * env * amp;
	Out.ar(\out.ir(0),Pan2.ar(sig)); 
}).add;
Pdef(\single, { |freq=440, split=1, dur=4|
	var pre=0.2;
	split=split.clip(pre,dur-pre);
	postf("% // % - % \n",dur,pre,split);
	Ptpar([
		0.0,
		Pbind(
			\instrument, \1,
			\dur, split.value*1.25,
			\freq, Pn(freq.value,1), // freq is a function, has to be evaluated
			\amp,0.2,
		)
		,split.value-pre,
		Pbind(
			\instrument, \2,
			\dur, (dur.value-split.value+pre).postln,
			\atk,pre,
			\amp,0.08,
			\freq, Pn(freq.value,1), // freq is a function, has to be evaluated
		)
	],1)
});
)
(
Pdef(\test, 
	Pbind(
		\type, \phrase,
		\instrument, \single,
		\dur, Pseries(2,1,4),
		\split, Pgauss(1,0.2), // Pwhite(0.2,Pkey(\dur)-0.2),
		\freq,Pseq([420,440],2),
	)
).play;

)
// test "single"
Pdef(\single).play 

All what I’m missing is getting the “gate” from the controlling Pdef and use it into the phrase Pdef.