FoxDot.lib.Players

Players are what make FoxDot make music. They are similar in design to SuperCollider’s PDef and PBind combo but with slicker syntax. FoxDot uses SuperCollider to actually make the sound and does so by triggering predefined SynthDefs - sort of like definitions of a digital instruments. To have a look at the list of SynthDefs, you can just print them to the console:

print(SynthDefs)

Each one of these represents a SynthDef object. These objects are then given to Players to play - like giving an instrument to someone in your orchestra. To give someone the instrument, pads, you use a double arrow some code syntax like this:

p1 >> pads()

To stop a Player, use the stop method e.g. p1.stop(). If you want to stop all players, you can use the command Clock.clear() or the keyboard shortcut Ctrl+., which executes this command.

p1 is the name of a predefined player object. At startup, FoxDot reserves all one- and two-character variable names, such as x, p1, or bd for player objects but these can be repurposed if you like. If you want to use a variable name for a player object with more than two characters, you just instantiate a new Player object:

foo = Player()

foo >> pads()

Changing parameters

By default, player objects play the first note of their default scale (more below) with a duration of 1 beat per note. To change the pitch just give the SynthDef a list of numbers.

p1 >> pads([0,7,6,4])

Play multiple pitches together by putting them in round brackets:

p1 >> pads([0,2,4,(0,2,4)])

When you start FoxDot up, your clock is ticking at 120bpm and your player objects are all playing in the major scale. With 8 pitches in the major scale, the 0 refers to the first pitch and the 7 refers to the pitch one octave higher because Python, like most programming languages, uses zero-indexing. To change your scale you can specify a new scale as a keyword argument (see the documentation on Scales for more information on scales) or change the default scale for all player objects.

# Changing scale as a keyword argument
p1 >> pads([0,7,6,4], scale=Scale.minor)

# Changing the default scalew (the following are equivalent)
Scale.default.set("minor")
Scale.default.set(Scale.minor)
Scale.default.set([0,2,3,5,7,8,10])

# See a list of scales
print Scale.names()

# Change the tempo (this takes effect at the next bar)
Clock.bpm = 144

To change the rhythm of your player object, specify the durations using the dur keyword. Other keywords can be specified, such as oct for the octave and sus for the sustain, which is the same as the duration by default.

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

# See a list of possible keyword arguments
print(Player.get_attributes())

Using the play SynthDef

There is a special case SynthDef object called play which allows you to play short audio files rather than specify pitches. In this case you use a string of characters as the first argument where each character refers to a different folder of audio files. You can see more information by evaluating print(Samples). The following line of code creates a basic drum beat:

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

To play multiple patterns simultaneously, you can create a new play object. This is useful if you want to have different attributes for each player.

bd >> play("x( x)  ", dur=1)
hh >> play("---[--]", dur=[1/2,1/2,1/4], rate=4)
sn >> play("  o ", rate=(.9,1), pan=(-1,1))

Grouping characters in round brackets laces the pattern so that on each play through of the sequence of samples, the next character in the group’s sample is played. The sequence (xo)— would be played back as if it were entered x—o—. Using square brackets will force the enclosed samples to played in the same time span as a single character e.g. –[–] will play two hi-hat hits at a half beat then two at a quarter beat. You can play a random sample from a selection by using curly braces in your Play String like so:

d1 >> play("x-o{-[--]o[-o]}")

FoxDot Player Object Keywords

dur - Durations (defaults to 1 and 1/2 for the Sample Player)

sus - Sustain (defaults to dur)

amp - Amplitude (defaults to 1)

rate - Variable keyword used for misc. changes to a signal. E.g. Playback rate of the Sample Player (defaults to 1)

delay - A duration of time to wait before sending the information to SuperCollider (defaults to 0)

sample - Special keyword for Sample Players; selects another audio file from the bank of samples for a sample character.

class FoxDot.lib.Players.EmptyPlayer(name)[source]

Bases: object

Place holder for Player objects created at run-time to reduce load time.

class FoxDot.lib.Players.Group(*args)[source]

Bases: object

add(other)[source]
iterate(dur=4)[source]
metro = None
only()[source]
solo(arg=True)[source]
class FoxDot.lib.Players.GroupAttr(iterable=(), /)[source]

Bases: list

class FoxDot.lib.Players.Player(name=None)[source]

Bases: Repeatable

FoxDot generates music by creating instances of Player and giving them instructions to follow. At startup FoxDot creates many instances of Player and assigns them to any valid two character variable. This is so that when you start playing you don’t have to worry about typing myPlayer = Player() and myPlayer_2 = Player() every time you want to do something new. Of course there is nothing stopping you from doing that if yo so wish.

Instances of Player are given instructions to generate music using the >> syntax, overriding the bitshift operator, and should be given an instance of SynthDefProxy. A SynthDefProxy is created when calling an instance of SynthDef - these are the “instruments” used by player objects and are written in SuperCollider code. You can see more information about these in the SCLang module. Below describes how to assign a SynthDefProxy of the SynthDef pads to a Player instance called p1:

# Calling pads as if it were a function returns a
# pads SynthDefProxy object which is assigned to p1
p1 >> pads()

# You could store several instances and assign them at different times
proxy_1 = pads([0,1,2,3], dur=1/2)
proxy_2 = pads([4,5,6,7], dur=1)

p1 >> proxy_1 # Assign the first to p1
p1 >> proxy_2 # This replaces the instructions being followed by p1
classmethod Attributes()[source]

To be replaced by Player.get_attributes()

accompany(other, values=[0, 2, 4], debug=False)[source]

Similar to “follow” but when the value has changed

addfx(**kwargs)[source]

Not implemented - add an effect to the SynthDef bus on SuperCollider after it has been triggered.

after_update_methods = ['stutter']
alias = {'char': 'degree', 'pitch': 'degree'}
alt_dur(dur)[source]

Used to set a duration that changes linearly over time. You should use a linvar but any value can be used. This sets the dur to 1 and uses the bpm attribute to seemingly alter the durations

static apply_prime_funcs(event, key)[source]
attrmap(key1, key2, mapping)[source]

Sets the attribute for self.key2 to self.key1 altered with a mapping dictionary.

bang(**kwargs)[source]

Triggered when sendNote is called. Responsible for any action to be triggered by a note being played. Default action is underline the player.

There is a video on YouTube demonstrating this functionality.

Open FoxDotEditor and run the .bang() function as a parameter, for example:

d1 >> play('x', dur=2)
d1.bang(underline=True)

I recommend experimenting with the parameters:

overstrike=1
underline=1
foreground='red'
background='#e24329'
font=('Consolas', 30)

Here is a table with all the options:

OPTION

DESCRIPTION

background

The background color for text with this tag. Note that you can’t use bg as an abbreviation.

bgstipple

To make the background appear grayish, set this option to one of the standard bitmap names (see Section 5.7, “Bitmaps”). This has no effect unless you also specify a background.

borderwidth

Width of the border around text with this tag. Default is 0. Note that you can’t use bd as an abbreviation.

fgstipple

To make the text appear grayish, set this option a bitmap name.

font

The font used to display text with this tag. See Section 5.4, “Type fonts”.

foreground

The color used for text with this tag. Note that you can’t use the fg abbreviation here.

justify

The justify option set on the first character of each line determines how that line is justified: tk.LEFT (the default), tk.CENTER, or tk.RIGHT.

lmargin1

How much to indent the first line of a chunk of text that has this tag. The default is 0. See Section 5.1, “Dimensions” for allowable values.

lmargin2

How much to indent successive lines of a chunk of text that has this tag. The default is 0.

offset

How much to raise (positive values) or lower (negative values) text with this tag relative to the baseline. Use this to get superscripts or subscripts, for example. For allowable values, see Section 5.1, “Dimensions”.

overstrike

Set overstrike=1 to draw a horizontal line through the center of text with this tag.

relief

Which 3-D effect to use for text with this tag. The default is relief=tk.FLAT; for other possible values see Section 5.6, “Relief styles”.

rmargin

Size of the right margin for chunks of text with this tag. Default is 0.

spacing1

This option specifies how much extra vertical space is put above each line of text with this tag. If a line wraps, this space is added only before the first line it occupies on the display. Default is 0.

spacing2

This option specifies how much extra vertical space to add between displayed lines of text with this tag when a logical line wraps. Default is 0.

spacing3

This option specifies how much extra vertical space is added below each line of text with this tag. If a line wraps, this space is added only after the last line it occupies on the display. Default is 0.

tabs

How tabs are expanded on lines with this tag. See Section 24.6, “Setting tabs in a Text widget”.

underline

Set underline=1 to underline text with this tag.

wrap

How long lines are wrapped in text with this tag. See the description of the wrap option for text widgets, above.

Table taken from the tkinter.Text().tag_config() documentation.

base_attributes = ('sus', 'fmod', 'pan', 'rate', 'amp', 'midinote', 'channel')
changeSynth(list_of_synthdefs)[source]
count(time=None, event_after=False)[source]

Counts the number of events that will have taken place between 0 and time. If time is not specified the function uses self.metro.now(). Setting event_after to True will find the next event after time

debug = 0
default_root = 0
default_scale = P[0, 2, 4, 5, 7, 9, 11]
degrade(amount=0.5)[source]

Sets the amp modifier to a random array of 0s and 1s amount=0.5 weights the array to equal numbers

dur_updated()[source]

Returns True if the players duration has changed since the last call

envelope_keywords = ('atk', 'decay', 'rel', 'legato', 'curve', 'gain')
follow(other=False)[source]

Takes a Player object and then follows the notes

fx_attributes = ('vib', 'vibdepth', 'slide', 'sus', 'slidedelay', 'slidefrom', 'glide', 'glidedelay', 'bend', 'benddelay', 'coarse', 'striate', 'buf', 'rate', 'pshift', 'hpf', 'hpr', 'lpf', 'lpr', 'swell', 'bpf', 'bpr', 'bpnoise', 'chop', 'tremolo', 'beat_dur', 'echo', 'echotime', 'spin', 'cut', 'room', 'mix', 'formant', 'shape', 'drive')
fx_keys = ('vib', 'slide', 'slidefrom', 'glide', 'bend', 'coarse', 'striate', 'pshift', 'hpf', 'lpf', 'swell', 'bpf', 'chop', 'tremolo', 'echo', 'spin', 'cut', 'room', 'formant', 'shape', 'drive')
classmethod get_attributes()[source]

Returns a list of possible keyword arguments for FoxDot players and effects

get_event()[source]

Returns a dictionary of attr -> now values

get_event_length(event=None, **kwargs)[source]

Returns the largest length value in the event dictionary

get_key(key, i, **kwargs)[source]
get_prime_funcs(event)[source]

Finds and PGroupPrimes in event and returns the modulated event dictionary

get_synth_name(buf=0)[source]

Returns the real SynthDef name of the player. Useful only for “play” as there is a play1 and play2 SynthDef for playing audio files with one or two channels respectively.

get_timestamp(beat=None)[source]
classmethod help()[source]
info()[source]
internal_keywords = ('oct', 'freq', 'dur', 'delay', 'buf', 'blur', 'amplify', 'scale', 'bpm', 'sample', 'env')
jump(ahead=1, _beat_=None, **kwargs)[source]

Plays an event ahead of time.

keywords = ('degree', 'oct', 'freq', 'dur', 'delay', 'buf', 'blur', 'amplify', 'scale', 'bpm', 'sample', 'env')
kill()[source]

Removes this object from the Clock and resets itself

largest_attribute(**kwargs)[source]

Returns the length of the largest nested tuple in the current event dict

lshift(n=1)[source]

Plays the event behind

map(other=None, /, *, k=None, d=0, **mappings)[source]

Map a value to a given condition.

Abbreviation of:

d1 >> play(PwRand(['-', 'o'], [80, 20]))
b1 >> dbass(dur=1/2, oct=d1.degree.map({'-': 5, 'o': 6}))

map another player

d1 >> play(PwRand(['-', 'o'], [80, 20]))
b1 >> dbass(dur=1/2).map(d1, oct={'-': 5, 'o': 6})

or itself

s1 >> space(P[:7:2]).map(oct={0: var([6, 5])})

play by char

d2 >> play('{xX}').map(sample={'x': 2, 'V': var([2,4], [3,1])})

loop by pshift

l1 >> loop('foxdot', pshift=PWalk(2,3)).map(rate={0: 2}, lpf={3: 5000, 0: 1000}, hpf={-3: 800})

synth by degree

s1 >> space(P[:7]).map(root={0: P(4,5), 3: P^P[:10:3]})

or define which attr should be used with k=

k1 >> saw(tremolo=PSine(4)).map(root={0.0: 1, -1.0: -2}, k='tremolo')

define the default value (default: 0) with d=

d1 >> play('xs:h', dur=1)
v1 >> donk(pan=PWhite(-1, 1))
v1.map(d1, degree={':': P(var([-2,4],8),0,2), 'h': P*(-2,-4,0,1)}, d=var(P[:2]))

the value of d= can be a function that will receive the current value and should return the new value

f1 >> space(dur=1/2).degrade(.1).map(v1, degree={}, d=lambda val: 6 if (val >= 3) else 4)

in addition to d=, the mapping keys can also be a function that will receive the current value and return True or False

f2 >> swell(dur=2).map(v1, degree={lambda val: val >= 3: 6})

values can also receive functions and, like the functions for d=, will receive the current value and should return the new value

f3 >> dirt(cut=.25, dur=PDur(3,8)).map(v1, degree={bool: lambda val: 3 if val > 8 else 9})
metro = <FoxDot.lib.TempoClock.TempoClock object>
multiply(n=2)[source]
new_message_header(event, **kwargs)[source]

Returns the header of an osc message to be added to by osc_message()

now(attr='degree', x=0, **kwargs)[source]

Calculates the values for each attr to send to the server at the current clock time

num_key_references()[source]

Returns the number of ‘references’ for the attr which references the most other players

number_attr(attr)[source]

Returns true if the attribute should be a number

number_of_layers(**kwargs)[source]

Returns the deepest nested item in the event

offbeat(dur=1)[source]

Off sets the next event occurence

often(*args, **kwargs)[source]

Calls a method every 1/2 to 4 beats using every

only()[source]

Stops all players except this one

pause()[source]
penta(switch=1)[source]

Shorthand for setting the scale to the pentatonic mode of the default scale

play()[source]
push_osc_to_server(packet, timestamp, verbose=True, **kwargs)[source]

Adds message head, calculating frequency then sends to server if verbose is True and amp/bufnum values meet criteria

rarely(*args, **kwargs)[source]

Calls a method every 16 to 32 beats using every

reload()[source]

If this is a ‘play’ or ‘loop’ SynthDef, reload the filename used

required_keys = ('amp', 'sus')
reset()[source]

Sets all Player attributes to 0 unless their default is specified by an effect. Also can be called by using a tilde before the player variable. E.g. ~p1

reverse()[source]

Reverses every attribute stream

rhythm()[source]

Returns the players array of durations at this point in time

rotate(n=1)[source]

Rotates the values in the degree by ‘n’

rshift(n=1)[source]

Plays the event in front

samples = <BufferManager>
seconds()[source]

Sets the player bpm to 60 so duration will be measured in seconds

send(timestamp=None, verbose=True, **kwargs)[source]

Goes through the current event and compiles osc messages and sends to server via the tempo clock

send_osc_message(event, index, timestamp=None, verbose=True, **kwargs)[source]

Compiles and sends an individual OSC message created by recursively unpacking nested PGroups

set(**kwargs)[source]

Set multiple arguments on a single line.

What allows you to go from this:

p1.slide = 2
p1.slidedelay = .2
p1.cut = .5
p1.delay = .5

To this:

p1.set(slide=2, slidedelay=.2, cut=.5, delay=.5)
classmethod set_clock(tempo_clock)[source]
set_queue_block(queue_block)[source]

Gives this player object a reference to the other items that are scheduled at the same time

classmethod set_sample_bank(sample_bank)[source]
shuffle()[source]

Shuffles the degree of a player.

slider(start=0, on=1)[source]

Creates a glissando effect between notes

smap(kwargs)[source]

Like map but maps the degree to the sample attribute

solo(action=1)[source]

Silences all players except this player. Undo the solo by using Player.solo(0)

sometimes(*args, **kwargs)[source]

Calls a method every 4 to 16 beats using every

spread(on=0.125)[source]

Sets pan to (-1, 1) and pshift to (0, 0.125)

stop(N=0)[source]

Removes the player from the Tempo clock and changes its internal playing state to False in N bars time - When N is 0 it stops immediately

strum(dur=0.025)[source]

Adds a delay to a Synth Envelope

stutter(amount=None, _beat_=None, **kwargs)[source]

Plays the current note n-1 times. You can specify keywords.

test_for_circular_reference(value, attr, last_player=None, last_attr=None)[source]

Used to raise an exception if a player’s attribute refers to itself e.g. p1 >> pads(dur=p1.dur)

unduplicate_durs(event)[source]

Converts values stored in event[“dur”] in a tuple/PGroup into delays

unison(unison=2, detune=0.125)[source]

Like spread(), but can specify number of voices(unison) Sets pan to (-1,-0.5,..,0.5,1) and pshift to (-0.125,-0.0625,…,0.0625,0.125) If unison is odd, an unchanged voice is added in the center Eg : p1.unison(4, 0.5) => pshift=(-0.5,-0.25,0.25,0.5), pan=(-1.0,-0.5,0.5,1.0) p1.unison(5, 0.8) => pshift=(-0.8,-0.4,0,0.4,0.8), pan=(-1.0,-0.5,0,0.5,1.0)

unpack(item)[source]

Converts a pgroup to floating point values and updates and time var or playerkey relations

update(synthdef, degree, **kwargs)[source]

Updates the attributes of the player. Called using the >> syntax.

update_all_player_keys(ignore=[], event=None, **kwargs)[source]

Updates the internal values of player keys that have been accessed e.g. p1.pitch. If there is a delay, then schedule a function to update the values in the future.

update_player_key(key, value, time)[source]

Forces object’s dict uses PlayerKey instances

update_player_key_from_event(event, time=None, delay=0, ignore=[], **kwargs)[source]
update_player_key_relation(item)[source]

Called during ‘now’ to update any Players that a player key is related to before using that value

versus(other_key, rule=<function Player.<lambda>>, attr=None)[source]

Sets the ‘amplify’ key for both players to be dependent on the comparison of keys

versus_old(other, key=<function Player.<lambda>>, f=<built-in function max>)[source]

Takes another Player object and a function that takes two player arguments and returns one, default is the higher pitched

wait(n=0)[source]

Wait n beats to release the player.

d0 >> play('.-.-').wait()
d1 >> play('x...').wait(8)
d2 >> play('..o.').wait(16)
wait_bars(n=0)[source]

Wait n bars to release the player.

Clock.meter = 4,4  # is used by `wait_bars`/`futureBar`

e0 >> play('.-.-').wait_bars()
e1 >> play('x...').wait_bars(2)
e2 >> play('..o.').wait_bars(4)
widget = None
exception FoxDot.lib.Players.PlayerKeyException[source]

Bases: Exception

class FoxDot.lib.Players.rest(dur=1)[source]

Bases: object

Represents a rest when used with a Player’s dur keyword