Using the TempoClock

The TempoClock, called Clock in FoxDot, handles all of the scheduling of musical (and non-musical) events. Here are some useful methods for getting the most out of the TempoClock while you’re live coding.

Returning Measures

Clock.now()

Returns the current beat measure held by the clock.

Clock.bar_length()

Returns the length of the bar in beats

Clock.bars(n=1)

Returns the number of beats in n bars. Equivalent to Clock.bar_lenth() * n

Clock.beat_dur(n=1)

Returns the the length of n beats in seconds

Clock.beats_to_seconds(beats)

Equivalent to Clock.beat_dur(beats).

Clock.seconds_to_beats(seconds)

Returns the number of beats in seconds

Clock.get_time_at_beat(beat)

Returns the local machine time at the specified beat.

Clock.next_bar()

Returns the beat number for the start of the upcoming bar

Updating the Clock

Clock.set_time(beat)

Sets the current clock beat to beat and updates all Player objects in the clock.

Clock.set_cpu_usage(value)

Must be a value between 0 and 2. A value of 0 will use a smaller amount of CPU power but jitter may occur when using smaller durations. A value of 2 will use a higher amount of CPU but will have better performance.

Clock.set_latency(value)

Must be a value between 0 and 2. A value of 0 will use a smaller latency value, meaning updates to code will be heard more immediately, and a value of 2 will use a larger latency value, which will help with avoid “late” messages in SuperCollider.

Clock.update_tempo(bpm)

Sets the tempo at the start of the next bar. Can (and should) be set using Clock.bpm = bpm.

Clock.update_tempo_now(bpm)

Will update the clock’s tempo immediately (i.e. not at the start of the next bar)

Clock.bpm = new_tempo

Sets the tempo at the start of the next bar. Must be an integer, floating point number, or TimeVar.

Clock.nudge = new_nudge

Offset the downbeat of the clock by new_nudge seconds. Useful for manually synchronising to an external sound source. E.g. both FoxDot and the other sound source are playing at 120 bpm but FoxDot is slightly behind on the downbeat, you could use Clock.nudge = 0.2 to delay the down-beat by 0.2 seconds.

Clock.meter = (num_beats, beat_length)

Essentially updates the value returned by Clock.bar_length(). E.g. to set the clock to 3/4 time, use Clock.meter = (3, 4).

Scheduling Events

Clock.schedule(callable, beat=None, args=(), kwargs={})

Schedule a callable object, such as a function or an object with a valid __call__ method, at the given beat. If no beat is given, then object will be scheduled for the start of the next bar. Arguments and keyword arguments for the callable object can be supplied in a list and dictionary respectively:

def update(key, bpm=None):
    Root.default = int(key)
    if bpm is not None:
        Clock.bpm = bpm
    return

# Schedule for 2 beats in the future
Clock.schedule(update, Clock.now() + 2, args=[4], kwargs={"bpm", 120})

Clock.future(dur, callable, args=(), kwargs={})

Similar to Clock.schedule but the first argument specifies how far in the future to schedule the callable object, not a specific beat.

nextBar(func)

Schedules a function to be called at the start of the next bar. Can also be used as a decorator for defining a new function that is called at the start of the next bar i.e. does not have to be invoked directly:

@nextBar
def key_change():
    Scale.default = "minor"
    Root.default = 4

Clock.clear()

Clears all scheduled events in the clock, stopping any sound. From the FoxDot editor Ctrl+. is a short-cut to run this command.

Synchronisation

Clock.sync_to_espgrid(host="localhost", port=5510)

Uses the EspGrid software to synchronise FoxDot to other live coding environments, such as TidalCycles or SuperCollider. Make sure the EspGrid is running on your machine before executing this command.

Clock.sync_to_midi(sync=True)

EXPERIMENTAL: Synchronise to an external MIDI device’s clock.

Clock.connect(address)

Used for synchronising instances of FoxDot over a network. One user (the master clock) needs to go to the “Language” menu and select “Listen for connections”. This will print the IP address of the master clock. All other users that wish to synchronise use Clock.connect and the given IP address.