Fade in and out a Pdef

Hello everyone!

Is it possible to fade in and out the synths generated from a Pdef ?
I know that I could use proxy space or Ndefs for that, but I have a long setup code and a close performance, I think I won’t have the time to rewrite my code and I’m not so confident with using proxyspace.

Here is a simple example.

(
SynthDef(\synth, {
	arg freq = 220, amp = 0.2, gate = 1;
	var sig, env;
	sig = LPF.ar(Saw.ar(freq), freq * 3);
	env = Env.perc().ar( 2, gate);
	sig = sig * env * amp;
	sig = Pan2.ar(sig, 0);
	Out.ar(0, sig)
}).add;

Pdef(\seq, Pbind(
	\instrument, \synth,
	\dur, 0.125,
	\degree, Pwhite(0, 12, inf),
	\amp, Pwhite(0.1, 0.2, inf) * Pdefn(\fade)
));
)


~seq = Pdef(\seq).play; // let the pattern play for a while
Pdefn(\fade, Pseg([1,0], 4, -4)); //fade out with Pseg 

My solution for now is to use Pdefn in the amp arg, and fade out using Pseg when I want to stop the sequence.
The problem is that when I start the pattern again with the play message, Pdefn(\fade) is still burned into the Pattern and I got an immediate fade out, which is not what I need.

Is there a built in way to let the pattern do its job for a while and then fading it out with a stop messagge?

Thank you in advance
best,

You can use the fadeTime arg of Pdef.

Pdef(\seq).fadeTime = 5;
Pdef(\seq, Pbind(\c, \rest))

This is really a cross fade between your Pbind inside the Pdef and a dummy Pbind which does not produce sound.

Also worth noting that you don’t need to use ~seq variable, the Pdef is already assigned to the symbol \seq and the Pdef class takes care of the rest. My suggestion still works using ~seq = Pdef(\seq).play though:

~seq = Pdef(\seq).play;
~seq.fadeTime = 5
~seq = Pdef(\seq, Pbind(\c, \rest))

Because you might want to fade up again and keep access to your original pbind, I would do it like this:

~seq = Pbind(
	\instrument, \synth,
	\dur, 0.125,
	\degree, Pwhite(0, 12, inf),
	\amp, Pwhite(0.1, 0.2, inf) * Pdefn(\fade)
);
)

Pdef(\seq, ~seq).play
Pdef(\seq).fadeTime = 5;
Pdef(\seq, Pbind(\c, \rest)); //fade out 

Pdef(\seq, ~seq).play // note how it fades back in because we did not change the fadeTime

Thank you very much for your solution!

That works but now I miss the possibility to modify the pattern while it’s playing.
Because Pdef keeps reference to the Pbind registered in the ~seq variable.

And I would like to keep the fadeTime separated from the fadeIn and fadeOut times because I want the changes in the pattern to happen quickly but still have a longer fadeOut time when I want to stop the pattern.

any other idea?

Thank you again

If you are running your code ‘by hand’, you can evaluate:

Pdef(\seq, 
	Pbind(
		\instrument, \synth,
		\dur, 0.125,
		\degree, Pwhite(0, 12, inf),
		\amp, Pwhite(0.1, 0.2, inf) * Pdefn(\fade)
	)
).play

and change values as you like. If you need to do this by code you could create a function which returns a pbind:

~seq = { |dur = 0.125, degLo = 0, degHi = 12, ampLo = 0.1, ampHi = 0.2|
	Pbind(
		\instrument, \synth,
		\dur, dur,
		\degree, Pwhite(degLo, degHi, inf),
		\amp, Pwhite(ampLo, ampHi, inf)
	)
}
)
Pdef(\seq, ~seq.()).play
Pdef(\seq).fadeTime = 0
Pdef(\seq, ~seq.(dur: 0.125, degHi: 3)).play(quant: 0)
Pdef(\seq, ~seq.(dur: [0.125, 0.25].choose, degLo: rrand(0, 5), degHi: rrand(6, 12))).play(quant: 0.25).fadeTime_(3)
Pdef(\seq).fadeTime = 5
Pdef(\seq, Pbind(\c, \rest)); //fade out