{ SinOsc.ar( freq:SinOsc.kr( freq:1, add:500, mul:10 ), mul:0.2 ); }.play;What happens if the server calculates the audio-rate UGen first? It wouldn't have a frequency. This is another one of those things which the interpreter takes care of automatically when we run Function rather than create a Synth. Since it's often preferable to use a synth instead of a Function, we need some way to control the order of execution. The interpreter and the server are only so good at guessing what we need, after all.
Synth
Class that we can use to inform the server about our desired order of execution: "before" and "after". They represent a small extension to the "new" method, and they work like this: Synth.before(
variableHoldingSynth, nameOfSynthDef, ListOfArguments)
;
Synth.after(
variableHoldingSynth, nameOfSynthDef, ListOfArguments)
;
( // execute first: prepare the server var busAudioSynth = { arg bus, freqOffset = 0; Out.ar( 0, SinOsc.ar( freq:( In.kr(bus) + freqOffset ), mul:0.1 ) ); }; var busControlSynth = { arg bus, freq = 400; Out.kr( bus, SinOsc.kr( freq:1, mul:( freq/40 ), add:freq ) ); }; SynthDef( \tutorialAudioBus, busAudioSynth ).send( s ); SynthDef( \tutorialControlBus, busControlSynth ).send( s ); b = Bus.control( s ); ) ( // execute second: create synths x = Synth.new( \tutorialControlBus, [\bus, b] ); // control synth y = Synth.after( x, \tutorialAudioBus, [\bus, b] ); // low audio synth z = Synth.after( x, \tutorialAudioBus, [\bus, b, \freqOffset, 200] ); // high audio synth ) ( // commands to free each Object x.free; x = nil; // control synth y.free; y = nil; // low audio synth z.free; z = nil; // high audio synth b.free; b = nil; // control bus )In this case, the control-rate synth is created before the audio-rate synths - probably the easier way to think about it. Even so, it's possible to add them in the opposite order with a little extra thought.