Product SiteDocumentation Site

11.3.10.9. Things to Do with a SynthDef: Set and Free

Once you send a synth definition to the server, and make some synths, you've collected a few Synth Objects, and you wonder what to do with them next. Of course, you could listen to them, but you can also change the arguments that you used, and stop it.
To change the arguments used by a synth, send it the "set" message, with a list of arguments:
variableHoldingSynth.set( [\argument1,value,\argument2,value,...] );
This helps to save even more time and memory: rather than destroying and creating synths all the time, you can simply change pre-existing ones.
This modification of the ten-pseudo-random-tones example includes an extra line that lets you change the tones without destroying and re-creating the synths.
// run this first
h = List.new;

// run this second
(
   var myRandFunc =
   {
      arg frequency = 440;
      Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
   };

   SynthDef.new( \myRandFunc, myRandFunc ).send( s );
)

// run this third
10.do( { h.add( Synth.new( \myRandFunc, [\frequency,(440.rand + 440)] ) ); } );

// run this fourth, as many times as you please
h.do( { arg item; item.set( \frequency, (440.rand + 440) ); } );
The reason that you have to run each of those segments separately is two-fold: we need to store the List of Synth's in a single-letter variable because, for this simple demonstration, this is the most efficient way; second, for the asynchronous behaviour of the server that was previously noted as causing an error.
The only aspect of that example that's a little tricky to understand is the "do" loop. Remember that when you run a "do" loop on a List, the interpreter automatically loops over each of the elements in the List, running the Function that you provide. Each time the Function is run, it receives the current List item, and its index number in the List, in that order. So the Function in this loop simply uses "set" to change the "frequency" argument.
Take special note that the arguments in this case are not identical to those given with the "new" message. Compare the two forms below:
SynthDef.new( \SynthName, [\parameter1,value,\parameter2,value] );
and
existingSynth.set( \parameter1, value, \parmeter2, value );
To get rid of one synth without stopping all sound, send its corresponding Synth the "free" message:
variableHoldingSynth.free;
This stops the synth and frees the associated memory - on the server. Your Synth Object still exists in the interpreter, but you can't use it any more. A Synth Object represents a synth on the server; since you got rid of the synth on the server, the Synth Object represents something that doesn't exist. If you attempt to send the "free" message again, you'll get an error. For this reason, it's a good idea to get rid of the Synth Object at the same time:
<replaceable>variableHoldingSynth</replaceable>.free;
<replaceable>variableHoldingSynth</replaceable> = nil;
If you accidentally send "free" to an already-freed Synth, the interpreter will cause an error, and program execution will stop. If you accidentally send "free" to a variable set to "nil", nothing will happen. Proactively avoiding mistakes like this is good programming practice.