Pspawner iteration index affecting \dur

Hello,
Im trying to use the iteration index to affect the \dur key inside of a Pspawner and already read several Helpfiles and this thread Newbie: what is the unit of .wait and can it be changed? - #7 by dkmayer
At the moment im getting multiple notes postet at the same time, starting from the second iteration. I think because the waittime is not in sync with the duration of the Pseq.
how do i set the wait time right, to be in sync with the Pseq, so i dont get multiple notes postet at the same time? or is there another error? many thanks :slight_smile:

(
Pspawner({
	arg sp;
	inf.do {
		arg i;
			var d = 8/(2**(i/2).round);
			sp.par(Pbind(*[
			type: \midi,
			dur: d,
			midicmd: \noteOn,
			midiout: m,
			chan: 0,
			midinote: Pseq([64, 71, 72, 67],inf).trace,
			latency: 0.03,
			//stretch: 1,
			amp: 0.5,
			sustain: 0,
			group: ~mainGrp,
			out: ~bus[\reverb],
					]) );
		d.postln;
        sp.wait(16);
    };
    sp.suspendAll;
}).play(t);
)

If you want a sequence of Pbinds, that is, the second starts after the first stops, you should use sp.seq instead sp.par. Then sp.wait would take the time to wait between the first pbind stops and the next starts, instead of between the two starts.
PS: you should also remove the inf from Pseq, otherwise the first Pbind will never end, and thus the second would never start.

// ...
var d = 8/(2**(i/2).round);
sp.seq(Pbind(*[
// ...
	midinote: Pseq([64, 71, 72, 67]).trace,
// ...
sp.wait(0); // no pause between Pbinds
//...

If instead you want the first Pbind to play one cycle, and then spawn a second Pbind while the first is repeating, I don’t know any better solution than calculating the wait time like this:

		// ....
		var d = 8/(2**(i/2).round);
		var wait = d * 4; //4 is your notes.size
		sp.par( Pbind(*[
		// ...
		sp.wait(wait);
		// ...
1 Like

hey,
thanks for your help again.
i would like to have a fixed wait time as long as the first Pseq of 4 notes is → wait(16).
and then the iteration starts again from 0 but with the iteration index (value for d) still in mind.
because in the more advanced example im connecting these 4 notes with another Pseq.
like this:

Pseq([Pseq([64, 71, 72, 67], inf), Pseq(n,1)],inf),

so after every cycle you got more notes from the second Pseq, because the time for the first Pseq is shorter and its filling up notes until wait(16) is reached. but i would like to have a linear sequence and no notes from the past iterations.

Ok so this sounds like it should be an sp.seq. You could calculate how many times the first seq should repeat to fill 16 seconds.

But it sounds this is not really the type of control.you have in mind. You can express something like "run this patter for x seconds, then this other for y seconds … " in different ways. For example using a single pattern and changing it’s parameters in a Routine (check out Pdef or Pbindef).

Or you could just start by calling sp.suspendAll every time before you spawn a new Pbind, right after you wait.

//...
d.postln; 
sp.wait(16);
sp.suspendAll;
};
// ...

sp.suspendAll gives me a linear sequence without any notes from past iterations this is great :slight_smile: but now the second pseq always starts with the first item in the array with each new iteration. i would like that the function also remembers at which item from the second pseq it left off (n is the L-System Array). there is also just “suspend” maybe this works.

and is there a way to implement a condition that it stays at a specific value for d and not getting any faster?

d.clip(min,max)

You can do this by using a shared environment where to keep your index count. I would use Penvir for this. A simple example:

n = [1,2,3]

// Here is our shared environment
e = (i: -1);
// Use with Penvir. Note that independent:false makes it possible 
// to share our environment across different patterns
p = Penvir(e,Pbind(
	\note, Pfunc{~i = ~i + 1 % n.size; n[~i]}
),independent:false).trace.play

// wait a bit, let's say we get
// -> ( 'note': 1 )
// -> ( 'note': 2 )
// Then we do:
n = [1,2,3,4,5]
// -> ( 'note': 3 )
// -> ( 'note': 4 )
p.stop

// start a new pattern
p = Penvir(e,Pbind(
	\note, Pfunc{~i = ~i + 1 % n.size; n[~i]}
),independent:false).trace.play
// -> ( 'note': 5 )

wow i cant thank you enough.
just added

dur: d.clip(0.5,16),

and the result sounds awesome.
will try out the Penvir tomorrow :slight_smile:

hey,
when i put rests in the duration pattern the next note from the Pfunc is still played but not audible, so its jumping over one note from the array. how do i use rests, so the Pfunc waits until there is an audible note to play? sorry for these questions

dur: Pseq([1/2, 1/2, 1/2, Rest(1/2), 1/2, 1/2, Rest(1/2), 1/2, Rest(1/2), 1/2, 1/2, Rest(1/2)]*d, inf),
midinote: Pseq([Pseq([76, 83, 84, 79], 1), Pfunc{~i = ~i + 1 % n.size; n[~i]}], inf).trace,

Not at my computer but I think this would do it:

midinote: Pif(
    Pfunc { |ev| ev.isRest },
    0,  // use this if there's a rest, otherwise...
    Pseq([Pseq([76, 83, 84, 79], 1), Pfunc{~i = ~i + 1 % n.size; n[~i]}], inf)
).trace

hjh