Playing Sound#
Let us create the most simple sound possible: the sound of a sine wave.
First, we define a function that returns a so-called unit generator UGen that starts when we call play()
.
In fact play()
is shorthand for
transforming our UGen into a full SynthDef (synth definition),
adding it to the audio server and
executing it by generating a synth on it.
Protect your ears!
SC will not protect you from any wrongdoing. It will play the sound you defined, and if this sound can hurt your ears, you have to be sure to protect them. It is good practice to use headphones far away from your ears if you do not know what sound to expect!
There are hundreds of different UGens. Basically, they spit out real numbers over time. For example, SinOsc samples a sine wave.
~sine = {arg freq=200; SinOsc.ar(freq, mul: 0.2)};
~sineplay = ~sine.play();
If we execute this code, we get a warning that the server localhost
is not running.
We have to boot the real-time audio server scsynth first:
Server.local.boot; // boots the local server on your machine
//s.boot; // is equivalent
~sine = {arg freq=200; SinOsc.ar(freq, mul: 0.2)};
~sineplay = ~sine.play();
~sine
is a function that returns SinOsc.ar(freq, mul: 0.2)
which is a BinaryOpUGen.
Sound termination
To terminate all sound press CMD
+ .
. This might be the most important shortcut of all.
If we press CMD
+ i
while the curser is at play()
and we select the implementation for Function, we can see lookup what ~sine.play()
actually does:
play { arg target, outbus = 0, fadeTime = 0.02, addAction=\addToHead, args;
var def, synth, server, bytes, synthMsg;
target = target.asTarget;
server = target.server;
if(server.serverRunning.not) {
("server '" ++ server.name ++ "' not running.").warn; ^nil
};
def = this.asSynthDef(
fadeTime:fadeTime,
name: SystemSynthDefs.generateTempName
);
synth = Synth.basicNew(def.name, server);
// if notifications are enabled on the server,
// use the n_end signal to remove the temp synthdef
if(server.notified) {
OSCFunc({
server.sendMsg(\d_free, def.name);
}, '/n_end', server.addr, argTemplate: [synth.nodeID]).oneShot;
};
synthMsg = synth.newMsg(target, [\i_out, outbus, \out, outbus] ++ args, addAction);
def.doSend(server, synthMsg);
^synth
}
play()
constructs a new SynthDef, adds it to the server, and generates a synth which is returned.
The fadeTime
makes sure that the sound ramps up over a certain amount of seconds.
For example, we can increase fadeTime
:
~sineplay = ~sine.play(fadeTime: 2.0);
play
comes in handy if we wanna just try something out – if we want to explore sounds in a quick and dirty way.
For complex synth, we will define our own SynthDef.