Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Tutorials / JITLib / proxyspace_examples.schelp
blob264b89d860c43732beaed4f9bec7ec8874bb32e8
1 title:: ProxySpace examples
2 summary:: Some ProxySpace examples
3 categories:: Libraries>JITLib>Tutorials
4 related:: Overviews/JITLib, Classes/ProxySpace
6 section::main examples
8 subsection::preparing the environment
10 code::
12 s.boot;
13 p = ProxySpace.push(s);
17 subsection::playing and monitoring
19 code::
20 // play some output to the hardware busses, this could be any audio rate key.
21 ~out.play;
23 ~out = { SinOsc.ar([400, 408] * 0.8, 0, 0.2) };
26 // replacing the node. the crossfade envelope is created internally.
27 ~out = { SinOsc.ar([443, 600 - Rand(0,200)], 0, 0.2) };
28 ~out = { Resonz.ar(Saw.ar(40 + [0,0.2], 1), [1200, 1600], 0.1) + SinOsc.ar(60 * [1,1.1],0,0.2) };
29 ~out = { Pan2.ar(PinkNoise.ar(0.1), LFClipNoise.kr(2)) };
32 subsection::setting the node controls
34 code::
35 ~out = { arg rate = 2; Pan2.ar(PinkNoise.ar(0.1), LFClipNoise.kr(rate)) };
36 ~out.set(\rate, 30);
37 ~out = { arg rate = 2; Pan2.ar(Dust.ar(2000, 0.2), LFClipNoise.kr(rate)) };
38 ~out.set(\rate, 2);
41 subsection::referencing between proxies
43 code::
44 ~lfo = { LFNoise2.kr(30, 300, 500) };
45 ~out = { SinOsc.ar(~lfo.kr, 0, 0.15) };
46 ~out = { SinOsc.ar(~lfo.kr * [1, 1.2], 0, 0.1) * Pulse.ar(~lfo.kr * [0.1, 0.125], 0.5) };
47 ~lfo = { LFNoise1.kr(30, 40) + SinOsc.kr(0.1, 0, 200, 500) };
48 ~out = { SinOsc.ar(~lfo.kr * [1, 1.2], 0, 0.1) };
49 ~lfo = 410;
52 subsection::math
54 code::
55 // unary operators
56 ~lfo2 = { SinOsc.kr(0.5, 0, 600, 100) };
57 ~lfo = ~lfo2.abs;
58 ~lfo2 = { SinOsc.kr(1.3, 0, 600, 100) };
60 // binary operators
61 ~lfo3 = { LFTri.kr(0.5, 0, 80, 300) };
62 ~lfo = ~lfo2 + ~lfo3;
63 ~lfo = ~lfo3;
64 ~lfo = (~lfo3 / 50).sin * 200 + 500 * { LFTri.kr(~lfo.kr * 0.0015, 0, 0.1 * ~lfo3.kr / 90, 1) };
65 ~lfo3 = { Mix(~lfo2.kr * [1, 1.2]) };
67 currentEnvironment.free; // free all node proxies
68 ~out.stop; // free the playback synth.
71 subsection::waking up a network of proxies
73 code::
74 // hit cmd-. to stop all nodes
75 // start again
76 ~out.play;
79 subsection::feeding back
81 (one buffer size delay)
83 code::
84 ~out = { SinOsc.ar([220, 330], ~out.ar(2).reverse * LFNoise2.kr(0.5, 4pi), 0.4) };
86 // there is no immediacy: hear the buffer size cycle
87 ~out = { Impulse.ar(1 ! 2) + (~out.ar(2) * 0.99) };
91 // supercollider 'differential equations'
93 ~out = { SinOsc.ar(Slope.ar(~out.ar) * MouseX.kr(1000, 18000, 1)) * 0.1 + SinOsc.ar(100, 0, 0.1) };
96 ~out = { var z, zz;
97         z = Slope.ar(~out.ar);
98         zz = Slope.ar(z);
99         SinOsc.ar(Rand(300,410), z) *
100         SinOsc.ar(zz * 410)
101         * 0.1 + Decay2.ar(Pan2.ar(Dust.ar(600), MouseX.kr(-1,1)), 0.01, 0.05);
106 subsection::multiple control
108 code::
110 ~out = { arg freqOffest;
111         var ctl;
112         ctl = Control.names(\array).kr(Array.rand(8, 400, 1000));
113         Pan2.ar(Mix(SinOsc.ar(ctl + freqOffest, 0, 0.1 / 8)), LFNoise0.kr(2))
117 ~out.setn(\array, Array.exprand(8, 400, 2000));
118 ~out.set(\freqOffest, rrand(300,200));
119 ~out.map(\freqOffest, ~lfo);
121 // a simpler short form for this is:
123 ~out = { arg freqOffest=0, array = #[ 997, 777, 506, 553, 731, 891, 925, 580 ];
124         Pan2.ar(Mix(SinOsc.ar(array + freqOffest, 0, 0.1 / 8)), LFNoise0.kr(2))
129 subsection::mixing
131 code::
132 ~out1 = { SinOsc.ar(600, 0, 0.1) };
133 ~out2 = { SinOsc.ar(500, 0, 0.1) };
134 ~out3 = { SinOsc.ar(400, 0, 0.1) };
135 ~out = ~out2 + ~out1 + ~out3;
137 ~out = ~out1 + ~out2;
138 ~out = ~out1;
140 // another way is:
141 ~out = { SinOsc.ar(600, 0, 0.1) };
142 ~out.add({ SinOsc.ar(500, 0, 0.1) });
143 ~out.add({ SinOsc.ar(400, 0, 0.1) });
145 // or with direct access:
146 ~out[1] = { SinOsc.ar(500 * 1.2, 0, 0.1) };
147 ~out[2] = { SinOsc.ar(400 * 1.2, 0, 0.1) };
150 subsection::restoring / erasing
152 code::
153 ~out.free; // this frees the group, not the play synth x
154 ~out.send; // resends all synths
155 ~out.free;
156 ~out.send(nil, 1); // this sends at index 1 only
157 ~out.send;
159 // removing:
160 ~out.removeLast;
161 ~out.removeAt(0);
163 // cleaning up, freeing the bus:
164 ~out.clear; // this neutralizes the proxy, and frees its bus
167 for more on the proxy slots see: link::Tutorials/JITLib/jitlib_basic_concepts_03::
169 subsection::garbage collecting
171 code::
172 // often there are proxies playing that are not used anymore - this is good,
173 // because they might be used again at any time.
174 // this shows how to free unused proxies, such as ~out1, ~out2.
176 ~out.play;
177 ~out = { Pan2.ar(SinOsc.ar(~lfo.kr, 0, 0.2), sin(~lfo.kr / 10)) }; // ~lfo is kept, as its parents.
178 ~lfo = { LFNoise2.kr(3, 160, 400) };
180 p.keysValuesDo { arg key, proxy; [key, proxy.isPlaying].postln };
181 p.reduce; // all monitoring proxies (in this case ~out) are kept running.
182 // equivalent: p.reduce(to: [~out]);
183 p.keysValuesDo { arg key, proxy; [key, proxy.isPlaying].postln };
185 // to remove everything else:
186 p.postln;
187 p.clean; // all monitoring proxies (in this case ~out) are kept.
188 p.postln;
190 // after ~out is stopped, it is removed, too:
191 ~out.stop; // stop monitor
192 p.clean;
193 p.postln; // empty space.
196 subsection::execution order
198 code::
199 // you can .play .kr or .ar also a name that is not yet used.
200 // the rate is guessed as far as possible. on this topic see also: [the_lazy_proxy]
202 ~myOut.play; // play some key (audio rate is assumed)
204 // the rate is determined from the first access:
205 // like this ~lfo becomes control rate
207 ~myOut = { SinOsc.ar(~freq.kr * 2, 0, 0.1) };
208 ~freq = 900;
209 ~freq = { SinOsc.kr(115, 0, 70, 220) }
211 ~myOut = { SinOsc.ar(~otherFreq.ar * 2, 0, 0.1) };
212 ~otherFreq = { SinOsc.ar(115, 0, 70, 220) };
214 currentEnvironment.clear; // clear every proxy in this environment and remove them. (same: p.clear)
217 subsection::setting the xfade time
219 code::
220 ~out.play;
222 ~out.fadeTime = 4;
223 ~out = { SinOsc.ar(Rand(800, 300.0) * [1,1.1], 0, 0.1) };
224 ~out = { SinOsc.ar(Rand(800, 300.0) * [1,1.1], 0, 0.1) };
225 ~out.fadeTime = 0.01;
226 ~out = { SinOsc.ar(Rand(800, 300.0) * [1,1.1], 0, 0.1) };
227 ~out = { SinOsc.ar(Rand(800, 300.0) * [1,1.1], 0, 0.1) };
229 ~out.free(3);   // release the synths and the group with a given fadeTime without changing proxy time
230 ~out.stop;      // stop monitor
233 subsection::setting and mapping arguments
235 code::
236 ~out.play;
238 ~out = { arg freq=500, ffreq=120; SinOsc.ar(freq*[1,1.1], SinOsc.ar(ffreq, 0, pi), 0.2) };
239 ~out.set(\freq, 400 + 100.rand2);
240 ~out.set(\freq, 400 + 100.rand2);
241 ~out.set(\ffreq, 30 + 20.rand2);
242 ~out.unset(\freq, \ffreq);      // remove the setting
243 ~out.set(\ffreq, 30 + 10.rand2, \freq, 500 + 200.rand2);
246 // argument settings and mappings are applied to every new function
247 ~out = { arg freq=100, ffreq=20; SinOsc.ar(freq, SinOsc.ar(SinOsc.ar(ffreq)*ffreq, 0, pi), 0.2) };
249 // mapping to other proxies
250 ~lfo = { SinOsc.kr(0.3, 0, 80, 100) };
251 ~out.map(\ffreq, ~lfo);
253 ~out = { arg freq=300, ffreq=20; Pulse.ar(freq * [1, 1.1] + SinOsc.ar(ffreq, 0, freq), 0.3, 0.1) };
254 ~out = { arg freq=300, ffreq=20; BPF.ar(LFSaw.ar(ffreq * [1, 1.1], 0, 1), freq, 0.2) };
256 ~lfo = { FSinOsc.kr(0.3, 0, 30, 200) + FSinOsc.kr(10, 0, 10) };
257 ~out = { arg freq=300, ffreq=20; SinOsc.ar(freq*[1,1.1], SinOsc.ar(ffreq, 0, pi), 0.1) };
260 // crossfaded setting and mapping: fadeTime is used
261 ~out.fadeTime = 2;
262 ~out.xset(\freq, 9000);
263 ~out.xset(\freq, rrand(400, 700));
265 ~lfo = { FSinOsc.kr(0.1, 0, 30, 100) };
266 ~lfo2 = { LFClipNoise.kr(3, 100, 200) };
267 ~lfo3 = StreamKrDur(Pseq([Prand([530, 600],1), 700, 400, 800, 500].scramble, inf) / 3, 0.2);
269 ~out.xmap(\ffreq, ~lfo2);
270 ~out.xmap(\ffreq, ~lfo);
271 ~out.xmap(\ffreq, ~lfo3);
273 // argument rates: just like a synthdef has input 'rates' (like \ir or \tr), a nodeproxy control
274 // can be given a rate. this rate is used for each function passed into the proxy.
276 // trigger inputs
277 ~out = { arg trig, dt=1; Decay2.kr(trig, 0.01, dt) * Mix(SinOsc.ar(7000 * [1.2, 1.3, 0.2])) }
278 ~out.setRates(\trig, \tr);
280 // set the group, so the node proxy does not store the new value
281 ~out.group.set(\trig, 0.1, \dt, 0.1);
282 ~out.group.set(\trig, 0.4, \dt, 0.31);
283 ~out.group.set(\trig, 0.13, \dt, 2);
285 // lagging controls:
286 ~out.lag(\xfreq, 1); // equivalent to ~out.setRates(\xfreq, 1);
288 ~out = { arg trig, dt=1, xfreq=700;
289         Decay2.kr(trig, 0.01, dt) * Mix(SinOsc.ar(xfreq * [1.2, 1.3, 0.2]))
292 ~out.group.set(\trig, 0.1, \dt, 1, \xfreq, rrand(2000,9000));
293 ~out.group.set(\trig, 0.1, \dt, 0.5, \xfreq, rrand(2000,9000));
294 ~out.group.set(\trig, 0.1, \dt, 1, \xfreq, rrand(2000,9000));
296 // changing the lag, the synth is reconstructed with the new lag:
298 ~out.lag(\xfreq, 0.01);
299 ~out.group.set(\trig, 0.1, \dt, 1, \xfreq, rrand(2000,9000));
300 ~out.group.set(\trig, 0.1, \dt, 1, \xfreq, rrand(2000,9000));
301 ~out.group.set(\trig, 0.1, \dt, 1, \xfreq, rrand(2000,9000));
303 // removing the trig rate:
304 ~out.setRates(\trig, nil);
306 // note that the same works with the i_ and the t_ arguments, just as it does in SynthDef
309 section::other possible inputs
311 subsection::using a synthdef as input
313 for a more systematic overview see: link::Tutorials/JITLib/jitlib_fading::
315 code::
316 // you have the responsibility for the right number of channels and output rate
317 // you have to supply an 'out' argument so it can be mapped to the right channel.
319 ~out.play;
320 ~out = SynthDef("w", { arg out=0; Out.ar(out,SinOsc.ar([Rand(430, 600), 600], 0, 0.2)) });
321 ~out = SynthDef("w", { arg out=0; Out.ar(out,SinOsc.ar([Rand(430, 600), 500], 0, 0.2)) });
324 // if you supply a gate it fades in and out. evaluate this several times
326 ~out = SynthDef("w", { arg out=0, gate=1.0;
327         Out.ar(out,
328                 SinOsc.ar([Rand(430, 800), Rand(430, 800)], 0, 0.2)
329                         * EnvGen.kr(Env.asr(1,1,1), gate, doneAction:2)
330         )
331         });
334 // once the SynthDef is sent, it can be assigned by name.
335 // using this method, a gate argument should be
336 // provided that releases the synth. (doneAction:2)
337 // this is very efficient, as the def is on the server already.
339 // if the synth def is in the synthdesc lib (.add) its gate is detected.
342 SynthDef("staub", { arg out, gate=1;
343         Out.ar(out,
344                 Ringz.ar(Dust.ar(15), Rand(1, 3) * 3000*[1,1], 0.001)
345                         * EnvGen.kr(Env.asr, gate, doneAction:2)
346         )
347 }).add;
350 ~out = \staub;
354 // if you supply an envelope that frees itself, no bundle is sent to free it
356 ~out = SynthDef("w", { arg out, lfo, f0=430;
357         Out.ar(out,
358                 SinOsc.ar([Rand(f0, 800), Rand(f0, 800)]+lfo, 0, 0.2)
359                         * EnvGen.kr(Env.perc(0.01, 0.03), doneAction:2)
360         )
361         });
364 ~out.spawn;
365 ~out.spawn([\f0, 5000]);
366 fork { 5.do { ~out.spawn([\f0, 5000 + 1000.0.rand]); 0.1.wait; } }
369 // when the synth description in the SynthDescLib is found for the symbol,
370 // the proxy can determine whether to release or to free the synth.
371 // so if there is no 'gate' arg provided and the def has a desc, the synth is
372 // freed and not released.
375 SynthDef("staub", { arg out;
376         Out.ar(out, Ringz.ar(WhiteNoise.ar(0.01), 1000 * [1,1], 0.001))
377 }).add; // store the synth def so it is added to the SynthDescLib
381 ~out = \staub;
382 ~out = \staub;  // watching the synth count shows that the old synth is freed.
383 ~out = 0;       // now out plays continuous stream of zero.
384 ~out = nil;     // removes object and stops it.
387 subsection::using patterns
389 code::
390 // example
393 SynthDef(\who, { arg amp=0.1, freq=440, detune=0, gate=1, out=0, ffreq=800;
394         var env;
395         env = Env.asr(0.01, amp, 0.5);
396         Out.ar(out, Pan2.ar(
397                 Formant.ar(freq + detune, ffreq, 30, EnvGen.kr(env, gate, doneAction:2)), Rand(-1.0, 1.0))
398         )
399 }).add;
403 ~out.play;
406 ~out = Pbind(\instrument, \who, \freq, [600, 601], \ffreq, 800, \legato, 0.02);
409 // embed a control node proxy into an event pattern:
410 // this does not work for indirect assignment as \degree, \midinote, etc.,
411 // because there is calculations in the event! if needed, these can be done in the SynthDef.
413 ~lfo = { SinOsc.kr(2, 0, 400, 700) };
414 ~out = Pbind(\instrument, \who, \freq, 500, \ffreq, ~lfo, \legato, 0.02);
416 ~lfo = { SinOsc.kr(SinOsc.kr(0.2, Rand(0,pi), 10, 10), 0, 400, 700) };
418 ~lfo = { LFNoise1.kr(5, 1300, 1500) };
419 ~lfo = { MouseX.kr(100, 5500, 1) };
422 ~out = Pbind(
423                 \instrument, \who,
424                 \freq, Pseq([500, 380, 300],inf),
425                 \legato, 0.1,
426                 \ffreq, Pseq([~lfo, 100, ~lfo, 100, 300, 550], inf), // use it in a pattern
427                 \dur, Pseq([1, 0.5, 0.75, 0.125]*0.4, inf)
428         );
431 // note that when you use a proxy within a non-event pattern it gets embedded as an object,
432 // so this functionality is still standard
434 // works only with control rate proxies. multichannel control rate proxies cause
435 // multichannel expansion of the events:
437 ~lfoStereo = { LFNoise1.kr([1, 1], 1300, 1500) }; // 2 channel control rate proxy
438 ~out = Pbind(\instrument, \who, \ffreq, ~lfoStereo, \legato, 0.02).trace;
439 ~lfoStereo = { [MouseX.kr(100, 15500, 1), SinOsc.kr(SinOsc.kr(0.2, 0, 10, 10), 0, 400, 700)] }
441 // btw: setting the clock will cause the pattern to sync:
442 p.clock = TempoClock.default;
443 p.clock.tempo = 2.0;
444 p.clock.tempo = 1.0
447 // patterns also crossfade, if an \amp arg is defined in the synthdef:
448 // (evaluate a couple of times)
449 ~out.fadeTime = 3.0;
451 ~out = Pbind(
452                 \instrument, \who,
453                 \freq, Pshuf([500, 380, 200, 510, 390, 300, 300],inf) * rrand(1.0, 2.0),
454                 \legato, 0.1,
455                 \ffreq, Pshuf([~lfo, 100, ~lfo, 100, 300, 550], inf),
456                 \dur, 0.125 * [1, 2, 3, 2/3].choose
457         );
461 subsection::using instruments and players
463 note::
464 for the following to work you will need to have the strong::cruciallib:: quark installed.
467 code::
468 // pause and resume do not work yet.
471 // store an instrument
473 Instr(\test,
474         { arg dens=520, ffreq=7000; Ringz.ar(Dust.ar(dens, [1,1] * 0.1), ffreq, 0.02) }
475         );
478 ~out = Patch(\test, [10, rrand(5000, 8000)]);
479 ~out.fadeTime = 3;
483 ~out = InstrSpawner({ arg freq=1900,env,pan;
484         Pan2.ar(SinOsc.ar(freq, 0.5pi, 0.3) * EnvGen.kr(env, doneAction: 2), pan)
486         Prand([1500, 700, 800, 3000] + 170.rand2, inf),
487         Env.perc(0.002,0.01),
488         Prand([-1,1],inf)
489 ],0.125)
492 ~out.clear;
496 // does not work (yet).
497 //~out.set(\dens, 120);
498 //~out.xset(\dens, 1030);
499 //~out.unmap(\ffreq);
500 //~out.set(\ffreq, 500);
503 section::client side routines
505 subsection::spawning
507 code::
508 ~out.play;
509 ~out.awake = false; // allow sound object assignment without immediate sending
511 // putting an synthdef into the node proxy without playing it right away
512 // the synthdef has an envelope that frees by itself.
514 ~out = SynthDef("a", { arg out=0, freq=800, pmf=1.0, pan;
515                 var env, u;
516                 env = EnvGen.kr(Env.perc(0.001, 0.04, 0.4),doneAction:2); // envelope
517                 u = SinOsc.ar(freq * Rand(0.9, 1.1), SinOsc.ar(pmf, 0, pi), env);
518                 Out.ar(out, Pan2.ar(u, pan))
519         })
523 // create a task to repeatedly send grains
525 t = Task.new({
526         loop({
527                 // starts a synth with the current synthdef at index 0
528                 ~out.spawn([\pmf, [1, 20, 300].choose, \pan, [0, -1, 1].choose]);
529                 [0.1, 0.01, 0.25].choose.wait;
530         })
534 t.start;
535 t.stop;
536 t.start;
538 // note: if you want to avoid using interpreter variables (single letter, like "t"),
539 // you can use Tdef for this. (see Tdef.help)
541 // set some argument
542 ~out.set(\freq, 300);
543 ~out.set(\freq, 600);
544 ~out.map(\freq, ~lfo);
545 ~lfo = { SinOsc.kr(0.1, 0, 3000, 4000) };
546 ~lfo = { SinOsc.kr(0.1, 0, 600, 700) };
547 ~lfo.add({ Trig.kr(Dust.kr(1), 0.1) * 3000 });
548 ~lfo = 300;
550 // change the definition while going along
552 ~out = SynthDef("a", { arg out, freq=800;
553                 var env;
554                 env = EnvGen.kr(Env.perc(0.01, 0.1, 0.3),doneAction:2);
555                 Out.ar(out, Pulse.ar(freq * Rand([0.9,0.9], 1.1), 0.5, env) )
556         });
560 t.stop;
561 ~out.awake = true; // don't forget this
562 // free all synths in this current ProxySpace
563 currentEnvironment.clear;
566 subsection::granular synthesis: efficient code
568 see also link::Tutorials/JITLib/jitlib_efficiency::
570 code::
571 ~out.play;
574 SynthDef("grain", { arg i_out = 0, pan;
575         var env;
576         env = EnvGen.kr(Env.perc(0.001, 0.003, 0.2),doneAction:2);
577         Out.ar(i_out, Pan2.ar(FSinOsc.ar(Rand(1000,10000)), pan) * env)
578 }).send(s);
581 // a target for the grains
582 ~someInput.ar(2); // initialize to 2 channels audio
583 ~out = ~someInput;
586 t = Task({
587         loop({
588                 s.sendMsg("/s_new","grain",-1,0,0,
589                         \i_out, ~someInput.index, // returns the bus index of the proxy
590                         \pan, [1, 1, -1].choose * 0.2
591                 );
592                 [0.01, 0.02].choose.wait;
593         })
596 t.play;
598 // different filters;
600 ~out.fadeTime = 1.0;
602 ~out = { BPF.ar(~someInput.ar, MouseX.kr(100, 18000, 1), 0.1) };
604 ~out = { CombL.ar(~someInput.ar * (LFNoise0.ar(2) > 0), 0.2, 0.2, MouseX.kr(0.1, 5, 1)) };
606 ~out = { RLPF.ar(~someInput.ar, LFNoise1.kr(3, 1000, 1040), 0.05) };
609 t.stop;
612 // end
614 ~out.stop;
615 currentEnvironment.clear;
616 ProxySpace.pop; // restore original environment
619 subsection::using multiple proxyspaces
621 can be done while the server is not running: with p.wakeUp or p.play
623 the environment can be played back.
625 code::
626 // quit server:
628 s.quit;
631 // create two proxyspaces without a running server
633 p = ProxySpace(s);
634 q = ProxySpace(s);
636 p.use({
637         ~out = { Resonz.ar(~in.ar, ~freq.kr, 0.01) };
638         ~in = { WhiteNoise.ar(0.5) };
639         ~freq = { LFNoise2.kr(1, 1000, 2000) };
642 q.use({
643         ~in = { Dust.ar(20, 0.1) };
644         ~out = { Resonz.ar(~in.ar * 450, ~freq.kr, 0.005) };
645         ~freq = { LFNoise2.kr(1, 400, 2000) };
649 // wait for the booted server
650 s.boot;
652 // play the proxy at \out
653 p.play(\out);
654 q.play; // out is the default output
657 subsection::external access
659 code::
660 q[\in][1] = { Impulse.ar(2, 0, 0.5) }; // adding a synth at index 1
662 // equivalent to
663 q.at(\in).put(1, { Impulse.ar(7, 0, 0.5) });
666 subsection::connecting two spaces
668 (must be on one server)
670 code::
672 q.use({
673         ~freq = 100 + p[\freq] / 2;
678 subsection::recording output
680 (see also: link::Classes/RecNodeProxy::)
682 code::
683 r = p.record(\out, "proxySpace.aiff");
685 // start recording
686 r.unpause;
688 // pause recording
689 r.pause;
691 // stop recording
692 r.close;
695 subsection::push/pop
697 code::
698 // make p the currentEnvironment
699 p.push;
701 ~freq = 700;
702 ~freq = 400;
703 ~freq = { p.kr(\freq) + LFNoise1.kr(1, 200, 300) % 400 }; // feedback
704 ~freq = 400;
706 p.pop; // restore environment
709 // make y the currentEnvironment
710 q.push;
712 ~freq = 1000;
713 ~in = { WhiteNoise.ar(0.01) };
715 q.pop; // restore environment
717 q.clear;
718 p.clear;
721 section::some more topics
723 subsection::nodeproxy with numbers as input
725 code::
726 p = ProxySpace.push(s.boot);
729 ~out = { SinOsc.ar(~a.kr * Rand(1, 2), 0, 0.1) };
730 ~out.play;
732 ~a = 900;
734 // these add up:
735 ~a[0] = 440;
736 ~a[1] = 220;
737 ~a[2] = 20;
739 ~a.fadeTime = 2;
741 ~a[0] = 300; // now there is a crossfade.
742 ~a[1] = { SinOsc.kr(5, 0, 20) };
743 ~a[2] = { SinOsc.kr(30, 0, 145) };
747 // internally a numerical input is approximately replaced by:
748 // (pseudocode)
749 SynthDef("name", { arg out, fadeTime;
750         Out.kr(out,
751                 Control.kr(Array.fill(proxy.numChannels, { the number }))
752                         * EnvGate.new(fadeTime:fadeTime)
753         )