Saturday, May 22, 2010

SynthDefs

Last time, I promised we would cover sound-making. First, make sure to boot the localhost server. The localhost server is one of the two small gray boxes at the bottom left of your screen. Press the “Boot” button. When it's booted, the window will say "running" in it and the "Boot" button will turn green and change to say "Quit."

Then, select this code and press enter (not return!). You can select it by double-clicking to the right of the open parenthesis.

 (

  var syn, sound;

  syn = SynthDef.new("example1", {
   Out.ar(0, SinOsc.ar(440));
  });
 
  syn.load(s);

  sound = Synth.new("example1");
 )

When you want to stop the program, press apple-period.

What's going on here? Our program first declares a variable, and then it defines a SynthDef and loads it on the server, then creates a Synth object that plays the sound. This is a complicated example, but I wanted to get you making sounds as soon as possible. Let's look at the example line by line.

The first line is var syn, sound; We are declaring two variables. One is called syn and the other is called sound.

The next line, translated into English, means "I want to create a new SynthDef called 'example1' and store it in the variable syn." Whoa, what's a SynthDef? The SynthDef help file told me that a SynthDef is a "definition of a synth architecture." I got to the help file by highlighting the word SynthDef and pressing apple-d. When I see a term like that, which I don't understand, I can always get help by highlighting it and typing apple-d.

Recall that SuperCollider is not just one program; it is two. One part of the program is the interpreter, which is what we've been talking about so far. The other part of the program is audio server, which is what actually makes the sound. It does not know anything but what it needs to know. This makes it run much faster and more efficiently. You can tell it to make certain kinds of sounds, but in order to run quickly, it wants to know what kinds of sounds you want before you actually make them. You write a description of what you want the server to do. This description, or definition, is called a SynthDef.

When we run SynthDef.new, we get back a new SynthDef, which we're stroing in the variable named syn. Inside the parenthesis are some arguments. SynthDef is the class. new is the message. And "example1" and the stuff in between the curly brackets are the two arguments.

The stuff in the curly brackets is telling the SynthDef what to play. Things between curly brackets {} are called functions. A function is a special type of object that is made up of a code block that you can run. We'll come back to this later.

Out is a UGen. The help file for UGens says, "A UGen or unit generator is an object for generating or processing audio or control signals." UGens exist in SynthDefs. They are what make up a SynthDef. Out is a UGen that writes a signal to a bus, which, in this case, sends it's output to the left channel. .ar is a type of constructor. So Out.ar creates a new instance of a an Out UGen running at the audio rate. ar stands for "audio rate" and is a common constructor name for UGens.

Looking at the arguments to Out.ar, 0 means left channel. If that were a 1, it would mean right channel. And the next thing is what gets sent out, which is a sine tone generator. The argument to SinOsc.ar, 440, is the frequency to play. So SinOsc.ar(440) creates a sine wave at 440 Hz. Out.ar takes that sine wave and sends it out to the left channel, which is channel 0.

The next line, is a closing curly bracket, a close paren and a semicolon. It's the end of the function, the end of the SynthDef and the end of a statement. We've created a new SynthDef that includes in it a function describing what the SynthDef should do when it gets instantiated.

The next line says, take that SynthDef and load it on the server. We're sending a message to syn, saying load. The argument, s, is the server to send it to. In SuperCollider, a lowercase s by itself refers to the audio server.

The next line asks to create a new Synth. The interpreter sends a message to the server, saying, "Hey, could you make a synth that plays the SynthDef called 'example1'?" The server looks and says, "oh yeah, I have a SynthDef called that" and makes a new instance of a Synth, which is running the function that we defined.

We get a new Synth object back from this and store it in "sound."

Let's say we don't want to play an A. Let's say we want to play an E. We can change 440 to 660.


(
 var sound;
 SynthDef.new("example1a", {
 
  Out.ar(0, SinOsc.ar(660));
 }).load(s);
 
 sound = Synth.new("example1a");
)

You'll note that we have one fewer variable in that example. Messages are evaluated left to right. So the interpreter first figures out the result of SynthDef.new("example1a" ... ). Then, it takes that new SynthDef and sends it the message load. We can keep adding on messages at the end as long as we'd like:

object.message1.message2(arg1).message3.message4(arg2)

Of course, this gets silly and difficult to read after a while, but it's legal.

When we're writing a piece, we don't want to have to write a new SynthDef for every note that we're going to play. We can create our own argument, which will tell the SynthDef what frequency to play.


(

 var sound;

 SynthDef.new("example1", { arg freq;
   Out.ar(0, SinOsc.ar(freq));
  }).load(s);

  sound = Synth.new("example1", [\freq, 440]);
)

We call that argument “freq.” An argument is a special kind of variable. You declare then at the top of a code block by using the reserved word “arg.” So the arg freq; part of syn = SynthDef.new("example1", { arg freq;tells SuperCollider that our SynthDef function takes a single argument called freq. We can then use freq like we would any other variable. Here, we’re passing to SinOsc.ar, to use for the frequency.

Passing variables to Synths is a bit different than normal variable passing. The interpreter has to communicate with the audio server. They use a protocol called OSC. The Synth object will handle the OSC for you, but the server does not know which argument you’re trying to pass a value to unless you specifically tell it. So Synth.new takes an optional second argument, which is an Array. An array is a list separated by commas and surrounded by square brackets. When you are passing arguments to the server via a synth, the array must be made up of pairs. The first item in a pair is a symbol or a string and the second is a value. The symbol or string must match the name of the argument. So for an argument called freq, we use the symbol \freq or the string “freq”. If we had an argument called amp, we would use the symbol \amp or the string "amp". A symbol starts with a forward slash: ‘\’. So to pass a value of 440 to the argument freq, our array contains [\freq, 440]. If we had two arguments, one freq and the other amp, we could pass values to freq and amp with an array that looks like [\freq, 440, \amp,0.2]. The array is made up of pairs, to the 440 is paired with freq and 0.2 is paired with amp. The symbols or strings must match the names of the arguments taken by the SynthDef function.

Summary

  • You must boot the server in order to play sounds.
  • There is a variable called "s" which always refers to the server
  • The sounds you want to play must be defined on the server before you play them. They are defined in SynthDefs.
  • Get help by highlighting a class name with the mouse and typing apple-d
  • Blocks of code surrounded by curly braces are functions
  • You play SynthDefs by using Synth
  • You can declare arguments to a function with the word arg: { arg agrument1, argument2;
  • Comma-separated lists surrounded by square brackets are Arrays
  • Synths use arrays to pass arguments: Synth.new(name, [\symbol, argument])

Problems

When you are writing code, if you want to syntax colorize it, so that reserved words are blue, strings are grey, symbols are green, and so on, you can find that in the Format menu or just type apple-‘ (apple-single quote).

  1. Write your own version of “hello world.”
  2. Write your own SynthDefs, using some of the oscillator UGens. To find a list of them, highlight the word “UGens” and type apple-d. Some oscillators to try are Saw and Pulse.

2 comments:

Victor Macedo said...

cool information bro, Im learning SC combined with PD, u have information of gold here :) thank u so much for ur help, have u read The SuperCollider Book from MIT Press ? Kind regards!

jowdjbrown said...

This is a complicated example, but I wanted to get you making sounds as soon as possible. Let's look at the example line by line.speech recognition program