Parallelizing event patterns


There are a couple of different ways to have several patterns playing at the same time. The most obvious is to play them separately. The patterns' events get scheduled independently on their clock(s) and run concurrently. None of these patterns need to have any knowledge of the others. One advantage of this approach is that the patterns can be stopped and started independently.


The other is to combine them into a parallel stream. The result is a single pattern object that can be played or stopped only as one unit. Some degree of interactive control is lost, but there are times when merging several patterns is necessary -- for instance, converting a pattern into a Score object for NRT rendering.



An excellent example of Ppar and Pseq used together to structure an entire piece (Kraftwerk's "Spacelab") can be found in examples/pieces/spacelab.scd.


Dynamic parallelizing


Ppar and its cousins are good for a fixed set of parallel patterns -- that is, you need to know in advance how many patterns will be parallelized. Once the parallel pattern starts, there is no way to add more streams to it. To keep adding streams, use Pspawner and Pspawn. For the purpose of this overview, some basic features will be illustrated in a couple of simple examples. These classes have more capabilities; refer to their help files for specifics.



This example uses Pspawner to trigger overlapping scale segments at different speeds. Unlike Ppar, which could handle a fixed number before stopping, Pspawner can keep going indefinitely.


(

p = Pspawner({ |sp| // sp = the Spawner object

loop {

// run a new pattern in parallel

// the pattern is finite

// after a few events, it stops and the Pspawner forgets about it

sp.par(Pbind(

\degree, Pseries(rrand(-5, 7), #[-1, 1].choose, rrand(4, 7)),

\pan, rrand(-1.0, 1.0),

\dur, rrand(0.1, 0.3) // duration is chosen once for each pattern

));

// tell the Spawner to wait a bit before the next pattern goes

// DO NOT use numBeats.wait for this!

// Everything must go through the Spawner

sp.wait(rrand(1, 4) * 0.25);

}

}).play;

)


p.stop;


The same, written using Pspawn:


(

p = Pspawn(Pbind(

\method, \par, // embed patterns in parallel

// generate the subpattern in a Pfunc (so there's a new pattern each time)

// Pfunc returns the pattern without rendering the stream

// -- important for Pspawn

// See the Pspawn helpfile for other ways to embed patterns

\pattern, Pfunc {

Pbind(

\degree, Pseries(rrand(-5, 7), #[-1, 1].choose, rrand(4, 7)),

\pan, rrand(-1.0, 1.0),

\dur, rrand(0.1, 0.3) // duration is chosen once for each pattern

)

},

// The \delta key is used automatically for the spawner.wait() call

\delta, Pwhite(1, 4, inf) * 0.25

)).play;

)


p.stop;



Previous: PG_06c_Composition_of_Patterns

Next: PG_06e_Language_Control