Time based ramdom values via Patterns

hey,
short little question:
when i would like to rewrite this for beeing used in a Pbind / Pmono what Pattern class should i choose in combination with Pexprand to have multiple random values per Event?

pitchRatio = TExpRand.ar(\pitchLo.kr(0.5), \pitchHi.kr(4), Dust.ar(3));

thanks.

Can you add it to your Ugen graph instead of calling it from a pattern? There aren’t any args here, so unsure where the values from the pattern would be going. Maybe this? Or perhaps a combination of Ppar and Pexprand?

Could you share your SynthDef?

var pitchRatio = 3.collect({      //or whatever number you like
TExpRand.ar(\pitchLo.kr(0.5), \pitchHi.kr(4), Dust.ar(3))
});

hey,

i would like to replace the pitchRatio variable with \pitchRatio.kr and sequence it via patterns.
to have more flexibility for taking .midiratio or not or having multiple values per event or not. So im searching for the Pattern expression for TExpRand.ar(\pitchLo.kr(0.5), \pitchHi.kr(4), Dust.ar(3));
right now its hardcoded into the SynthDef.

here is the Fx SynthDef:

(
SynthDef(\pitchShift, {

	var sig, inSig, local;
	
	//var pitchRatio = TExpRand.ar(\pitchLo.kr(0.5), \pitchHi.kr(4), Dust.ar(3));

	inSig = In.ar(\in.kr(0), 2);

	local = inSig + (\fbAmp.kr(1) * LocalIn.ar(2));
	local = PitchShift.ar(local, \windowSize.kr(0.15), /*pitchRatio*/ \pitchRatio.kr(0.5), \pitchDisp.kr(0.001), \timeDisp.kr(0.001));
	local = DelayC.ar(local, 1, \delTime.kr(2));
	local = Limiter.ar(local);
	LocalOut.ar(local * \decay.kr(0.5));

	sig = local * \amp.kr(1);

	sig = XFade2.ar(inSig, sig, \mix.kr(0.5).linlin(0, 1, -1, 1));

	sig = Balance2.ar(sig[0], sig[1], \pan.kr(0));
	//sig = SafetyLimiter.ar(sig);
	Out.ar(\out.kr(0), sig);
}).add;
)

I’m not sure I got your question right, but you can use Ndefs as Pbind parameter values.

// not tested code, just an example
Pbind(\pitchRatio, Ndef(\pr, {TExpRand.ar(\pitchLo.kr(0.5), \pitchHi.kr(4), Dust.ar(3))});
Ndef(\pr).set(\ptichLo, 0.7, \pitchHi, 3);
1 Like

hey, thanks for your reply :slight_smile:
Ndefs is something i havent considered.
But I think i wil leave it in the SynthDef and try to be able to enable or disable the TExpRand expression and also be able to use a sequence of values instead via patterns for \pitchRatio or just forget about it.
I thought there would be a straight forward pattern solution for this, using Ndefs inside Patterns is unfortunately not congruent with the general pattern approach i have atm and making an excuse just for this case feels a bit odd to me.

Interesting that the question is about patterns, but you haven’t shared any pattern snippets, only SynthDefs.

Anyway… “multiple random values per Event”

In other words, there is a hierarchy of behavior: one note contains multiple random values.

Pbind is a flat stream of events – therefore, Pbind by itself is likely to be clumsy for this requirement. (So, if you were thinking “How to make a Pbind do this” then you’d run into some obstacles.)

One hierarchical approach would be to have an Event spawn another stream, to set controls in the outer stream’s synth nodes. To do that, you would need access to the outer event’s node ID(s). There is a way to do that, although it’s buried in the Pattern Guide:

http://doc.sccode.org/Tutorials/A-Practical-Guide/PG_08_Event_Types_and_Parameters.html#User%20function%20hooks

\callback: A function that will be executed after the Event has finished all its work. The callback may be used for bookkeeping. Finished Events are expected to store new node IDs under ~id; with the IDs, you can register functions to watch node status or set node controls, for instance. The function receives the finished event as its argument.

I always like to post some information first, to be sure that required data will be available. In particular, how long will it play each synth? You don’t want to set controls on a synth that’s already finished. We also definitely need the ID. Because callback happens after the event has finished processing, all of these are available:

// let's start by probing for available info
(
p = Pbind(
	\degree, Pwhite(-7, 7, inf),
	\dur, 2,
	\legato, 0.9,
	\callback, { |event|
		[event[\id], event[\freq], event[\sustain]].postln;
	}
).play;
)

[ [ 1000 ], 174.6141157165, 1.8 ]
[ [ 1001 ], 440.0, 1.8 ]

p.stop;

OK, so we get an array with one or more IDs, and \freq and \sustain are there too.

Then:

(
p = Pbind(
	\degree, Pwhite(-7, 7, inf),
	\dur, 2,
	\legato, 0.9,
	\callback, { |event|
		Pfindur(event[\sustain], Pbind(
			\type, \set,
			\id, event[\id],
			\args, [\freq],
			\fake_lfo, Pgeom(1, 1.04, inf),
			\freq, event[\freq] * Pexprand(
				Pkey(\fake_lfo).reciprocal,
				Pkey(\fake_lfo),
				inf
			),
			\dur, rrand(0.05, 0.09)
		)).play
	}
).play;
)

p.stop;

(Edit: First version left out \id, event[\id] :laughing: which is kinda the whole point, oops…)

hjh

1 Like

yes thats the thing i was struggeling with. i will have a deeper look into \callback.
I see myself often writing a function for testing out some synthesis and often find some timbres i like while doing this. But then having a hard time transfering these approaches into pattern logic to be able to have a larger variety of possibilites and not be stuck with just one approach which does one random thing. Same with Demand rate Ugens. I cant see a way using them for a bigger variety of possible timbres when you have fixed sequences inside the SynthDef.

i thought another solution maybe would be to use an LFO for the pitchRatio:

pitchRatio = \pitchRatio.kr(0.5) + lfo.linlin(-1, 1, 0, \pitchRatioEnvAmount.kr(2));

Then you could either set the LFO boundaries and probably modulate its frequency and also be able to set \pitchRatioEnvAmount to 0 to disable the LFO and use a more straight forward Pseq for \pitchRatio, Pseq([7, 4], inf).midiratio, instead.

thanks a lot for you detailed explanation :slight_smile: