How to customize Foxdot with your own Synths, effects, functions and samples.

One of FoxDot greatest strength is that you can easily add new functions and new sounds (synths, effects, samples).
In this article, we will cover a way to achieve that – it might not be the best but it works for us.

This is a advanced tutorial and it’s good to have some FoxDot and Python knowledge.
If you have questions about foxdot please go to FoxDot, TOPLAP Chat or TOPLAP Forum, we hang around those places.

These instructions are valid for this kind of configuration:
Linux Ubuntu Studio 19.10, Python 3.7, SuperCollider 3.10, FoxDot 0.8* (git version), Troop 0.9.6 (git version).

It should work on others configurations but you may have to do some corrections.

>> All starts with startup.py

We found that adding all of our changes directly to a file was the cleanest way. This make directories identical to the official version, making upgrades easier.

– First open the /FoxDot/lib/Custom/startup.py file with your favorite text editor.

– create a directory with your name in /FoxDot/lib/yourname/ to store all the synthdefs, fx, samples and functions.

>> Custom Samples

1 - Prepare the sample directory

– copy the official samples folder /FoxDot/snd/ to a new one in /FoxDot/lib/yourname/

– add or delete the samples you want in this new directory. You can also rename the samples and start samples names with 0-,1-,2-,3-,4-,… so that it matches when you code.

– Put long samples or loops in the _loop_ directory.
If you have a lot of loop samples, place them in sub-directories.
And play them in FoxDot with :

l1 >> loop("subdirectory", sample=[0,1,2], dur=8)

@@@ Global Functions @@@

2 - Change the default sample directory (3 methods)

I – First Method, args :

You can launch FoxDot with command line arguments and specify an alternate samples path :

python3 -m FoxDot -d /path/to/the/sample/dir/snd/

or with Troop :

python3 run-client.py -a -d /path/to/the/sample/dir/snd/

II – Second method, edit startup.py

We chose this method, because of Troop, so we can have a fully customized FoxDot, if you just need custom samples go for method I.
For more details go to the Install Custom FoxDot, Troop use section.

– in the startup.py add this lines :

import os
from .Settings import FOXDOT_ROOT

my_path = os.path.realpath(FOXDOT_ROOT + "/lib/yourname/snd/")

FOXDOT_SND = my_path
FOXDOT_LOOP = os.path.realpath(my_path + "/_loop_/")
FoxDotCode.use_sample_directory(FOXDOT_SND)
Samples.addPath(FOXDOT_LOOP)

– restart FoxDot or evaluate FoxDot.restart() and you should be able to play with your own sound

III – Changing in FoxDot
Also, you can load and change a directory directly in FoxDot.

FoxDotCode.use_sample_directory("/home/myname/mypath/")

3 - (Optional) Add a list of loops

When you deal with a lot samples in the loop directory, sometimes it’s good to have a list with all loops and sub-directories names, you can add this line in the startup.py
loops = sorted([fn.rsplit(“.”,1)[0] for fn in os.listdir(FOXDOT_LOOP)])
Now you have a list of all your samples loops names and sub-directories in FoxDot:
print(loops)

>> Custom FOXDOT Synths

This is a basic sine synthdef FoxDot model you can use to create your own. We add a ADSR envelope, but it’s not always necessary.

For more information on how to build SynthDefs go to Supercollider help.

SynthDef(\mysynth,
{|bus=0, amp=0.1, atk=0.001, decay=0.01, sus=1,rel=0.01, level=0.8, peak=1, gate=1, pan=0, freq=0, fmod=0, vib=0, rate=1, blur=1, beat_dur=1|
var osc, env;
sus = sus*blur;
freq = In.kr(bus, 1);
freq = [freq, freq+fmod];
osc = SinOsc.ar(freq);
//ADSR envelope
osc = osc * EnvGen.ar(Env([0, peak, level, level, 0], [atk, decay, max((atk + decay + rel), sus - (atk + decay + rel)), rel], curve:\sin), doneAction: 0);
osc = Mix(osc) * 0.5;
osc = Pan2.ar(osc, pan);
ReplaceOut.ar(bus, osc);
}).add;

3 way to add new synths in FoxDot :

  •  Create the synth in SuperCollider and evaluate, if there’s no error you should see a SynthDef in the SC log.
    In FoxDot, add this line:
    mysynth = SynthDef(“mysynth”)
    m1 >> mysynth([0,4,2], dur=1/2)

    Now you can modify your synth in SuperCollider and hear how it sounds live.

  • To add this synth permanently, first save in SC this mysynth.scd in the /FoxDot/osc/scsynthdef/ directory and add this lines in the startup.py:
from .SCLang.SynthDef import FileSynthDef
mysynth = FileSynthDef(“mysynth”)
mysynth.add()
  • You can also code a synthdef directly in FoxDot :

sinefb = SynthDef(“sinefb”)
sinefb.osc = SinOscFB.ar(freq, sinefb.rate)
sinefb.add()

a1 >> sinefb(oct=(3,4), rate=linvar([0,1],32), dur=1/2)

You can find on our Github some of our custom FoxDot Synthdefs, some of them are made by other people and we have modified them for FoxDot.

You can also find some very good stuff on sccode.org.

>> Custom FOXDOT FX

The method is similar to the custom foxdot synth you can add it live in FoxDot or in the startup.py, example with this tanh distortion :

from .Effects import *

fx = FxList.new("tanh", "tanhDisto", {"tanh":0}, order=2)
fx.add("osc = osc + (osc*tanh).tanh.sqrt()")
fx.save()

Effect.server.setFx(FxList)
d1 >> play(“X-“, tanh=4)

Notice the ‘order’ args, it’s important.
0 : Process frequency / playback rate (vibrato, slide, glide, striate, pshift, …)
1 : Before envelope (dist, crush,…)
2. Adding the envelope (lpf, hpf, chop, echo, fromant, shape,…)
3. After envelope

You can find more custom fx on our Github.

>> Custom FOXDOT FUNCTIONS

With FoxDot you can define or import a lots of cool functions to help you, put them in the startup.py

def binary(number):
    # convert a number to a binary list
    binlist = [int(i) for i in str(bin(number)[2:])]
    return binlist

def PTimebin():
    ### Generate a pattern of actual time converted to binary
    return binary(int(Clock.get_time_at_beat(int(Clock.now()))))

def lininf(start=0, finish=1, time=32):
    return linvar([start,finish],[time,inf], start=now)

Here is a more advanced tutorial on how to built your own foxdot function or a list of useful functions

>> Install Custom FoxDot for use with Troop

Troop use the FoxDot version installed in .local/lib/python3.*/site-packages/FoxDot-0.8.*-py3.7.egg/ (Linux).
If you have a clone version, you need to install your custom version to the site-packages:
In a terminal (the –user may be optional)

python3 setup.py install –user

We hope this has helped some people. Have fun and make good music!