203 lines
3.9 KiB
Text
203 lines
3.9 KiB
Text
|
#lang scribble/manual
|
||
|
@(require (for-label racket))
|
||
|
|
||
|
@title{Pstep}
|
||
|
timed, sample-and-hold embedding of values@section{related}
|
||
|
Classes/Pseg
|
||
|
@section{categories}
|
||
|
Streams-Patterns-Events>Patterns>Time
|
||
|
|
||
|
@section{description}
|
||
|
|
||
|
|
||
|
Pstep is a "sample and hold" pattern: The value returned by teletype::next:: is held at each value in teletype::levels:: for the corresponding duration in teletype::durs::. This cycling is similar to link::Classes/Ptuple::, in that the current repeat ends when eiher pattern returns nil.
|
||
|
|
||
|
Pstep measures elapsed time using the thread's logical time. That is, it assumes it will be evaluated only exactly when needed, not before.
|
||
|
|
||
|
See link::Classes/Pseg:: for a pattern whose value changes like an link::Classes/Env::.
|
||
|
|
||
|
@section{ClassMethods}
|
||
|
|
||
|
|
||
|
@section{method}
|
||
|
new
|
||
|
Create an instance of Pstep.
|
||
|
|
||
|
@section{argument}
|
||
|
levels
|
||
|
A number, collection, or link::Classes/Pattern:: that returns the levels.
|
||
|
|
||
|
@section{argument}
|
||
|
durs
|
||
|
A number, collection, or link::Classes/Pattern:: that returns segments durations in beats.
|
||
|
|
||
|
@section{argument}
|
||
|
repeats
|
||
|
An integer, or teletype::inf::.
|
||
|
|
||
|
@section{Examples}
|
||
|
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
(
|
||
|
// 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 independently 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: Done.freeSelf),
|
||
|
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)
|
||
|
)
|
||
|
::
|
||
|
]
|
||
|
|
||
|
|