Write your own custom FoxDot function with Python.

We have already seen how to customize Foxdot with its own samples, synth and fx.

In this tutorial we will focus on creating functions using Python. We will not go back over the basics of this language but rather we will see how to use functions already defined in Foxdot to create others.

>> Custom FOXDOT FUNCTIONS

Before starting to code, we will first define what type of function we are going to do. Because depending on the type, we will use different decorators that are already predefined by foxdot.

Does the function relate to a player, a pattern, a pattern generator, a random pattern, is more global ?

>> PLAYER FUNCTION

A function to modify the player args. The ‘self’ reference to the player itself.

Like d1 >> play(“x.”).spread(), d1.degrade(), d1.offbeat()

Decorator: @player_method

Now let’s try to code a function that would add the duration of the player to the degree (don’t ask why we do that).

@player_method
def degdur(self):
    self.degree = self.attr['degree'] + self.attr['dur']
    return self

Example:

d1 >> blip([0,2,4,2], dur=PRand([1/2,1,2])).degdur()

>> PATTERN FUNCTION

A function to modify an existing Pattern. The ‘self’ reference to the pattern itself.

Like P[].palindrome(), P[].rotate(), P[].stretch()

Decorator: @PatternMethod

With this simple example, we are coding a function that multiplies a pattern.

@PatternMethod
def mul(self, value):
    ''' multiply a pattern '''
    return self * value
Useless ? Not so sure, try this :
d1 >> play("x-o-").sometimes("rate.mul", -1)

>> PATTERN GENERATOR FUNCTION

A function that generates a Pattern. No ‘self’ reference.

Like PRange(), PTri(), PDur()

Decorator: @loop_pattern_func

Why not try to code a function based on PSine() but with a Saw waveform.

@loop_pattern_func
def PSaw(n=16):
    ''' Returns values of one cycle of Saw wave split into 'n' parts '''
    i = 1 / (n-1)
    return Pattern([i * j for j in range(0,int(n))])
Example:
b1 >> blip(0, dur=1/2, amp=PSaw(8))

>> RANDOM PATTERN GENERATOR FUNCTION

A function that generates a random Pattern. No ‘self’ reference.

Like PRand(), PWhite(), PWalk()

Decorator: no decorator but a Class inheritance

Use the logarithmic distribution to create a generator.

class PLog(RandomGenerator):
    ''' Returns random floating point values using logarithmic distribution '''
    def __init__(self, mean=0, deviation=1, **kwargs):
        RandomGenerator.__init__(self, **kwargs)
        self.args = (mean, deviation)
        self.mean = mean
        self.deviation = deviation
        self.init_random(**kwargs)
    def func(self, index):
        if isinstance(self.mean, float):
            return lognormvariate(self.mean, self.deviation)
        elif isinstance(self.mean, int):
            return int(round(lognormvariate(self.mean, self.deviation)))
Example:
print(PLog(0,1)[:8]) --> P[1, 3, 6, 1, 1, 2, 0, 0]

>> GLOBAL FUNCTION

Nothing special here. Just define your function.

Decorator: no decorator

Do you want a fadein function ?

def fadein(duration=16):
    return linvar([0,1],[duration,inf], start=now)
Example:
b1 >> blip(0, dur=1/2, amp=fadein(8))

>> do you remember startup.py ?

Congratulations ! You have created your first foxdot function and you want to integrate them into the software.

No problem, we recommend defining your functions in the /FoxDot/lib/Custom/startup.py

Indeed this file is launched automatically when Foxdot starts and you do not need to import all the variables and functions already defined by foxdot.

If you have any questions, suggestions or if you want to share your discoveries with us, don’t hesitate to post on the toplap forum, on the telegram group, the toplap discord or directly by email.

You can also try our FoxDot Ultimate Functions and test some useful functions.