class:: Pstep
summary:: timed embedding of values
related:: Classes/Pseg
categories:: Streams-Patterns-Events>Patterns>Time

description::

Pstep is good for representing chord progressions, scale progressions, accent patterns, etc.

ClassMethods::

method::new
Levelpattern can return individual values, arrays, or events. The value returned by levelpattern is returned for the duration returned by durpattern.

Examples::

code::
(
// select a chord and duration and repeat it for a random time interval
p = Pstep(
	Pbind(
		\ctranspose, [0, 4, 7],
		\note,	Pwhite(0, 12),
		\dur,	Prand([0.2, 0.4, 0.8], inf)
	),
	Prand([1, 2, 4], inf)/4
);
Ppar([p, p]).play;
)
// change degree independant of number of events that have been playing

(
Pchain(
	Ppar([
		Pbind(
			\degree, Pbrown(0, 12, 1),
			\dur, Pstep( Pseq([0.1, 0.2, 0.4, 0.8, 1.6], inf), 3.2)
		),
		Pbind(
			\degree, Pbrown(0, 20, 1),
			\dur, Pstep( Pseq([0.1, 0.2, 0.4, 0.8, 1.6], inf), 4.5)
		)
	]),
	Pbind(
		\scale, Pstep(Pseq([ [0, 2, 4, 5, 7, 9, 11], [0, 1, 2, 3, 4, 5, 6]], inf), 5),
		\db, Pstep(Pseq([2, -2, 0, -2], inf), 0.25) - 10
	)
).play;
)

// use a simple pattern
(
Pchain(
	Ppar([
		Pbind(
			\octave, [5, 6] + Prand([0, 0, \r], inf),
			\degree, Prout({ | ev | loop { ev = Pseq(ev[\degree]).embedInStream } }),
			\dur,	Prout({ loop { Pseq([0.2, 0.2, 0.2, 0.2, 0.3].scramble).embedInStream } })
		),
		Pbind(
			\octave, 4,
			\legato, 1.2,
			\dur, Prout({ loop { Pseq([0.2, 0.2, 0.2, 0.2, 0.3].scramble * 5).embedInStream }})
		),
	]),
	Pstep(Pbind(
		\db, Pseq([0, -4, -2, -4, -3, -4, -3, -4], inf) - 20
	), 0.2),
	Pstep(
		Pbind(
			\degree, 	Pfunc({ {10.rand}.dup(10) }),
			\scale,	Pfunc({ {rrand(1, 2)}.dup(7).integrate })
		),
		5
	)
).play
)



// change one parameter
(
Pbind(
	\degree, Pstep(Pseq([1, 2, 3, 4, 5]), 1.0).trace,
	\dur, Pseries(0.1, 0.1, 15)
).play;
)


// change degree independant of number of events that have been playing

(
var a, b;
a = Pbind(
	\degree, Pstep(Pseq([0, 2b, 3], 1), 1.0),
	\dur, Prand([0.2, 0.5, 1.1, 0.25, 0.15], inf)
);
b = Pbind(
	\degree, Pseq([0, 2b, 3], 1),
	\dur, 2,
	\ctranspose, -7
);
Pseq([Event.silent(1.25), Ppar([a, b])], inf).play;
)



// test tempo changes

(
var a, b;
a = Pbind(
	\degree, Pstep(Pseq([0, 2b, 3], 1), 1.0),
	\dur, Prand([0.2, 0.5, 1.1, 0.25, 0.15], 9)
);
b = Pbind(
	\degree, Pseq([0, 2b, 3], 1),
	\dur, 2,
	\ctranspose, -7
);

Ppar([a, b], inf).play;
)


SystemClock.sched(0, { TempoClock.default.tempo = [1, 2, 3, 5].choose.postln; 2 });

TempoClock.default.tempo = 1.0;



// timing test:
// parallel streams


(
var a, b, x;
var times, levels;

SynthDef(\pgrain,
	{ arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
		var window;
		window = Env.sine(sustain, amp);
		Out.ar(out,
			Pan2.ar(
				SinOsc.ar(freq) * EnvGen.ar(window, doneAction:2),
				pan
			)
		)
	}
).add;

times = Pseq([3.4, 1, 0.2, 0.2, 0.2], inf);
levels = Pseq([0, 1, 2, 3, 4], inf);

a = Pstep(levels, times);
b = Pbind(\instrument, \pgrain, \octave, 7, \dur, 0.12, \degree, a);
x = times;

Ppar([b, Pset(\mtranspose, 2, b) ]).play;

b.play;
r {
	var z = x.asStream; // direct times
	0.5.wait;
	loop {
		z.next.wait;
		s.makeBundle(0.2, {
			Synth(\pgrain, [\freq, 3000, \sustain, 0.01]); // signal tone
		})
	}
}.play(quant:1)
)
::
