Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Tutorials / JITLib / jitlib_basic_concepts_02.schelp
blobbb5fdfeaae539a22f4c6c8789234b26b35cd6536
1 title:: jitlib_basic_concepts_02
2 summary:: proxy space - basic concepts
3 categories:: Libraries>JITLib>Tutorials
4 related:: Overviews/JITLib, Tutorials/JITLib/jitlib_basic_concepts_01, Tutorials/JITLib/jitlib_basic_concepts_03
6 external structure of the node proxy, referencing in proxyspace and environments.
8 This document covers:
10 list::
11 ## link::#a)_normal_environment_lookup#a) normal environment lookup::
12 ## link::#b)_a_proxyspace_as_an_environment#b) a proxyspace as an environment::
13 ## link::#c)_using_the_proxyspace_to_change_processes_on_the_fly#c) using the proxyspace to change processes on the fly::
14 ## link::#d)_when_are_the_node_proxies_initialized?#d) when are the node proxies initialized?::
15 ## link::#e)_moving_out_of_the_proxy_space#e) moving out of the proxy space::
16 ## link::#f)_using_ProxySpace_together_with_other_Environments#f) using ProxySpace together with other Environments::
19 section::a) normal environment lookup
21 code::
22 currentEnvironment.postln; // anEnvironment (if not, you haven't left it from last helppage..)
24 ~a; // access the environment: there is nothing stored: nil
25 ~a = 9; // store something
26 ~a;     // now 9 is stored
27 ~a + 100; // calculate with it
29 currentEnvironment.postln; // the value is stored in the environment
31 ~b + ~a; // cause an error: ~b is nil.
32 ~b = -90; // set ~b
34 ~b + ~a; // now this works.
36 // note that you can always access environments (or ProxySpaces) from outside as well:
38 x = currentEnvironment;
39 x[\a] + x[\b] // equivalent to ~b + ~a
41 // or, if "know" is true, you can access named things with message-like syntax:
42 x.know = true;
43 x.a + x.b;
46 further readings: link::Classes/Environment::
48 section::b) a proxyspace as an environment
50 one can replace the current environment with a special type of environment, a ProxySpace. this environment represents processes that play audio on a server.
52 code::
53 p = ProxySpace.new(s);  // create a new environment, store it in variable p for now.
54 p.push;                 // push it, so i becomes the current environment.
55 currentEnvironment.postln;
56 currentEnvironment === p; // and they are identical.
58 ~x;             // accessing creates a NodeProxy (uninitialized) automatically.
59 ~x + ~y;        // this works immediately, because the lookup does not return nil,
60                 // but a placeholder (proxy) instead
62 p.postln;       // now there are two empty placeholders in the environment.
65 section::c) using the proxyspace to change processes on the fly
67 code::
68 // boot the server
69 s.boot;
72 // as soon as a sound function (or any compatible input) is assigned to a proxy
73 // this sound plays on its own private bus (so it is not audible yet.)
75 ~x = {
76         RLPF.ar(Impulse.ar(4) * 20, [850, 950], 0.2)
80 // the proxy has been initialized by its first assignment.
81 // it plays at audio rate (because we have assigned an audio rate ugen function)
82 // and it has two channels (because the function has stereo output)
84 ~x.index;       // a nodeproxy owns a private bus, so its signal can be used in diverse ways.
85                 // what is the proxy bus's index? this posts the index to the postwindow
86                 // before it was .ir(nil), now it is initialized to .ar(2)
88 ~x.bus // what is the proxy's bus?
91 ~x.play;        // now listen to it. a monitor is created (see Monitor) that plays the signal
92                 // onto a public bus - by default, this is bus 0, the first audio output bus.
93                 // This monitoring function is independent of the proxy itself.
94                 // for further info see: jitlib_basic_concepts_03 (part c)
98 // the sound function can be changed at any time:
100 ~x = {
101         RLPF.ar(Impulse.ar([5, 7]) * 5, [1450, 1234], 0.2)
105 // You can tune a sound function to your liking very easily
106 // by replacing it with little (or big) variations:
108                 // filter freqs higher:
109 ~x = {  RLPF.ar(Impulse.ar([5, 7]) * 5, [1800, 2000], 0.2) }
111                 // same pulse ratio (5/8), different pulse tempo:
112 ~x = {  RLPF.ar(Impulse.ar([5, 8] * 3.2) * 5, [1800, 2000], 0.2) }
114                 // different filter:
115 ~x = {  Ringz.ar(Impulse.ar([5, 8] * 3.2), [1800, 2000], 0.05) }
117 // and if you set the proxy's fadeTime, you can create little
118 // textures by hand:
120 ~x.fadeTime = 3;
121                 // different filter freqs every time:
122 ~x = {  Ringz.ar(Impulse.ar([5, 8] * rrand(0.5, 1.5)) * 0.5, ({ exprand(200, 4000) } ! 2), 0.05) }
126 // here is another proxy:
127 ~y = { Pan2.ar(Dust.ar(20), 0) };
129 ~y.bus; // it has two channels, just as the ~x., but it plays on another (private) bus.
131 // note that ~y is not audible directly,
132 // but it can be used like a UGen in any other proxy:
134 ~x = {
135         RLPF.ar(~y.ar * 8, [1450, 1234], 0.2)
139 // when the proxy changes, the result changes dynamically:
141 ~y = { Impulse.ar(MouseX.kr(2, 18, 1)) * [1, 1] };
143 ~y = { PinkNoise.ar(MouseX.kr(0, 0.2) * [1, 1]) };
145 ~y = { Impulse.ar([MouseX.kr(2, 18, 1), MouseY.kr(2, 18, 1)]) };
149 // stop listening. the proxies run in the background.
151 ~x.stop;
153 ~y.bus; // ~y is playing on a different bus ...
154 ~x.bus; // than ~x.
156 // we can also listen to ~y directly:
157 ~y.play;
159 // to remove a proxy source, nil can be used:
161 ~y = nil;
163 // stop listening
164 ~y.stop;
167 further readings: link::Tutorials/JITLib/proxyspace_examples::, link::Classes/Bus::, link::Classes/AbstractFunction::
169 section::d) when are the node proxies initialized?
171 bus initialization of a node proxy happens as soon as it is used for the first time. later inputs are adjusted to this bus, as far as it is possible.
173 code::
174 ~z2 = { LFNoise0.kr([1, 2, 3, 4]) }; // a four channel control rate proxy
175 ~z2.bus.postln;
177 ~z100 = 0.5;    // a constant value creates a single channel control rate proxy.
178 ~z100.bus.postln;
180 ~z34.ar(3)              // the first access (with a numChannels argument) allocates the bus
181 ~z34.bus.postln;        // a 3 channel audio proxy
183 // these initializations can be removed by using clear:
184 ~z34.clear;
185 ~z34.bus.postln;
188 This initialisation happens whenever the proxy is first used. Later, the proxy can be accessed with other rate/numChannels combinations as needed (rates are converted,
189 numChannels are extended by wrapping, sources with too many channels are wrapped).
191 Note that this might cause ambiguous initialisation in which case the proxy should
192 be always initialized first. A typical problem is demonstrated here:
194 code::
195 ~u.play(0, 2);  // initialize 2 audio channels (default). 0 is the output bus number.
196                 // if the proxy is not inititialized, play defaults to 2 channels.
197                 // here it is explicitly given only to make it more clear.
198 ~u = { PinkNoise.ar(0.2) }; // use only one
199 ~u.numChannels; // 2 channels
200 ~u.clear;
203 if evaluated the other way round, only one channel is used:
205 code::
206 ~u = { PinkNoise.ar(0.2) };     // initialize 1 audio channel
207 ~u.play(0, 2);                  // play 2 channels: the 1 channel is expanded into 2.
208                                 // numChannels of .play defaults to the proxy's numChannels.
209                                 // here it is explicitly given, so to expand the channels
210 ~u.numChannels; // 1 channel
211 ~u.clear;
214 Thus it can be useful to explicitly initialize proxies that use variable type inputs:
216 code::
217 ~b.kr(8); ~c.ar;        // explicit initialisation
218 p.postln;               // post the whole proxy space
221 section::e) moving out of the proxy space
223 code::
224 // play the audio:
225 ~x.play;
227 ~x = { PinkNoise.ar(0.5) };
229 // p is the proxy space:
230 p.postln;
232 // to end all processes in p, use end:
233 p.end(2) // 2 seconds fade out.
235 // to remove all bus objects and free them from the bus allocato, use clear:
236 p.clear;
238 currentEnvironment.postln;
240 // restore original environment:
242 p.pop;
244 currentEnvironment.postln;
246 ~a + ~b; // the old values are still here.
248 p === currentEnvironment; // this is not the case anymore.
250 // remove the content, so the garbage collector can release their memory.
251 p.clear;
253 // note that if you use this kind of accessing scheme, the objects are not garbage collected
254 // until the keys are set to nil. This is a common mistake when using normal environments.
256 // clear all in the normal environment:
258 currentEnvironment.clear;
261 section::f) using ProxySpace together with other Environments
263 using proxy space as an access scheme for node proxies can get in the way of the normal use of environments as pseudo variables. Here are some ways to cope with this.
265 code::
266 //////////////  EnvirDocument is currently unavailable ////////////
267 //// if you want to keep using the current environment as usual, you can restrict the
268 //// scope of proxyspace to one document (note: this is mac-only currently)
270 //EnvirDocument(p, "proxyspace");       // to test this, check for currentEnvironment here
271 //                                      // and in the envir document.
273 // you can also access the proxy space and the proxies in it indirectly:
274 p[\x].play;
275 p[\x] = { SinOsc.ar(450, 0, 0.1) };
277 // or: when the proxyspace is pushed, you can use a normal environment indirectly:
278 p.push;
279 d = ();
280 d[\buffer1] = Buffer.alloc(s, 1024);
281 d.use { ~buffer1.postln; ~zz = 81; }; // for more than one access to the environment, use .use
284 // to access the inner environment of proxy space directly,
285 // e.g. to check whether a proxy exists, one can use .envir:
287 p.envir.postln;
288 p.envir[\x].postln;     // a proxy with this name exists
289 p.envir[\nono].postln;  // there is no proxy with this name.
291 // p[\nono].postln;     // this access would have created a new proxy called \nono.
294 previous: link::Tutorials/JITLib/jitlib_basic_concepts_01:: next: link::Tutorials/JITLib/jitlib_basic_concepts_03::