some placeholders in supercollider 1
this helpfile explains some basic concepts of interactive programming
with supercollider and proxy space.
previous: JITLib next: jitlib_basic_concepts_02
a) What is a proxy?
A proxy is a place holder that is often used to operate on something that does not yet exist.
For example, an OutputProxy is used to represent multiple outputs of a ugen, even if only
one ugen is created eventually.
Any object can have proxy behaviour (it may delegate function calls to different objects for example)
but specially functions and references can be used as operands while they keep their
referential quality.
see also: OutputProxy Function Ref
using a Ref as a proxy:
// reference example
// create a new Ref object
y = `(nil);
// you can start to calcuate with y, even if its value is not yet given:
z = y + 10; // returns a function
// now the source can be set:
y.value = 34;
// the function z can be evaluated now.
z.value
// the same without a reference does not work:
y = nil; // empty y first
z = y + 10; // this fails.
// also an array does not provide this referentiality:
y = [nil]; // array with nil as element
z = y + 10; // this fails.
// an environment without sufficient defaults has the same problem:
currentEnvironment.postln; // anEnvironment
~x; // access the enironment: there is nothing stored: nil
~x = 9; // store something
~x; // now 9 is stored
~x + 100; // calculate with it
currentEnvironment.postln; // the value is stored in the environment
~y + ~x; // cause an error: ~y is nil.
~y = -90; // set ~y
~y + ~x; // this works.
using a Function as a proxy:
// a function can serve the same purpose
y = nil; // empty y first
z = { y } + 10; // this does not fail, instead it creates a new function, which
// does not fail when evaluating it after y is set to 34.
y = 34;
z.value;
see also client side proxies like Tdef Pdefn Pdef Fdef
b) NodeProxy
For interactive programming it can be useful to be able to use something before it is there - it makes evaluation order more flexible and allows to postpone decisions to a later moment. Some preparations have to be done usually - like above, a reference has to be created. In other situations this sort of preparation is not enough, for example if one wants to do maths with running processes on the server.
Audio output on the server has mainly two properties - a calculation rate (audio or control) and a certain number of channels. These are the main static properties of a node proxy, which cannot be changed while it is in use.
// boot the server
s.boot;
// two proxies on a server. calculation rate is audio rate, number of channels is 2
y = NodeProxy.audio(s, 2);
z = NodeProxy.audio(s, 2);
// use them in calculation
z.play;
z.source = y.sin * 0.2;
// set its source now.
y.source = { Saw.ar([300, 301], 4*pi) };
// the source can be of various type, one of them would be a number:
y.source = 0.0;
// post the source
y.source;
// end them, free their bus number
y.clear;
z.clear;
In order to provide a simple way of creating node proxies, a proxy space can be used.
So the above reads like this:
p = ProxySpace.push(s.boot); // store proxy space in p so it can be accessed easily.
~z.play;
~z = ~y.sin * 0.2;
~y = { Saw.ar([300, 301], 4*pi) };
// clear the space (all proxies)
p.clear;
// move out of the proxyspace.
p.pop;
further readings: NodeProxy ProxySpace Ndef
next: jitlib_basic_concepts_02