about

supercollider

visual

This page documents my use of the environment and programming language SuperCollider. It will focus on practical examples that can help you integrate SuperCollider in your setup as well as reflections on sound synthesis and the basics of programming. Most of this will be written for MacOS which I currently use. If you want to get started with SuperCollider I recommend that you watch the videos of Eli Fieldsteel or have a look at the book A gentle introduction to SuperCollider by Bruno Ruviaro.



Posts:

13-03-2024 | functions in SC
04-12-2023 | setting up SuperCollider (2)
05-10-2023 | Setting up SuperCollider (1)

13-03-2024


Functions in SuperCollider
---------------------------

In this post I want to have a brief look at functions and how you can use them in SC. Functions are a central concept in computer programming. A function can be defined as a callable unit that has a well-defined behavior and can be invoked by other software units to exhibit that behavior. Usually this means that a value goes into the function, a behavior or series of behaviors is executed inside the function and a new value is returned. For instance if we want to write a function that subtracts half of a given number. We would have to make the following calculation:

y = x - x/2

In SuperCollider we can write this as a reusable function as follows:

a = {arg x; x = x - (x/2)}

We now have a function stored in a variable (a) that takes as an argument x and performs the necessary calculation. This means that we can easily perform our calculation for different numbers. We can use the .value method to evaluate our function, this method can also be written as value(a,4). For example:

a.value(4) a.value(8)


Some things to note:

Now how can we use this to make sounds? In the previous post we wrote the following code to send our SinOsc to bus 7.

( b = {var osc; osc = SinOsc.ar(220); Out.ar(7,osc)})

Now we can see that it is a function. Similarly to our previous example lets add a variable that we can use to modify our sound and send it to bus 0 an 1.

(b = {arg freq;
var osc;
osc = SinOsc.ar(freq);
Out.ar([0,1],osc)})

Now we can use our function to play this sine wave at different frequencies:

b.play(args: ["freq", 110])
b.play(args: ["freq", 220])
b.play(args: ["freq", 240.43])

To make it a bit more interesting lets add another variable called control which outputs a control rate signal. This signal can then be used to modify the amplitude of the signal.

( b = {arg freq;
var control;
var osc;
control = SinOsc.kr(4);
osc = SinOsc.ar(freq, 0, control);
Out.ar([0,1],osc)}
)

And run it with a few different frequencies:

b.play(args: ["freq", 140.23])
b.play(args: ["freq", 110])
b.play(args: ["freq", 220])
b.play(args: ["freq", 240.43])

04-12-2023


Setting up SuperCollider (2)
---------------------------

If you want to use SuperCollider it might be interesting to incorporate external instruments or use send/return effects. To do this you will need an external audio interface. I’m using the Native Instruments Komplete Audio 6 MK2. To see which output devices are available for SuperCollider run the following code:

ServerOptions.outDevices; // output devices

Based on this information you can set one of these as the default device. The previous post discussed routing your audio internally into your DAW using software such as Soundflower. Now we are going to combine this with our external audio interface to make an make aggregate device. For MacOs users this is pretty straightforward (Windows user can try using ASIO4ALL)

Once you’ve set up the aggregate device you want to run the above command again, if all is well it should show up in the list of possible output devices. Next use the following code to set it as a the default device.

Server.default.options.outDevice_("[insert the name of your aggregate device here]");

My aggregate device now consists of 6 channels on my external audio interface and 2 additional channels, these are the channels that will contain the SuperCollider audio. However, we do have to make sure that the audio from SuperCollider is being sent to channel 7/8. In order to do this we first need to expand our number of output channels to 8.

s.options.numOutputBusChannels(8);

You can check the levels of the different busses by running:

s.meter

Let’s run the simple sine oscillator with two busses that we made in the previous post. Notice that the sound will not be sent through to your DAW as it is sent to busses 1 & 2. in order to write a signal to another bus we have to use the Out() class which has the following methods:

Out.ar(bus, channelsArray)
Out.kr(bus, channelsArray)

You can see that you can either send audio rate (ar) or control rate (kr). In this case we want to send out our sine wave audio rate. We can do this by creating a function (more on functions later) for our oscillator and setting our bus to 6 and 7 with an array.

(
( b = {var osc;
osc = SinOsc.ar(220);
Out.ar([6,7],osc)})

Notice that we are setting it to 6 and 7 but it enters your DAW in input 7/8 because in SC we start counting from 0 instead of 1.

05-10-2023


Setting up SuperCollider (1)
---------------------------

SuperCollider is based on a client/server architecture. In short we have an audio server (which makes the sound) that we are able to communicate with using a client. The server is also called scsynth and the client as sclang, which functions as both the client and the interpreter. To execute commands we type our code in the high-level SuperColliding language which is then translated and sent to the server. That’s why, when you start the SuperCollider environment you will see this at the bottom:

Meaning that your Interpreter (or client) is Active but you still need to start (or boot) the server. You can do this using the following command.

s.boot

To run the code: put your text cursor at the end of the line of code you want to run and pres shift + enter. There is one default server stored in the interpreter variable s. The server object has a number of methods which can be accessed by writing a period (.) followed by the name of the method, e.g. server.boot. For more information about the server class have a look at the documentation. If you want to stop the server you can use the quit method by writing s.quit. Once you’ve booted the server, the next thing you want to do is set a hard limit for the output. This is not built into SuperCollider but can be installed as an additional package or a Quark. You can find more information about how to use Quarks over here: Using Quarks. The Quark you need is called Safety. I usually set the limiter at 0.5 but you can find your own preference.

Safety.setLimit(0.5)

Instead of just running SuperCollider on its own it can be interesting to run it into your DAW of choice. You can route your audio into another device internally using open source software such as Soundflower for Mac OS. You can check if it is working by running a simple sine oscillator at 220 hertz as follows: (before playing the sound turn your volume way down and then gradually turn it back up)

{SinOsc.ar(220)}.play

To stop the sound press shift +command + . (period). You've probably noticed that the sound is just coming from one speaker. Let’s make it a bit more interesting by expanding it to two channels by adding an array:

{SinOsc.ar([220, 220]}.play

So what we've got so far is

s.boot //booting the server
Safety.setLimit(0.5) //set a limit of the output
{SinOsc.ar([220, 220]}.play //play a sine oscillator 220 Hz on channel 0 and 1