SuperCollider CLASSES

Pspawner

dynamic control of multiple event streams from a Routine
Inherits from: Prout : Pattern : AbstractFunction : Object

Description

Pspawner allows a routine to dynamically start and stop subpatterns.

Class Methods

*new (routineFunc)

From superclass: Prout

Arguments:

routineFunc

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
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
Run the entire pattern and then return control to the routine.
wait
Wait dur seconds and then return control to the routine.
suspend
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.
NOTE: We should move the documentation of above methods to the Spawner helpfile...

Inherited class methods

Instance Methods

Inherited instance methods

Undocumented instance methods

-asStream

-embedInStream (inevent)

Examples

// 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 6 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 |
    var pat = Pbrown( -7, 7, 3);

    sp.par(Pbind(*[octave: 5, degree: pat, dur: 1/4]) );
    sp.wait(2);
    sp.par(Pbind(*[octave: 6, degree: pat, dur: 1/8]) );
    sp.wait(3);
    sp.par(Pbind(*[octave: 7, degree: pat, dur: 1/6, db: -20]) );
    sp.wait(4);
    sp.par(Pbind(*[octave: 4, degree: pat, dur: 1/4]) );

    sp.wait(8);
    sp.suspendAll;
});
)

// play the basic patten
p.play;

(
// manipulate basic pattern with Pchain
Pchain(
    Pbind(*[mtranspose: Pkey(\mtranspose) + Pstutter(8, Prand([0,[0,3,-2],[0,2,4]], inf)) ] ), //make some notes into triads
    Pbind(*[ctranspose: Pwhite(-0.1, 0.1)]), //add random detuning to notes
    Pbind(*[\scale, Scale.minor]), //alter the scale
    Pn(Pseq([p, (type:\rest, dur: 1.0)]) ), //repeat the pattern after a 1 second pause
    Pbind(*[
        db: Pstep(Pseq([-10, -13, -13, -11, -13, -13], inf), 0.1) - 10,
        mtranspose: Pstep(Pwhite(-7,7), Prand([5,4,2],inf) ) //random modal transposition
    ])
).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
)