sclang: ServerShmInterface - try to avoid multiple destructor calls
[supercollider.git] / HelpSource / Classes / Pspawner.schelp
blobac5750b6d2372fdcc6b6f33225296c6c47db0541
1 class:: Pspawner
2 summary:: dynamic control of multiple event streams from a Routine
3 related:: Classes/Pspawn
4 categories:: Streams-Patterns-Events>Patterns>Parallel
6 description::
8 Pspawner allows a routine to dynamically start and stop subpatterns.
10 ClassMethods::
12 method::new
14 argument::function
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 InstanceMethods::
19 argument::par
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.
22 argument::seq
23 Run the entire pattern and then return control to the routine.
25 argument::wait
26 Wait strong::dur:: seconds and then return control to the routine.
28 argument::suspend
29 Find the stream in the Spawner and stop it, returns nil if the stream is not found, the stream otherwise.
31 argument::suspendAll
32 Stop all substreams of the Spawner.
34 Examples::
36 code::
37 // example 1: a simple Pspawner
40 Pspawner({ | sp |
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
46         sp.seq(
47                 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
48         );
49         sp.wait(0.4);
50         sp.seq(
51                 Ppar([
52                         Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, octave: 4]),
53                         Pbind(*[ degree: Pseq((0..7).reverse.mirror), dur: 0.2])
54                 ])
56         );
57         sp.wait(3);
58         sp.seq(
59                 Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, mtranspose: (0,2..14)])
60         );
62 // scales overlaped at 0.4 second intervals
64         10.do {
65                 sp.par(
66                         Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])
67                 );
69                 sp.wait(0.4)
70         };
71         sp.wait(1.6);
72         sp.suspendAll;
73 }).play
78 // example 2: create 5 streams at 4 second intervals
79 // then delete them in the order they were created
81 Pspawner({ | sp |
82         var streams, stream;
83         // start patterns, collect the resultant event streams
84         streams = [2, 3, 4, 6, 7, 8].collect { | i |
85                 stream = sp.par(Pbind(*[
86                         harmonic: i,
87                         ctranspose:     [0, 1, 3]/40,
88                         octave: Pbrown(2,8,2), dur: 1/i, db: -30
89                 ]) );
90                 sp.wait(4);
91                 stream;
92         };
94         // now stop those streams one by one
95         streams.do { | s | sp.suspend(s); sp.wait(4) };
96 }).play
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]) );
105         sp.wait(2);
106         sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.1]) );
107         sp.wait(1);
108         sp.par(Pbind(*[octave: 6, degree: Pbrown( -7, 7, 3), dur: 0.05]) );
109         sp.wait(0.5);
111         sp.wait(4);
112         sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );
114         sp.wait(4);
115         sp.suspendAll;
119 // play the basic patten
120 ( p.play )
123 // manipulate it with Pchain
124 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)]) ),
128         Pbind(*[
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) )
131         ])
132  ).play(protoEvent: Event.default)
135 // example 4: altering the contents of the Pspawner from separate code
138 a = Pspawner({ |sp |
139         c = sp;                         // store the Spawner in a global variable
140         100.do{ sp.wait(1) }
142 a.play;
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
151 c.par(b)
152 c.suspend(b)
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
162 c = Spawner({ |sp |
163         100.do{ sp.wait(1) }
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
171 c.par(b)
172 c.suspend(b)
174 b = c.par(                              // or just start up a new pattern
175         Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])
180 Pspawner({ | sp |
181         (1..5).do { | i |
182                 sp.par(Pbind(*[
183                         octave: i + 2,
184                         degree: Pwhite(0,7), dur: 1/i, db: -30
185                 ]) );
186                 sp.wait(4);
187         };
188         sp.suspendAll;
189 }).play