Endlessly repeating...

Livecoding with SuperCollider: Learning to crawl

20 January 2011

Via @mclduk I've finally found a tutorial for TempoClocks in SuperCollider that I can get my head around. To celebrate and to help me remember it, here's a very quick example of some livecoding...

First we need a synth:

SynthDef(\beep, {
    arg freq = 440;
    var sig;
    sig = SinOsc.ar(freq, mul:0.2);
    sig = sig * EnvGen.kr(Env.perc(0.1, 0.5), doneAction:2);
    Out.ar(0, sig);
}).send(s);

I'm not going to bother explaining all of that because it's out of the scope of the tutorial, suffice to say it makes a short beeping sound and then frees itself.

The idea of this method of livecoding is to use a TempoClock to call a function every beat. The function can be modified while the clock is running and so we have livecoding. The first thing we need is an empty function:

a = {}

Exciting eh? Next we need a TempoClock:

c = TempoClock(2)

The argument is the clock's rate, in this case 120bpm (the argument is beats per second, 2 * 60 = 120). Next thing is to tell the clock to call our empty function every beat:

c.schedAbs(
    0, //evaluate this immediately
    {
        arg ...args;
        args[0].postln;    // arg[0] is the beat number
        a.value(args[0]); // pass the beat number to our function
        1.0               // do it all again on the next beat
    }
);

If you evaluate that you should see a number counting up in the post window.

The next step is to make our function do something:

a = {Synth(\beep)};

Evaluate that and you should hear a beep every half a second. Congratulations, you just livecoded!

a = {Synth(\beep, [\freq, 480])};

Yeah, ok that's not all that exciting but it was a breakthrough for me. It'd be nice if we could do something at a different interval than every beat. Fortunately, we're passing the beat number to our function.

a = {
    arg beat;
    // if beat number is even play a high note
    if(beat % 2 == 0, {Synth(\beep, [\freq, 440])});

    // play a low note every beat
    Synth(\beep, [\freq, 219]);
}

I'm not going to get into the modulo operation but suffice to say it's hugely useful for subdividing counters like this. You can also access external data in our function:

~notes = [50, 52, 56];
a = {Synth(\beep, [\freq, ~notes.choose.midicps])};

The contents of ~notes can be changed on the go as well. None of this is particularly groundbreaking but if you've never played around with this stuff it'll hopefully get you from sitting to crawling.