2 summary:: dynamic control of multiple event streams from a Routine
3 related:: Classes/Pspawn
4 categories:: Streams-Patterns-Events>Patterns>Parallel
8 Pspawner allows a routine to dynamically start and stop subpatterns.
15 The function defines a link::Classes/Routine:: that receives a link::Classes/Spawner:: as its sole argument. All control of subpatterns is through the spawner.
20 Begin an event stream in parallel to the routine. If delta is non-zero, the pattern will begin that many beats after 'now', provided that now + delta is later than the next event that the Spawner will generate. The method returns the stream. This may be called from any object.
23 Run the entire pattern and then return control to the routine.
26 Wait strong::dur:: seconds and then return control to the routine.
29 Find the stream in the Spawner and stop it, returns nil if the stream is not found, the stream otherwise.
32 Stop all substreams of the Spawner.
37 // example 1: a simple Pspawner
42 // parallel in-c'ish pulses will run throughout the example
43 sp.par(Pbind(*[ degree: [0,7], octave: 7, dur: 0.2, db: Pseq([-20, -24, -22, -24], inf)]) );
45 // scales in sequence with pauses
47 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
52 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, octave: 4]),
53 Pbind(*[ degree: Pseq((0..7).reverse.mirror), dur: 0.2])
59 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, mtranspose: (0,2..14)])
62 // scales overlaped at 0.4 second intervals
66 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
78 // example 2: create 5 streams at 4 second intervals
79 // then delete them in the order they were created
83 // start patterns, collect the resultant event streams
84 streams = [2, 3, 4, 6, 7, 8].collect { | i |
85 stream = sp.par(Pbind(*[
87 ctranspose: [0, 1, 3]/40,
88 octave: Pbrown(2,8,2), dur: 1/i, db: -30
94 // now stop those streams one by one
95 streams.do { | s | sp.suspend(s); sp.wait(4) };
100 // example 3: define a Pspawner and use Pattern manipulations
101 p = Pspawner({ | sp |
103 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );
106 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.1]) );
108 sp.par(Pbind(*[octave: 6, degree: Pbrown( -7, 7, 3), dur: 0.05]) );
112 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );
119 // play the basic patten
123 // manipulate it with Pchain
125 Pbind(*[ctranspose: 0 + Pwhite(-0.1, 0.1)]),
126 Pbind(*[mtranspose: Pkey(\mtranspose) + Pstutter(8, Prand([0,[-3,0,2],[0,2,4,6,8,10]], inf)) ] ),
127 Pn(Pseq([p, (type:\rest, dur: 0.4)]) ),
129 db: Pstep(Pseq([-10, -13, -13, -11, -13, -13], inf), 0.1) - 10,
130 mtranspose: Pstep(Pwhite(-7, 7), Prand([5,4,2],inf) )
132 ).play(protoEvent: Event.default)
135 // example 4: altering the contents of the Pspawner from separate code
139 c = sp; // store the Spawner in a global variable
145 ( // c will not be valid until the Pspawner has run
146 b = c.par( // now start a pattern in spawner
147 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
150 c.suspend(b) // we can suspend and resume the stream
154 b = c.par( // or just start up a new pattern
155 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
159 // example 5: Spawner can be used directly in the manner of Pspawner.
160 // This allows external code to access to the spawner whether or not it has run
165 b = c.par( // now start a pattern in spawner
166 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
168 c.play; // in this case, c is always valid
170 c.suspend(b) // we can suspend and resume the stream
174 b = c.par( // or just start up a new pattern
175 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
184 degree: Pwhite(0,7), dur: 1/i, db: -30