I am trying to change the volume using Line.kr but I get this error: ERROR: can't set a control to a UGen
Here is the code:
a = {arg freq=440, vol=0; SinOsc.ar(freq)*vol}.play
a.set(\vol,Line.kr(0,1.0,3))
Any ideas?
I am trying to change the volume using Line.kr but I get this error: ERROR: can't set a control to a UGen
Here is the code:
a = {arg freq=440, vol=0; SinOsc.ar(freq)*vol}.play
a.set(\vol,Line.kr(0,1.0,3))
Any ideas?
This is actually such a basic issue/topic that a more elaborate answer is perhaps warranted. Basically, if you need/want "total flexibility" in what that \vol
envelope is, you have to read it from a (server-side) bus or use one of the many client-side wrapper tricks that hide that (bus) plumbing under some syntactic sugar. A typical example of the latter would be JITLib. An example using the latter:
a = Ndef(\a, {arg freq=440, vol=0; SinOsc.ar(freq)*vol}).play;
a.set(\vol, Ndef(\v, { Line.kr(0,1.0,3) }))
If you now do a.edit
you'll see somthing like
Without using that JITLib sugar, you'd have allocate and map a bus yourself, such as in:
a = {arg freq=440, vol=0; SinOsc.ar(freq)*vol}.play;
b = Bus.control(s, 1); // "s" is the default-bound server variable
a.map(\vol, b);
c = { Out.kr(b, Line.kr(0,1.0,3);) }.play;
With JITlib you can just set
all over as it has "smarts" to detect the argument type, but with the basic SC you need to distinguish between mapping and setting... although you can also set something to a c-led bus-number string to achieve the same effect (map
basically does that for you), i.e. the penultimate line above can be a.set(\vol, b.asMap);
Just b.asMap
evaluates to something like e.g. "c1", meaning control bus 1. (Audio busses use "a" prefixes instead, as you might expect.)
This bit may be somewhat more confusing, but keeping in mind that a
and ~a
are different types of variables (more or less function stack vs environment stack), the Ndef
keys (first Ndef
arguments) can be used "directly" in "shortcut" ~variables provided by the ProxySpace
as in
p = ProxySpace.push(s);
~a = {arg freq=440, vol=0; SinOsc.ar(freq)*vol};
~a.play; // play the NodeProxy, not the Function (Synth) directly
~a.set(\vol, ~v); // ~v is a NodeProxy.nil(localhost, nil) due to ProxySpace
~v = { Line.kr(0,1.0,3) };
Under the hood this last example practically auto-issues Ndef
s, i.e the 2nd line does the same as Ndef(\a ...
, so you don't have to type Ndefs
explicitly anymore. The way this works is that ProxySpace
replaces the currentEnvironment
(where ~variables live) with one in which put
, which is triggered by assignments to ~variables, is now creating or modifying Ndef
s and at
is accessing them, e.g. if you evaluate currentEnvironment
now it shows something like
ProxySpace ( ~a - ar(1) ~v - kr(1) )
(To get back to your prior environment issue a p.pop
now.)
You can't use UGen to set some arg of a SynthDef, but you can set the arguments of Line.kr:
a = {arg freq=440, vol=0; SinOsc.ar(freq)*Line.kr(atk,sus,rel)}.play
a.set(\atk,0,\sus,1,\rel,0)
please note that with Line.kr you can't restart the envelope. For a more specific control please see the EnvGen UGen: http://doc.sccode.org/Classes/EnvGen.html