307 lines
8 KiB
Text
307 lines
8 KiB
Text
|
#lang scribble/manual
|
||
|
@(require (for-label racket))
|
||
|
|
||
|
@title{EventPatternProxy}
|
||
|
event stream reference@section{categories}
|
||
|
Libraries>JITLib>Patterns, Live Coding
|
||
|
@section{related}
|
||
|
Classes/Pdef
|
||
|
|
||
|
@section{description}
|
||
|
|
||
|
Keeps a reference to a stream that can be replaced while in use.
|
||
|
|
||
|
@section{ClassMethods}
|
||
|
|
||
|
|
||
|
@section{method}
|
||
|
new
|
||
|
create a new instance with a pattern (the source). The pattern should be an emphasis::event pattern:: (see link::Classes/Pdef::)
|
||
|
|
||
|
@section{method}
|
||
|
default
|
||
|
a default source, if none is given. the default is a Pbind with resting notes of 1.0 beat duration.
|
||
|
|
||
|
@section{method}
|
||
|
defaultQuant
|
||
|
set the default quantization value for the class.
|
||
|
|
||
|
@section{InstanceMethods}
|
||
|
|
||
|
|
||
|
@section{method}
|
||
|
source
|
||
|
set the source (a pattern). If a quantization is given, schedule this change to the next beat ( strong::pattern_::(..) is equivalent)
|
||
|
|
||
|
@section{method}
|
||
|
clear
|
||
|
set the source to nil and stop playing
|
||
|
|
||
|
@section{method}
|
||
|
quant
|
||
|
get or set the quantization value. can be an array [quant, phase, offset, outset]
|
||
|
|
||
|
@section{method}
|
||
|
fadeTime
|
||
|
when the synthdefs that are used contain an
|
||
|
@racketblock[\amp:: control, the patterns are replaced by crossfading the previous with the new over this time (in beats)
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
envir
|
||
|
provide a default event for the Pdef. It is used to filter the incoming stream before it is passed to the source pattern. This is similar to link::Classes/NodeProxy#-nodeMap::. When set for the first time, the pattern is rebuilt.
|
||
|
|
||
|
@section{method}
|
||
|
set
|
||
|
set arguments in the default event. If there is none, it is created and the pattern is rebuilt.
|
||
|
|
||
|
@section{subsection}
|
||
|
a) using as stream reference
|
||
|
|
||
|
@section{method}
|
||
|
embedInStream
|
||
|
Given a link::Classes/Stream:: like e.g. link::Classes/Routine::, yield all values from the pattern in the proxy before continuing. One pattern proxy can be used to produce values for any number of independent streams.
|
||
|
|
||
|
@section{argument}
|
||
|
inval
|
||
|
The inval is an link::Classes/Event:: and is passed into all substreams. It can be used to control how they behave from the outside.
|
||
|
|
||
|
@section{argument}
|
||
|
embed
|
||
|
See link::Classes/Object#-streamArg:: for explanation.
|
||
|
|
||
|
@section{argument}
|
||
|
default
|
||
|
Replacement for
|
||
|
@racketblock[nil:: outputs of the source pattern. One use case is link::#-endless::.
|
||
|
|
||
|
]
|
||
|
|
||
|
@racketblock[
|
||
|
a = EventPatternProxy.new;
|
||
|
a.source = Pbind(\freq, Pgeom(100, Pwhite(1.01, 1.2), 4));
|
||
|
r = Routine { |inval| loop { a.embedInStream(inval) }; };
|
||
|
r.nextN(12, ()); // the next 12 values from r
|
||
|
a.source = Pbind(\freq, Pgeom([100, 200], Pwhite(1.01, 1.2), 4));// replace the source
|
||
|
r.nextN(12, ()); // the next 12 values from r
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
b) using as EventStreamPlayer
|
||
|
|
||
|
@section{method}
|
||
|
play
|
||
|
starts the EventPatternProxy and creates a player. if you want to play multiple instances, use link::#-fork::.
|
||
|
|
||
|
@section{argument}
|
||
|
argClock
|
||
|
play on a certain clock, e.g. a link::Classes/TempoClock::.
|
||
|
|
||
|
@section{argument}
|
||
|
protoEvent
|
||
|
an event to be used as a first input to the chain
|
||
|
|
||
|
@section{argument}
|
||
|
quant
|
||
|
can be an array of [quant, phase, offset, outset], or an instance of link::Classes/Quant::.
|
||
|
|
||
|
@section{argument}
|
||
|
doReset
|
||
|
if set to true, play will restart the stream if already running (a link::Classes/Boolean::).
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
// using a protoEvent
|
||
|
Pdef(\x, Pbind(\dur, 0.1));
|
||
|
Pdef(\x).trace.play(protoEvent: (freq: 1000));
|
||
|
::
|
||
|
|
||
|
]
|
||
|
|
||
|
@racketblock[
|
||
|
// using a different clock: here a Scheduler
|
||
|
Pdef(\x, Pbind(\dur, Pwhite(0.1, 0.2, inf), \count, Pseries()));
|
||
|
a = Scheduler(TempoClock.default);
|
||
|
Pdef(\x).trace.play(a);
|
||
|
a.advance(0.2);
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
stop
|
||
|
stops the player
|
||
|
|
||
|
@section{method}
|
||
|
player
|
||
|
the current player (if the Pdef is simply used in other streams this is
|
||
|
@racketblock[nil::)
|
||
|
|
||
|
]
|
||
|
@section{method}
|
||
|
pause, resume, reset
|
||
|
perform player method
|
||
|
|
||
|
@section{method}
|
||
|
isPlaying
|
||
|
returns true if Pdef is running. if a Pdef is playing and its stream ends, it will schedule a stream for playing as soon as a new one is assigned to it.
|
||
|
|
||
|
|
||
|
@section{Examples}
|
||
|
|
||
|
|
||
|
@section{subsection}
|
||
|
a) embedding EventPatternProxy in streams
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
(
|
||
|
SynthDef("Pdefhelp", { arg out, freq, sustain=1, amp=1, pan;
|
||
|
var env, u=1;
|
||
|
env = EnvGen.kr(Env.perc(0.03, sustain), 1, doneAction: Done.freeSelf);
|
||
|
5.do { var d; d = exprand(0.01, 1); u = SinOsc.ar(d * 300, u, rrand(0.1,1.2) * d, 1) };
|
||
|
Out.ar(out, Pan2.ar(SinOsc.ar(u + 1 * freq, 0, amp * env), pan));
|
||
|
|
||
|
}).add;
|
||
|
)
|
||
|
s.boot;
|
||
|
|
||
|
#a, b, c, m = { EventPatternProxy.new } ! 4;
|
||
|
|
||
|
m.play;
|
||
|
m.source = Pbind(\instrument, \Pdefhelp, \dur, 1, \degree, 16, \legato, 0.1);
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 5, 4, 3]));
|
||
|
b.source = Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[7, 8, 7, 8]));
|
||
|
c.source = Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 1, 2], 2));
|
||
|
|
||
|
x = Pseq([a, b, c], inf).play;
|
||
|
|
||
|
|
||
|
c.source = Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[4, 3, 1, 2]*3));
|
||
|
|
||
|
|
||
|
// infinite loops are scheduled (to ths clock's next beat by default) and released:
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.753, \degree, Pseq(#[0, 5, 4, 3, 2], inf));
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[0, 5, 4, 3] + 1, 1));
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 5, 4, 3] - 1, 1));
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[0, 5] - 1, 1));
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.753, \degree, Pshuf(#[0, 5, 4, 3, 2], inf));
|
||
|
|
||
|
x.stop;
|
||
|
m.stop;
|
||
|
|
||
|
// EventPatternProxy can be used in multiple patterns
|
||
|
|
||
|
(
|
||
|
x = Ppar([
|
||
|
Pbindf(Pn(a, inf),
|
||
|
\gtranspose, Pstutter(8, Pseq(#[0, 2, 0, 3],inf))
|
||
|
),
|
||
|
Pbindf(Pn(a, inf),
|
||
|
\gtranspose, Pstutter(8, Pseq(#[7, 4, 0, 3],inf)),
|
||
|
\dur, 0.6
|
||
|
),
|
||
|
Pbindf(Pn(a, inf),
|
||
|
\degree, Pseq(#[0, 5, 4, 3, 2, 3, 2], 1)
|
||
|
)
|
||
|
]).play;
|
||
|
)
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.1, \degree, Pseq(#[0, 1, 0, 1, 2], inf));
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.2, \degree, Pseq([0, 4], inf));
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.2, \degree, Pseq([0, 4, Prand([6, 8b],2)], inf));
|
||
|
|
||
|
a.source = Pbind(\instrument, \Pdefhelp, \dur, 0.1, \degree, Pseq(#[0, 1b, 1, 2b, 2, 3, 4b, 4, 5], inf));
|
||
|
|
||
|
a.set(\detune, -50); // set environment
|
||
|
a.set(\detune, 0);
|
||
|
|
||
|
x.stop;
|
||
|
::
|
||
|
|
||
|
]
|
||
|
@section{subsection}
|
||
|
b) playing EventPatternProxy
|
||
|
|
||
|
|
||
|
@racketblock[
|
||
|
(
|
||
|
// load a synthdef
|
||
|
s.boot;
|
||
|
SynthDef("gpdef",
|
||
|
{ arg out=0, freq=440, sustain=0.05, amp=0.1, pan;
|
||
|
var env;
|
||
|
env = EnvGen.kr(Env.perc(0.01, sustain), doneAction: Done.freeSelf) * amp;
|
||
|
Out.ar(out, Pan2.ar(SinOsc.ar(freq, 0, env), pan))
|
||
|
}).add;
|
||
|
)
|
||
|
|
||
|
|
||
|
#x, y = {EventPatternProxy.new} ! 2;
|
||
|
|
||
|
x.play; // play them. A silent resting pattern is used.
|
||
|
y.play;
|
||
|
|
||
|
|
||
|
// assign various patterns to it:
|
||
|
|
||
|
x.source = Pbind(\dur, 0.25, \instrument, \gpdef);
|
||
|
x.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6], inf), \instrument, \gpdef);
|
||
|
x.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]+1, inf), \instrument, \gpdef);
|
||
|
y.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]-1, inf), \instrument, \gpdef);
|
||
|
y.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b]-2, inf), \instrument, \gpdef);
|
||
|
|
||
|
// using fadeTime:
|
||
|
|
||
|
y.fadeTime = 8.0;
|
||
|
y.source = Pbind(\dur, 0.125, \degree, Pseq([3, 4, 5b, 6]+4.rand, inf), \instrument, \gpdef);
|
||
|
y.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]-2, inf), \instrument, \gpdef);
|
||
|
|
||
|
(
|
||
|
x.source = Pbind(
|
||
|
\dur, 1 / 6,
|
||
|
\degree, Pseq([3, 4, Prand([8, 2, 3, 9, 10],1) - 5, 6]+1, inf),
|
||
|
\instrument, \gpdef
|
||
|
)
|
||
|
);
|
||
|
)
|
||
|
(
|
||
|
x.source = Pbind(
|
||
|
\dur, 0.25,
|
||
|
\degree, Pseq([3, 4, Prand([8, 2, 3, 9, 10],1), 6], inf),
|
||
|
\instrument, \gpdef)
|
||
|
);
|
||
|
)
|
||
|
x.stop;
|
||
|
|
||
|
|
||
|
|
||
|
// tempo change
|
||
|
TempoClock.default.tempo = 1.3;
|
||
|
y.source = Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5, 6]+1, inf), \instrument, \gpdef);
|
||
|
|
||
|
// drop in ending patterns
|
||
|
|
||
|
x.play;
|
||
|
x.fadeTime = nil;
|
||
|
|
||
|
x.source = Pbind(\dur, 0.25, \degree, Pseq([3, [7,4], 5, 6]-2), \instrument, \gpdef);
|
||
|
x.source = Pbind(\dur, 0.125, \degree, Pseq([3, [7,4], 5, 4]-3), \instrument, \gpdef);
|
||
|
x.source = Pbind(\dur, 0.35, \degree, Pseq([3, [7,4], 5, 4, 3]-3), \instrument, \gpdef);
|
||
|
x.source = Pbind(\dur, 0.25, \degree, Pshuf([3, [7,4], 5, 6]-2), \instrument, \gpdef);
|
||
|
|
||
|
|
||
|
|
||
|
TempoClock.default.tempo = 1.0;
|
||
|
x.stop;
|
||
|
y.stop;
|
||
|
::
|
||
|
]
|
||
|
|
||
|
|