// This file demonstrates creating temporal structures using Spawn and classes // built upon Spawn. None of these examples are meant to be particularly musical.. ////////////////////////////////////////////////////////////////////////// ( // one level of spawning e = Env.new([0,1,0.2,0],[0.004, 0.2, 4], -2); Synth.play({ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, FSinOsc.ar((i * 200) + 600, 0.1)); }, 1, // number of channels 0.1, // next time 20); // number of repeats }) ) ////////////////////////////////////////////////////////////////////////// ( // two levels of spawning e = Env.new([0,1,0.2,0],[0.004, 0.2, 4], -2); Synth.play({ Spawn.ar({ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, FSinOsc.ar((i * 200) + 600, 0.1)); }, 1, 0.1, 4); }, 1, // number of channels nil, // next time. nil means use the logical duration of the sub event 10) // number of repeats }) ) ////////////////////////////////////////////////////////////////////////// ( // nested time structures e = Env.new([0,1,0.2,0],[0.004, 0.2, 0.8], -2); play({ Cycle.ar([{ Spawn.ar({ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, FSinOsc.ar((i * 200) + 600, 0.1)); }, 1, 0.2, 4) + Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, PinkNoise.ar(0.1)); }, 1, 0.1, 8) }, 1, nil, 2) },{ Cycle.ar([{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, LFPulse.ar(1000 - (i * 200), 0.1, 0.1)); }, 1, 0.4, 4); },{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, BrownNoise.ar(0.2)); }, 1, 0.1, 8); }], 1, nil, 2) }], 1, nil, 2) })) ////////////////////////////////////////////////////////////////////////// ( // randomly spawning single events e = Env.new([0,1,0.2,0],[0.004, 0.2, 0.8], -2); Synth.play({ RandomEvent.ar([{ EnvGen.ar(e, FSinOsc.ar((6.rand * 200) + 600, 0.1)); },{ EnvGen.ar(e, PinkNoise.ar(0.1)); },{ EnvGen.ar(e, LFPulse.ar(600 + (6.rand * 200), 0.1, 0.1)); },{ EnvGen.ar(e, BrownNoise.ar(0.15)); }], 1, 0.2, nil) })) ////////////////////////////////////////////////////////////////////////// ( // spawning single events - mouse X controls which voice is spawned var e, mousex, mousey; mousex = MouseX.new(0,4); mousey = MouseY.new(0,4); e = Env.new([0,1,0.2,0],[0.004, 0.2, 0.8], -2); Synth.play({ SelectEvent.ar([{ EnvGen.ar(e, FSinOsc.ar((6.rand * 200) + 600, 0.1)); },{ EnvGen.ar(e, PinkNoise.ar(0.1)); },{ EnvGen.ar(e, LFPulse.ar(600 + (6.rand * 200), 0.1, 0.1)); },{ EnvGen.ar(e, BrownNoise.ar(0.15)); }], mousex, 1, 0.2, nil) }) ) ////////////////////////////////////////////////////////////////////////// ( // randomly spawning sub motives e = Env.new([0,1,0.2,0],[0.004, 0.2, 0.8], -2); Synth.play({ RandomEvent.ar([{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, FSinOsc.ar((i * 200) + 600, 0.1)); }, 1, 0.2, 4); },{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, PinkNoise.ar(0.2)); }, 1, 0.1, 8); },{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, LFPulse.ar(1000 - (i * 200), 0.1, 0.1)); }, 1, 0.4, 4); },{ Spawn.ar({ arg spawn, i, synth; EnvGen.ar(e, BrownNoise.ar(0.2)); }, 1, 0.1, 8); }], 1, nil, nil) })) ////////////////////////////////////////////////////////////////////////// ( // an orchestra and score player e = Env.new([0,1,0.2,0],[0.004, 0.2, 1], -2); Synth.play({ OrcScore.ar( // the orchestra [ { arg spawn, i, synth, deltaTime, instrumentNum, note, amp = 0.1; EnvGen.ar(e, FSinOsc.ar(note.midicps, amp)); }, { arg spawn, i, synth, deltaTime, instrumentNum, note, amp = 0.1; EnvGen.ar(e, LFPulse.ar(note.midicps, 0.1, amp)); }, { arg spawn, i, synth, deltaTime, instrumentNum, amp = 0.2; EnvGen.ar(e, BrownNoise.ar(amp)); } ], // the score #[ // deltaTime, instrumentNum, ... [0.1, 1, 60, 0.5], [0.1, 1, 62], [0.1, 1, 64], [0.1, 1, 65], [0.0, 0, 67], [0.0, 0, 71], [0.0, 0, 74], [0.4, 0, 79], [0.0, 0, 69], [0.0, 0, 72], [0.0, 0, 76], [0.4, 0, 81], [0.2, 2, 0.5], [0.2, 2], [0.4, 2], [0.4, 2], [0.4, 2], [0.4, 2, 0.5], [0.4, 2], [0.2, 2], [0.2, 2], [0.8, 2] ], 1, nil, 2) })) ////////////////////////////////////////////////////////////////////////// ( // an orchestra and score player with a dictionary as orchestra instead of an array. // the score is generated randomly and then repeated indefinitely e = Env.new([0,1,0.2,0],[0.004, 0.2, 0.5], -2, 2); Synth.play({ OrcScore.ar( // the orchestra IdentityDictionary[ // the right arrow operator -> defines an instance of Association 'sine' -> { arg spawn, i, synth, deltaTime, instrumentNum, note, dur, amp, pan; synth.releaseTime = dur; Pan2.ar(EnvGen.ar(e, FSinOsc.ar(note.midicps), 0, amp), pan); }, 'pulse' -> { arg spawn, i, synth, deltaTime, instrumentNum, note, dur, amp, pan; synth.releaseTime = dur; Pan2.ar(EnvGen.ar(e, LFPulse.ar(note.midicps, 0.1), 0, amp), pan); }, 'noise' -> { arg spawn, i, synth, deltaTime, instrumentNum, amp, pan; synth.releaseTime = 0.0; Pan2.ar(EnvGen.ar(e, PinkNoise.ar, 0, amp), pan); } ], // the score Array.fill(48, { [ { [[0.1, 0.2].choose, 'noise', 0.15.rand, 1.0.rand2] }, { [[0.1, 0.2].choose, 'pulse', 48+24.rand, 0.4.rand, 0.15.rand, 1.0.rand2] }, { [[0, 0.1, 0.2].choose, 'sine', 60+24.rand, 1.5.rand, 0.2.rand, 1.0.rand2] } ].choose.value; }) ++ [[3, 'rest']], // append a few seconds of rest 2, nil, nil) }) ) ////////////////////////////////////////////////////////////////////////// ( // another nested structure var e; e = Env.new([1, 1, 0],[3, 0.001]); // 3 second cut off envelope for bouncers Synth.play({ Cycle.ar([ { var n; n = 60; // n sines in each channel (twice as many during cross-fade) XFadeTexture.ar({ var z; z = [`[Array.fill(n, { 40 + 10000.0.linrand} ), nil, nil], `[Array.fill(n, { 40 + 10000.0.linrand} ), nil, nil] ]; Klang.ar(z, 1, 0, 0.04/n); }, 1, 3, 2, 4) }, { Spawn.ar({ Pan2.ar( // resonant filter bank simulates resonant modes of bouncing objects Klank.ar( `[ Array.fill(4, { 400 + 8000.0.rand }), // resonant freqs nil, Array.fill(4, { 0.01 + 0.1.rand }) // ring times ], // decays excite filter bank Decay.ar( // each impulse triggers a decay Impulse.ar( // impulses trigger decay envelope XLine.kr(5 + 2.0.rand2, 600, 4), // accellerating frequency XLine.kr(0.9, 0.00009, 4) // decaying impulse amplitude ), 0.001 // decay time - very short ) ), 1.0.rand2 // place each bouncer at a random position in the stereo field ) * // multiply by an envelope is necessary to make the sound end EnvGen.kr(e) }, 2, 1, 6) } ], 2, nil, 2) }) ) ////////////////////////////////////////////////////////////////////////// Tasks & Scheduling sched(timeFromNow, task) Schedules a task to be executed at a certain time. timeFromNow - a time in seconds. task - a function to be evaluated at the given time. The task function is passed the following arguments: synth - the Synth instance calling the task. now - the current logical time. task - the current task. Use this value if you want to reschedule the same task again. ( // change the frequency after 1 second. { arg synth; var freqCtl; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value synth.sched(1, { freqCtl.source = 1200; }); // schedule a task SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play ) ( // change the frequency after 1 second, then reschedule every 0.3 seconds. { arg synth; var freqCtl; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value synth.sched(1, { arg sameSynth, now, task; freqCtl.source = 1000 + 400.rand2; synth.sched(0.3, task); }); // schedule a task SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play ) repeat(start, period, task) Schedules a task to be repeated periodically. start - the time from now at which to call the task the first time. Start can be a function or anything else that responds to 'value' with an Integer or Float. period - a periodicity time in seconds. Period can be a function or anything else that responds to 'value' with an Integer or Float. task - a function to be evaluated each time. The task function is passed the following arguments: synth - the Synth instance calling the task. now - the current logical time. count - the number of times the task has been called. ( // repeat { arg synth; var freqCtl; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value synth.repeat(0, 0.125, { // schedule a task freqCtl.source = 700.rand + 500; // set a random frequency }); SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play ) ( // repeat at random intervals by using a closure { arg synth; var freqCtl; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value synth.repeat(0, { 1.0.rand }, { // schedule a task, period is random freqCtl.source = 700.rand + 500; // set a random frequency }); SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play ) repeatN(start, period, maxRepeats, task, completionFunc) Schedules a task to be repeated a finite number of times. start - the time from now at which to call the task the first time. Start can be a function or anything else that responds to 'value' with an Integer or Float. period - a periodicity time in seconds. Period can be a function or anything else that responds to 'value' with an Integer or Float. maxRepeats - number of times to repeat. task - a function to be evaluated each time. The task function is passed the following arguments: synth - the Synth instance calling the task. now - the current logical time. count - the number of times the task has been called. completionFunc - a function which is called after the scheduled duration after the last repeat. The completion function is passed the following arguments: synth - the Synth instance calling the task. now - the current logical time. ( // wait 2 seconds, then repeat 16 times at 0.125 second intervals. { arg synth; var freqCtl; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value synth.repeatN(2, 0.125, 16, // schedule a task { freqCtl.source = 700.rand + 500; }, // set a random frequency { freqCtl.source = 2000 } // upon completion ); SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play ) ( // then repeat 8 times at a random interval, then change the interval and continue. { arg synth; var freqCtl, task, compFunc; freqCtl = ControlIn.kr(800, 0); // use a ControlIn to change a value // define a task task = { freqCtl.source = 600.rand + 300; }; // set a random frequency // the function below, when executed, starts a repeating task. It schedules // itself to be called upon completion through the local variable 'compFunc'. // This is not recursion, because the completion function is called // from the scheduler, not from itself. compFunc = { synth.repeatN(0, 0.1 + 0.2.rand, 8, task, compFunc); }; compFunc.value; // start it SinOsc.ar(freqCtl, 0, 0.2); // return oscillator as output }.play )