Change individual keys inside Ppar

Im using a function ~transC by @elgiano to make transitions from one value to another inside a Pspawner. (But its also kind of a general question when using Ppar and want to change individual keys of the Patterns inside the Ppar).
its working fine for single keys. but ive tried to use the ~transC function with a Ppar chained to a \dur Pattern inside a Pspawner and make independent transitions for the \freq of \a and \b and its not working. any ideas? In this simplified example I would like to have \a going from 300 to 400 hz and \b going from 400 to 500 hz independently. thanks so much :slight_smile:

(
/* transC:
continuous transition, pars are set using a custom synth that writes to busses
- trans is defined as a dictionary of envelopes
e.g (amp: Env([0.1,0.5],1), ...)
- all envelopes are stretched to last transDur
- event-specific parameters like \legato are converted to Penvs and not written to busses

// \a for 3 seconds, then trans for 5 second
~transC.(\a,3,(
amp: Env([0.1,0.5],1)
),5)
*/

~transC = {|patA, durA, transDef, transDur|
	Pspawner{|sp|
		var trans = PatternProxy();
		trans.source = Pbind();
		sp.par(trans<>Pdef(patA));
		durA.wait;
		trans.source = Pbind(*~mapTrans.(transDef,transDur).asKeyValuePairs);
		transDur.wait;
		sp.suspendAll();
	}
};

// used by transC
~mapTrans = {|parEnvs, transDur= 1|
	var penvs = parEnvs.select{|v|v.class===Penv}.collect{|penv|
		penv.times = penv.times*transDur
	};
	var busses = parEnvs
	.select{|v,k| penvs.keys.includes(k).not}.collect{Bus.control(s,1)};

	{
		busses.collect{|bus, parName|
			Out.kr(bus, EnvGen.kr(parEnvs[parName],timeScale:transDur));
		};
		Line.kr(0,1,transDur,doneAction:2);
		Silent.ar;
	}.play.onFree{
		busses do: _.free
	};

	busses.collect(_.asMap) ++ penvs
};
)

working:

(
// transC example
Pdef(\a, Pbind(\note, Pseq((0..10)), \amp, 0.1, \pan, -1));
Pdef(\b, Pbind(\note, Pseq((0..10)), \amp, 0.5, \pan, 1));
)

// \a for 3 seconds, then trans for 5 second, then \b for 3 seconds
(
Pspawner{|sp|
	sp.seq(~transC.(\a, 3, (
		amp: Env([0.1, 0.5], 1),
		pan: Env([-1, 1])
	), 5));

	sp.seq(Pfindur(3, Pdef(\b)))
}.play
)

not working:

(
Pdefn(\durs, Pbind(\dur, 0.5));
Pdefn(\notes, Pbind(\freq, [300, 400]));

Pdef(\a, Pbind(\freq, Pkey(\freq).collect(_[0]), \amp, 0.1, \pan, -1, \out, 0));
Pdef(\b, Pbind(\freq, Pkey(\freq).collect(_[1]), \amp, 0.1, \pan, 1, \out, 2));

Pdef(\poly,
	Ppar([Pdef(\a), Pdef(\b)]) <> Pdefn(\durs) <> Pdefn(\notes);
)
)

// \poly for 3 seconds, then trans for 5 seconds
(
Pspawner{|sp|
	sp.seq(~transC.(\poly, 3, (
		freq: Env([[300,400], [400,500]], 1),
		//freq: Pfunc { Env([[300,400], [400,500]], 1).asArray },
		//freq: [ Env([300, 400], 1), Env([400, 500], 1) ]
	), 5));
}.play
)

My first thought is that there might not be a way to do it in this format. You would need to restructure.

To differentiate between Pdef(\a) and Pdef(\b), you would need to refer to \a and \b somehow. The catch is that Ppar doesn’t care where its subpatterns came from – it literally has no idea which pattern generated which output event.

~transC refers to keys, but these are keys within a pattern’s output events. \a and \b are keys identifying Pdefs but they are not internal to any events. Using the same word “key” for these two very different ideas may be introducing confusion. You can’t use ~transC's key mechanism to distinguish Pdefs.

Perhaps write a Pdefpar class that does keep track of each event’s source.

hjh

thanks alot @jamshark70 for taking some time looking into ~transC.

You can’t use ~transC's key mechanism to distinguish Pdefs.

would have been too good, too be true :slight_smile:

Perhaps write a Pdefpar class that does keep track of each event’s source.

unfortunately im not able to write a Pattern class on my own. The only solution i could come up with is getting rid of the Ppar and make the transitions independetly inside the Pspawner using ~transC which looks a bit uncomfortable when chaining Pdef(\a) and Pdef(\b) to Pdefn(\durs) separately instead of using Ppar and in addition using two Ptpars: Pdef(\a_ctrl) and Pdef(\b_ctrl) instead of one for multichannel expanding the LFO and split it inside the SynthDef(\pluck) to use lfo[0] for Pdef(\a) and lfo[1] for Pdef(\b). There are still some other mistakes handeling the multichannel expansion in the SynthDef i think, but for now the best i am able to do :slight_smile: thanks a lot.

(
SynthDef(\pluck, {
	var lfo = \lfo.kr(0)!2;
	var trig = Impulse.ar(0);
	var sig, env;

	env = EnvGen.kr(Env.perc(\atk.kr(0.05), \rel.kr(0.2)), doneAction: Done.freeSelf);

	sig = SinOsc.ar(lfo[0].linexp(-1, 1, 100, 8000)) + SinOsc.ar(lfo[1].linexp(-1, 1, 1000, 4000));
	sig = Pluck.ar(sig, trig, 0.1, \freq.kr(125).reciprocal, \dec.kr(0.1));

	sig = sig * env;

	sig = Pan2.ar(sig, \pan.kr(0), \amp.kr(0.25));
	Out.ar(\out.kr(0), sig);
}).add;

SynthDef(\lfo, {
	arg gate=1, devFreq=0.3, dev=1;
	var sig;
	FreeSelf.kr(gate <= 0);
	sig = LFSaw.ar(devFreq * (1 + (LFNoise2.kr(devFreq!2, dev) * 0.5)), mul: dev);
	Out.kr(\out.kr(0), sig)
}).add;
)

(
Pdefn(\durs, Pbind(\dur, Pseg(Pwhite(0.085, 0.1), 2, \exp, 1)));

Pdef(\a,
	Pbind(
		\instrument, \pluck,

		\dur, Pkey(\dur),

		\atk, 0.05,
		\rel, 0.2,

		\freq, 125,
		\dec, 0.2,

		\lfo, ~bus[\ctrl][0].asMap,
		\group, ~mainGrp,

		\out, 0,
		\amp, 0.05,
		\pan, (-1.0),
	) <> Pdefn(\durs)
);

Pdef(\b,
	Pbind(
		\instrument, \pluck,

		\dur, Pkey(\dur),

		\atk, 0.08,
		\rel, 0.4,

		\freq, 130,
		\dec, 0.3,

		\lfo, ~bus[\ctrl][1].asMap,
		\group, ~mainGrp,

		\out, 2,
		\amp, 0.05,
		\pan, 1.0,
	) <> Pdefn(\durs)
);

Pdef(\lfo_a,
	Pbind(
		\instrument, \lfo,
		\dur, inf,
		\devFreq, 0.3,
		\dev, 1,
		\out, ~bus[\ctrl][0],
		\group, ~ctrlGrp,
	);
);

Pdef(\lfo_b,
	Pbind(
		\instrument, \lfo,
		\dur, inf,
		\devFreq, 0.2,
		\dev, 1,
		\out, ~bus[\ctrl][1],
		\group, ~ctrlGrp,
	);
);

Pdef(\a_ctrl,
	Ptpar([0, Pdef(\a), 0.0001, Pdef(\lfo_a)])
);

Pdef(\b_ctrl,
	Ptpar([0, Pdef(\b), 0.0001, Pdef(\lfo_b)])
);
)

(
Pdef(\composition,
	Pspawner({|sp|

		sp.par( ~transC.(
			\a_ctrl, 8, (
				freq: Env([125, 250], 1, \exp),
				dec: Env([0.2, 0.3], 1, \lin),
				legato: Penv([0.8,0.25], 1, \exp),
		), 16));

		sp.par( ~transC.(
			\b_ctrl, 8, (
				freq: Env([130, 260], 1, \exp),
				dec: Env([0.3, 0.4], 1, \lin),
				legato: Penv([0.8,0.25], 1, \exp),
		), 16));

	})
).play;
)

Pdef(\composition).stop;