Pspawner dynamic control of multiple event streams from a Routine


superclass: Proutine

related class: Spawner


Pspawner allows a routine to dynamically start and stop subpatterns.  


see also Pspawn



Pspawner(function)

The function defines a Routine that receives a Spawner as its sole argument. All control of subpatterns

is through the spawner


Spawner responds to the messages:


par(pattern, delta = 0)

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

 

seq(pattern)

run the entire pattern and then return control to the routine

wait(dur)

wait dur seconds and then return control to the routine

suspend (stream) 

Find the stream in the Spawner and stop it,  returns nil if the stream is not found, the stream otherwise

suspendAll

Stop all substreams of the Spawner





// example 1: a simple Pspawner


(

Pspawner({ | sp |

// parallel in-c'ish pulses will run throughout the example

sp.par(Pbind(*[ degree: [0,7], octave: 7, dur: 0.2, db: Pseq([-20, -24, -22, -24], inf)]) );

// scales in sequence with pauses

sp.seq(

Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])

);

sp.wait(0.4);

sp.seq(

Ppar([

Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, octave: 4]),

Pbind(*[ degree: Pseq((0..7).reverse.mirror), dur: 0.2])

])

);

sp.wait(3);

sp.seq(

Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2, mtranspose: (0,2..14)])

);

// scales overlaped at 0.4 second intervals


10.do {

sp.par(

Pbind(*[ degree: Pseq((0..7).mirror), dur: 0.2])

);

sp.wait(0.4)

};

sp.wait(1.6);

sp.suspendAll;

}).play

)



(

// example 2: create 5 streams at 4 second intervals

// then delete them in the order they were created

Pspawner({ | sp |

var streams, stream;

// start patterns, collect the resultant event streams

streams = [2,  3, 4,  6, 7, 8].collect { | i |

stream = sp.par(Pbind(*[

harmonic: i,

ctranspose: [0, 1, 3]/40,

octave: Pbrown(2,8,2), dur: 1/i, db: -30

]) );

sp.wait(4);

stream;

};

// now stop those streams one by one

streams.do { | s | sp.suspend(s); sp.wait(4) };

}).play


)


(

// example 3: define a Pspawner and use Pattern manipulations

p = Pspawner({ | sp |

sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );


sp.wait(2);

sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.1]) );

sp.wait(1);

sp.par(Pbind(*[octave: 6, degree: Pbrown( -7, 7, 3), dur: 0.05]) );

sp.wait(0.5);

sp.wait(4);

sp.par(Pbind(*[octave: 5, degree: Pbrown( -7, 7, 3), dur: 0.2]) );

sp.wait(4);

sp.suspendAll;

});

)


// play the basic patten 

( p.play )


(

// manipulate it with Pchain

Pchain(

Pbind(*[ctranspose: 0 + Pwhite(-0.1, 0.1)]),

Pbind(*[mtranspose: Pkey(\mtranspose) +  Pstutter(8, Prand([0,[-3,0,2],[0,2,4,6,8,10]], inf))  ] ),

Pn(Pseq([p, (type:\rest, dur: 0.4)]) ), 

Pbind(*[

db: Pstep(Pseq([-10, -13, -13, -11, -13, -13], inf), 0.1) - 10,

mtranspose: Pstep(Pwhite(-7, 7), Prand([5,4,2],inf) )

  ]) 

 ).play(protoEvent: Event.default)

)


// example 4: altering the contents of the Pspawner from separate code

(

a = Pspawner({ |sp | 

c = sp; // store the Spawner in a global variable

100.do{ sp.wait(1) } 

});

a.play;

)


( // c will not be valid until the Pspawner has run

b = c.par( // now start a pattern in spawner

Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])

);

)

c.suspend(b) // we can suspend and resume the stream

c.par(b)

c.suspend(b)

b = c.par( // or just start up a new pattern

Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])

);


// example 5: Spawner can be used directly in the manner of Pspawner.

// This allows external code to access to the spawner whether or not it has run

(

c = Spawner({ |sp | 

100.do{ sp.wait(1) } 

});

b = c.par( // now start a pattern in spawner

Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])

);

c.play; // in this case, c is always valid

)

c.suspend(b) // we can suspend and resume the stream

c.par(b)

c.suspend(b)

b = c.par( // or just start up a new pattern

Pbind(*[degree: Pseq((0..6) ++ (7..1), inf), dur: 0.2])

);

Pspawner({ | sp |

(1..5).do { | i |

sp.par(Pbind(*[

octave: i + 2,

degree: Pwhite(0,7), dur: 1/i, db: -30

]) );

sp.wait(4);

};

sp.suspendAll;

}).play