// title: Pspawner demo // author: Bruno Ruviaro // description: // A short classroom demonstration of sequencing patterns with Pspawner // code: // =================================== // SynthDefs here // =================================== // Your SynthDefs go here ( ) // end of SynthDefs // =================================== // Define a bunch of "score snippets" // =================================== ( ~beat = Pbind( \degree, [0, 7], \ctranspose, 24, \dur, 0.2, \legato, 0.1, \amp, Pseq([0.2, 0.12, 0.16, 0.12], inf) ); // forever pattern ~up = Pbind( \scale, Scale.major, \degree, Pseq([0, 1, 2, 3, 4, 5, 6, 7], 1), // finite pattern \dur, 0.2 ); ~down = Pbind( \scale, Scale.minor, \degree, Pseq([7, 6, 5, 4, 3, 2, 1, 0], 1), // finite pattern \dur, 0.1, ); ~trill = Pbind( \degree, Pseq([8, 9], 4), // finite Pattern \dur, 0.1 ); ~thick = Pbind( \degree, Pseq([0, 1, 2, 3, 4, 5, 6, 7], 1), // finite Pattern \dur, 0.2, \mtranspose, [0, 2, 4, 6, 8, 10, 12, 14] ); ) // end of Pbind definitions // ============ // Quick test // ============ ~beat.play; ~up.play; ~down.play; ~trill.play; ~thick.play; // ===================== // Sequencing & playing // using Pspawner // ===================== // The advantage is that the spawner *knows* when a pattern has finished. // (... as opposed to sequencing patterns inside a {}.fork) // It's like a fork (things happen in order top to bottom), but // you always use the spawner argument (in this case, "maestro" -- arbitrary name) // in order to request a new pattern. // Notice you should NOT put any .play inside the Pspawner. The only .play is at the very end of the Pspawner. // When you write "maestro.seq(somePattern)", you are saying: // "maestro, please play this pattern and only move on in the sequence AFTER said pattern is finished". // When you write "maestro.par(somePattern)", you are saying: // "maestro, please start playing this pattern and MOVE ON RIGHT AWAY to the next line." // Patterns that self-terminate will do so as expected. // Patterns that do not self-terminate (inf) will keep going forever until told to stop. // TIP 1: Notice that if you write maestro.seq(someInfPattern) you are setting yourself up for failture. If you request maestro to play an *infinite* pattern and only move on when it's finished, maestro will never move on. // TIP 2: In order to control start and stop of specific patterns, you should declare a new variable to name it (as you learned before). See ~player1 example below. ( Pspawner({ arg maestro; "Scales in sequence, one right after the other".postln; maestro.seq(~up); "Down...".postln; maestro.seq(~down); "With a little pause in between".postln; maestro.wait(2.5); maestro.seq(~up); maestro.wait(1); maestro.seq(~down); maestro.wait(1); "Now two of them in paralell".postln; maestro.seq(Ppar([~up, ~down])); maestro.wait(4); "Now the never-ending beat".postln; // Saving into a variable so I can stop it later ~player1 = maestro.par(~beat); maestro.wait(4); "Up again...".postln; maestro.seq(~up); maestro.wait(1); "Stop player1 beta".postln; maestro.suspend(~player1); // stop that one maestro.wait(1); "Play the thick pattern".postln; maestro.seq(~thick); "Bye!".postln; maestro.suspendAll; }).play )