“play” and “loop” players

There are currently two special-case Synths in FoxDot for playing back audio stored in a file; play and loop. Here we will look at these in some depth:

The play synth


The very basics of the play synth has been covered briefly in the player object intro section but will revisited here. Unlike other synths in FoxDot, the first argument should be a string of character, not numbers. This allows more information to be encoded in the string. Each character refers to a set of samples such as kick drums, hi-hats, snares, and other sounds. The most basic sequence you create is a disco drum beat:

p1 >> play("x-o-")

You can use different types of brackets to add more information to the sequence. Putting two or more characters in round brackets will alternate which sound to play on each loop through the sequence:

# Simple pattern
p1 >> play("(x-)(-x)o-")

# Nested brackets for more variety
p1 >> play("(x-)(-(xo))o-")

Putting multiple characters in square brackets will play them successively in the space of one step:

# Plays a triplet on the fourth steps
p1 >> play("x-o[---]", dur=1)

# Can be used in the round brackets
p1 >> play("(x-)(-[-x])o-")

# Can contain round brackets
p1 >> play("x-o[-(xo)]")

You can also use curly braces to pick a sample at random and add some variety to your sequence:

# Randomly pick a sample on the fourth step
p1 >> play("x-o{-ox}")

# Can contain [square brackets]
p1 >> play("x-o{[--]ox}")

# Can be put inside square brackets
p1 >> play("x-o[-{ox}]")

The sample keyword

Each character relates to a folder of files arranged in alphabetical order. To select a different file, use the sample keyword.

p1 >> play("x-o-", sample=1)

Like with any other keyword argument, this can be a list, or even a tuple, of values.

p1 >> play("x-o-", sample=[0, 1, 2])

p1 >> play("x-o-", sample=(0, 3))

The sample for an individual character can be specified from within the string itself by surrounding the character with a “|” and the specific number like so:

# Plays sample=2 for the 'o' character
p1 >> play("x-|o2|-")

# Will override the sample keyword
p1 >> play("x-|o2|-", sample=3)

This syntax can contain any of the brackets used before on the character and on the numbers:

# Alternate the sample number
p1 >> play("x-|o(12)|-")

# Alternate the sample character
p1 >> play("x-|(o*)2)-")

# Play multiple different samples in one step
p1 >> play("x-|o[23]|-")

# Play random sample selection
p1 >> play("x-|o{1[23]}|-")

Layering sequences

You can also use less than and greater than signs to layer multiple sequences simultaneously. Let’s start with two separate sequences and then put them together in a single line of code.

p1 >> play("x-o-")
p2 >> play("  + + [ +]")

We can put each sequence between “<>” characters in a single sequence and have them play at the same time:

# "Layers" the two sequences
p1 >> play("<x-o-><  + + [ +]>")

# Equivalent to:
p1 >> play(P["x-o-"].zip(P["  + + [ +]"]))

Each ‘layer’ relates to the index of a group such that, for a group of values given to a player object, each ‘layer’ is affected only by one of those given values. This is best demonstrated by an example:

# Hard pan each sequence to left and right channels
p1 >> play("<x-o-><  + + [ +]>", pan=(-1, 1))

# Change the sample used in the first layer
p1 >> play("<x-o-><  + + [ +]>", sample=(2, 0))

Be careful when combining multiple layers with some functions like offadd as that creates new layers if they don’t exist, or affects them if they do. The following code will only affect the second layer and, so, the first layer is unaffected:

p1 >> play("<x-o-><  + + [ +]>", sample=(2, 0)).every(4, "sample.offadd", 2)

The loop synth

This is still a fairly experimental feature of FoxDot and is definitely subject to change but let’s have a look at the basics. The loop synth is designed to let you play longer audio files (>1 sec) and manipulate them. To get started, just supply the filename you want to play and the duration you want to play in beats:

p1 >> loop("path/to/my/my_file.wav", dur=32)

You can put files in a special folder located in FoxDot/snd/_loop_ which can be opened by going to “Help & Settings” and then “Open Samples Folder” from the FoxDot menu. You don’t need to supply the full path (or extension) for files in this folder:

p1 >> loop("my_file", dur=4)

To see all the files in this folder use print(Samples.loops).

If you want to play with the play back order, you can supply a “position” argument after the file name that FoxDot will iterate through based on the duration.

# Play the first 4 beats of audio in order
p1 >> loop("my_file", P[:4], dur=1)

# Play the first 4 beats in random order
p1 >> loop("my_file", P[:4].shuffle(), dur=1)

If you know the bpm of the audio file and wish to play it at the current tempo, you can supply the player with a tempo argument. For example, my_file could be a drum beat at 135 bpm but the current tempo is 120, I can fit the tempo of my_file to the clock like so:

# First 4 beats in 1 beat steps
p1 >> loop("my_file", P[:4], dur=1, tempo=135)

# First 4 beats in 1/2 beat steps
p1 >> loop("my_file", P[:8]/2, dur=1/2, tempo=135)

You can play the entire file at the current tempo by supplying a beat_stretch argument with a non-zero value (such as 1 or True) and you don’t need to know the tempo beforehand.

p1 >> loop("my_file", dur=4, beat_stretch=True)

Time stretching the audio in this fashion will change the pitch, so if the audio is pitched, you may wish the time-stretch it without losing that information. This is possible using the striate. This cuts the file into lots of little segments and plays them back spread out over the course of the duration value – this will play the entire audio file. The larger the audio file, the larger the number you will probably want to use. Using the example above, you may want to use a striate value of 100-200 for a smoother playback:

# Stretch the file using 100 segments
p1 >> loop("my_file", dur=4, striate=100)

# Stretch it using 10 segments - listen to the difference
p1 >> loop("my_file", dur=4, striate=10)

Please note: you may experience changes in pitch at faster tempos.

All FoxDot effects can be used with the loop synth, so experiment and find out what works best for your audio. Using slide with negative values can recreate the “dj scratching” effect from old school hip-hop as it slows the playback rate to 0 then back again:

p1 >> loop("my_file", P[:8]/2, dur=1/2, slide=[0,0,-2])

The stretch synth

This recent addition to FoxDot allows you to beat stretch an entire audio file without losing any pitch information – regardless if the tempo is faster or slower. Simply supply the filename in the same way as the loop synth and set the duration you wish to play the file over and away you go:

# Play back the whole file in 4 beats
p1 >> stretch("my_file", dur=4)