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.
17 link::Classes/Spawner:: responds to the messages:
21 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.
24 Run the entire pattern and then return control to the routine.
27 Wait strong::dur:: seconds and then return control to the routine.
30 Find the stream in the Spawner and stop it, returns nil if the stream is not found, the stream otherwise.
33 Stop all substreams of the Spawner.
37 We should move the documentation of above methods to the link::Classes/Spawner:: helpfile...
43 // example 1: a simple Pspawner
48 // parallel in-c'ish pulses will run throughout the example
49 sp.par(Pbind(*[ degree: [0,7], octave: 7, dur: 0.2, db: Pseq([-20, -24, -22, -24], inf)]) );
51 // scales in sequence with pauses
53 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
58 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, octave: 4]),
59 Pbind(*[ degree: Pseq((0..7).reverse.mirror), dur: 0.2])
65 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, mtranspose: (0,2..14)])
68 // scales overlaped at 0.4 second intervals
72 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
84 // example 2: create 5 streams at 4 second intervals
85 // then delete them in the order they were created
89 // start patterns, collect the resultant event streams
90 streams = [2, 3, 4, 6, 7, 8].collect { | i |
91 stream = sp.par(Pbind(*[
93 ctranspose: [0, 1, 3]/40,
94 octave: Pbrown(2,8,2), dur: 1/i, db: -30
100 // now stop those streams one by one
101 streams.do { | s | sp.suspend(s); sp.wait(4) };
106 // example 3: define a Pspawner and use Pattern manipulations
107 p = Pspawner({ | sp |
109 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );
112 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.1]) );
114 sp.par(Pbind(*[octave: 6, degree: Pbrown( -7, 7, 3), dur: 0.05]) );
118 sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );
125 // play the basic patten
129 // manipulate it with Pchain
131 Pbind(*[ctranspose: 0 + Pwhite(-0.1, 0.1)]),
132 Pbind(*[mtranspose: Pkey(\mtranspose) + Pstutter(8, Prand([0,[-3,0,2],[0,2,4,6,8,10]], inf)) ] ),
133 Pn(Pseq([p, (type:\rest, dur: 0.4)]) ),
135 db: Pstep(Pseq([-10, -13, -13, -11, -13, -13], inf), 0.1) - 10,
136 mtranspose: Pstep(Pwhite(-7, 7), Prand([5,4,2],inf) )
138 ).play(protoEvent: Event.default)
141 // example 4: altering the contents of the Pspawner from separate code
145 c = sp; // store the Spawner in a global variable
151 ( // c will not be valid until the Pspawner has run
152 b = c.par( // now start a pattern in spawner
153 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
156 c.suspend(b) // we can suspend and resume the stream
160 b = c.par( // or just start up a new pattern
161 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
165 // example 5: Spawner can be used directly in the manner of Pspawner.
166 // This allows external code to access to the spawner whether or not it has run
171 b = c.par( // now start a pattern in spawner
172 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
174 c.play; // in this case, c is always valid
176 c.suspend(b) // we can suspend and resume the stream
180 b = c.par( // or just start up a new pattern
181 Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
190 degree: Pwhite(0,7), dur: 1/i, db: -30