Using your own SynthDefs

While FoxDot does come with its own range of SynthDefs for you to control, you may want to write your own or use one you have already created. This page takes you through how you go about writing a SynthDef to be used with FoxDot. This page requires a basic understanding of SuperCollider SynthDefs; if you would like to find out more, you can visit the SuperCollider documentation on the topic.

Let’s start with a very basic SynthDef written in SuperCollider made from a sine wave and a basic percussive envelope. If we’re controlling amplitude and panning as well, it might look something like this:

SynthDef.new(\sine,
    {|amp=1, sus=1, pan=0, freq=0|
        var osc, env;
        osc=SinOsc.ar(freq, mul: amp);
        env=EnvGen.ar(Env.perc(attackTime: 0.01, releaseTime: sus), doneAction: 2);
        osc=(osc * env);
        osc = Pan2.ar(osc, pan);
        Out.ar(0, osc)}).add;

To trigger synth messages in SuperCollider from FoxDot, you just need to give FoxDot a reference to the SynthDef. You can do this by running the following code in FoxDot:

sine = SynthDef("sine") 

The sine on the left is what FoxDot will refer to the synth as, and the "sine" in brackets on the right is the name of the SynthDef in SuperCollider. They don’t have to have the same name but it makes sense to keep things consistent. Once you have a sine SynthDef in FoxDot, you can use it with a player object just like any other. e.g.

p1 >> sine([0, 4, 6, 7], dur=1/2)

However, if you try and use effects in FoxDot, you’ll find it doesn’t work:

p1 >> sine([0, 4, 6, 7], dur=1/2, shape=0.5, chop=4)

To be able to “chain” effects you need to make a few adjustments to the SuperCollider SynthDef. First of all you need to be able to supply the SynthDef with a bus argument, which will store the output of the synth as effects are added. Then you need to use In.kr for the freq value (you are actually reading it from a bus, not supplying it directly) and then ReplaceOut.ar instead of Out.ar on the last line so that we write the audio signal out to the effects bus instead of your computer’s audio device. Your new SynthDef should look something like this:

SynthDef.new(\sine,
    {|amp=1, sus=1, pan=0, bus=0|
        var osc, env;
        freq = In.kr(bus, 1);
        osc=SinOsc.ar(freq, mul: amp);
        env=EnvGen.ar(Env.perc(attackTime: 0.01, releaseTime: sus), doneAction: 0);
        osc=(osc * env);
        osc = Pan2.ar(osc, pan);
        ReplaceOut.ar(bus, osc)}).add;

Saving your SynthDef

If you want to save your SynthDef (or have already saved it) and wish to load it into memory from FoxDot you can use the FileSynthDef class. You will need to name the file the same name as the SynthDef itself. So in our example above, we would need to save it as sine.scd. The file needs to be saved in FoxDot/osc/scsyndef, in which you’ll find the other .scd files used by FoxDot. You can find this by going to your Python installation directory then going to /site-packages/FoxDot/osc/scsyndef.

To load the SynthDef during a FoxDot session, create the SynthDef and use the add method to load it into SuperCollider like so:

sine = FileSynthDef("sine")
sine.add()

Important

Make sure that any doneAction arguments are set to 0 so that the node isn’t immediately. Effects such as reverb or echo require the synth not to be released until later. Using a doneAction value of 4 will not free up all of the nodes and will cause SuperCollider to run out of memory – so be careful! Now try running the FoxDot code from above and you should hear the sound with effects applied!

p1 >> sine([0, 4, 6, 7], dur=1/2, shape=0.5, chop=4)