clockblocks package

Clockblocks is a library for controlling the flow of musical time, part of SCAMP (Suite for Computer-Assisted Music in Python).

Each Clock runs on its own thread, and clocks form families under a single master clock, whose Scheduler wakes each thread back up when its call to wait() is due. The scheduler keeps the whole clock family coordinated under a shared, ideal timeline, which is not polluted by the small delays that user code inevitably incurs. How aggressively a clock catches up when it does fall behind is set by its timing policy, which ranges from waiting out each delay in full to staying pinned to the absolute schedule.

The rate at which beats pass within a clock is given by its tempo, which may vary over time, as described by a TempoEnvelope. Clocks are also nestable: fork() spawns a child clock running a function in a parallel, subordinate timeline. A child clock’s tempo is felt relative to that of its parent, so the true rate at which time passes in a clock is the product of the clock’s own rate and that of each of its ancestors.

Taken together, these features allow a composer to create multiple, polyphonic (and perhaps poly-tempo) layers of music, each with its own tempo curve, all coordinated under a master clock.

Modules:

clock

Module defining the central Clock class — recursively nestable clocks that coordinate musical time under a master clock and its background Scheduler.

enums

Module containing the enums used to express units of duration and rate: DurationUnits, for saying whether a quantity is measured in beats or in time, and TempoUnits, for saying whether a rate of musical time is expressed as a tempo, a rate, or a beat length.

exceptions

Exception hierarchy for clockblocks.

metric_phase

Module containing the MetricPhaseTarget class, which names a point within a repeating beat or measure cycle — "the next downbeat", say, or "halfway through the bar" — without having to work out how far away that point actually is.

moment

Module containing Moment, which names a point on a clock's timeline, and the ResolvableMoment protocol implemented by anything that can be pinned to such a point.

scheduler

Module containing the Scheduler, the single background thread that drives an entire clock family: it holds a queue of upcoming events, sleeps until the next one is due, and wakes the clocks waiting on them.

tempo_envelope

Module defining the TempoEnvelope class for describing a time-varying tempo, the TempoHistory class, which adds to that a tracking of the current beat and time, and the MetricPhaseTarget class, which specifies a goal arrival point within the beat (or meter) cycle.

time_stamp

Module containing the TimeStamp class, which captures a moment on the scheduler's timeline in a clock-agnostic way, so that it can later be projected into the beat or time axis of any clock in the family.

utilities

Module containing the free functions that make up clockblocks' most convenient interface.

Public-Facing API (result of import *):

Clock([name, parent, initial_rate, ...])

Recursively nestable clock.

ClockFamilyOptions([timing_policy, ...])

Fine-tuning options for a clock family, passed to a master Clock on construction.

ClockState(*values)

Where a clock sits in its lifecycle.

DurationUnits(*values)

Units with which we measure duration or Moment positioning.

TempoUnits(*values)

The three different, and mutually determined, ways of expressing tempo.

ClockKilledError

Raised inside a forked clock's own thread when its wait is woken by kill(), so the fork wrapper can unwind the user function cleanly.

ClockblocksError

Base class for clockblocks errors.

DeadClockError

Raised when something tries to wait or fork on a clock that's no longer ALIVE (either killed already, or — for fork — still PENDING in its start_delay).

NoActiveClockError

Raised when a context-inferring clock operation (the module-level wait/fork/etc.) is attempted from a thread that has no clock active on it.

NotMasterClockError

Raised by operations that are only valid on the master (top-level) clock — e.g. run_as_server() — when called on a child clock.

SchedulerHeldError

Raised when wait() is called from a thread that is holding the scheduler via hold_scheduler() — most commonly inside a MIDI / OSC / HID callback, which runs under such a hold.

WrongThreadError

Raised when wait() is called from a thread that doesn't own the clock.

PackageNotFoundError

The package was not found.

version(distribution_name)

Get the version string for the named package.

MetricPhaseTarget(phase_or_phases[, ...])

Class representing a particular point in a (beat or measure) cycle.

Moment(value[, units, relative])

Represents a point on a clock's timeline.

ResolvableMoment(*args, **kwargs)

Anything that can name a point on a clock's timeline.

CompressedTime([factor])

A TimingBackend that runs scaled real time: now() advances factor times faster and the sleep condition's wait() divides its timeout by factor.

TimingBackend()

The scheduler's pluggable source of "now" and of the condition it uses for waiting.

TempoEnvelope([levels, durations, ...])

A subclass of Envelope that is specifically designed for representing changing tempo curves.

TempoHistory([levels, durations, ...])

Subclass of TempoEnvelope that keeps track of a current beat and time, and provides functionality for moving forward a certain number of beats or seconds, and/or setting tempo target(s) to reach in the future.

TimeStamp(scheduler_time, master_clock)

A clock-agnostic point on the scheduler's timeline, projectable into any clock's beat or time axis on demand.

TimeStampInterval(start_scheduler_time, ...)

The oriented span between two moments on the scheduler's timeline, produced by subtracting two TimeStamps (end_stamp - start_stamp).

apply_beat_length_function(function[, ...])

Drive the current clock's beat length (in seconds per beat) by following a function of beats/time.

apply_rate_function(function[, ...])

Drive the current clock's rate (in beats per second) by following a function of beats/time.

apply_tempo_envelope(envelope[, truncate, loop])

Append a ready-made TempoEnvelope onto the current clock's tempo curve.

apply_tempo_function(function[, ...])

Drive the current clock's tempo (in beats per minute) by following a function of beats/time.

current_clock()

Get the Clock active on the current thread, or None if none is active.

fork(forked_function[, args, kwargs, name, ...])

Run forked_function on a new child clock of the currently active clock, so it proceeds in parallel while staying coordinated under the same musical time.

get_beat()

Return how many beats have passed on the currently active clock (see beat).

get_beat_length()

Return the current beat length (in seconds per beat) of the currently active clock (see beat_length).

get_rate()

Return the current rate (in beats per second) of the currently active clock (see rate).

get_tempo()

Return the current tempo (in beats per minute) of the currently active clock (see tempo).

get_time()

Return how much time has passed on the currently active clock (see time) — in seconds if it is the master clock, or parent clock beats if it is a forked child clock.

set_beat_length(beat_length)

Immediately set the beat length of the current clock (see beat_length).

set_beat_length_target(beat_length_target, when)

Smoothly change the current clock's beat length to beat_length_target (in seconds per beat), arriving at when.

set_beat_length_targets(beat_length_targets, ...)

Set several beat-length targets at once, building a multi-segment tempo curve on the current clock.

set_rate(rate)

Immediately set the rate of the current clock (see rate).

set_rate_target(rate_target, when[, ...])

Smoothly change the current clock's rate to rate_target (in beats per second), arriving at when.

set_rate_targets(rate_targets, whens[, ...])

Set several rate targets at once, building a multi-segment tempo curve on the current clock.

set_tempo(tempo)

Immediately set the tempo of the current clock (see tempo).

set_tempo_target(tempo_target, when[, ...])

Smoothly change the current clock's tempo to tempo_target (in beats per minute), arriving at when.

set_tempo_targets(tempo_targets, whens[, ...])

Set several tempo targets at once, building a multi-segment tempo curve on the current clock.

stop_tempo_loop_or_function()

Stop following any function or looping envelope previously started on the current clock's tempo (via apply_tempo_function()/apply_rate_function()/apply_beat_length_function() or a looping apply_tempo_envelope()).

terminate_forked_children()

Kill the child clocks of the currently active clock, returning once they have finished unwinding (see terminate_forked_children()).

wait(dt[, units])

Block the clock currently active on this thread for dt beats (or seconds, if units="time"), yielding to the scheduler.

wait_for_children_to_finish()

Block on the currently active clock until its child clocks have finished (see wait_for_children_to_finish()).

wait_for_clock_to_finish(clock)

Block on the currently active clock until clock has finished (see wait_for_clock_to_finish()).

wait_forever()

Block forever on the currently active clock (see wait_forever()) — usually to keep the main script alive while child clocks do the work.

wait_until(when[, units])

Block the clock currently active on this thread until the absolute beat (or time, if units="time") given by when.