Clocks and clips#
A domain clock is a named beat clock owned by the engine. You create and
steer it through YSE::System(): createClock, destroyClock,
clockExists, setTempo, beatPosition and currentTempo (see
Core). A clip plays a looping list of beat-timed notes against one
of those clocks, into synths or MIDI output ports.
Clocks and clips walks through both, and
Time, scheduling and clocks shows how a patch uses the same clocks. The C API
equivalents are in C ABI (language bindings) (yse_clip.h and the clock functions in
yse_system.h).
-
namespace YSE
Public API of libYSE — sound playback, mixing, and 3D positional audio.
Entry points:
YSE::System(lifecycle and audio device),YSE::Listener(3D origin),YSE::sound(a playable source),YSE::channel(mixing tree),YSE::reverb(positioned reverb zone),YSE::patcher(modular DSP graph),YSE::player(note sequencer). Sub-namespaces group domain-specific types:YSE::DSPfor signal processing,YSE::MIDIfor MIDI I/O,YSE::MUSICfor note / chord / motif primitives.Note
Apart from their constructors, the oscillator and
vcfclasses must only be invoked from inside a DSP callback /processbody.-
class clip#
A looping clip transport: plays a timed note-event list against a domain clock, dispatched from the audio thread.
The clip binds to a named domain clock (see
System().createClock). It owns an immutable list ofclipEventand a loop length in beats. Every audio block it converts that block’s boundaries into a beat window on the clock and fires exactly the events whose crossings fall inside it — so the UI thread never dispatches a note, and tempo changes on the clock bend the clip with no rescheduling.The event list is replaceable while playing:
setEventspublishes a new list that the transport swaps in at the next block boundary, lock-free with respect to the audio thread. Sounding-note bookkeeping survives the swap — a note that vanished from the new list still gets its note-off on time.Output targets one or more
YSE::synthinstances (block-accurate, on the audio thread, via the RT-safe internal event queues) and — on builds withYSE_ENABLE_MIDI_DEVICE— one or more external MIDI output ports (issue #350): fired messages are stamped with an absolute send time and drained by a dedicated sender thread, so the RtMidi send never happens on the audio callback.Multiple clips run concurrently, each on its own clock. Non-copyable / non-movable — wrap in a
unique_ptrif you need transferable ownership.Public Functions
-
clip()#
-
~clip()#
-
bool create(const std::string &clockName)#
Bind the clip to a domain clock by name.
Binding shares the clock’s lifetime (issue #707), so the two can be destroyed in either order:
destroyClockon a bound clock stops it advancing, and a clip on a stopped clock simply stops firing rather than reading a freed object. Control thread only.- Parameters:
clockName – Name of a live domain clock (
System().createClock).- Returns:
trueon success;falseif no live clock owns the name.
-
clip &setEvents(const std::vector<clipEvent> &events)#
Replace the event list.
Takes effect at the next block boundary, lock-free with respect to the audio thread. Control thread only.
-
clip &loopLength(double beats)#
Set the loop length in beats.
Values <= 0 disable looping (events fire once). Control thread only.
-
clip &connect(YSE::synth &synth)#
Route this clip’s playback into a synth.
Every note / pitch-bend it fires is delivered to
synthblock-accurately on the audio thread. May be called for several synths.Warning
synthmust outlive the connection:disconnectit (or destroy this clip) before destroying the synth. Control thread only.
-
bool isPlaying() const#
Whether the clip is currently playing.
-
clip()#
-
struct clipEvent#
One timed note event in a clip, positioned in beats.
Times are beat offsets on the clip’s bound domain clock, not absolute seconds — the transport evaluates them against the clock every audio block, so a tempo change on the clock bends the clip immediately with no rescheduling.
startBeatis taken modulo the clip’s loop length, so an event repeats every loop.Public Members
-
double startBeat = 0.0#
Beat within the loop at which the note starts (>= 0).
-
double durationBeats = 0.0#
Note length in beats.
The note-off fires
durationBeatsafter each note-on, independent of the event list — so a note still sounding when the list is swapped is released on time even if it vanished from the new list.
-
float velocity = 0.8f#
Velocity, normalized to [0, 1].
-
float pitchBend = 0.0f#
Optional per-note pitch bend, normalized to [-1, 1] (0 = none).
Emitted as a channel pitch-wheel just before the note-on — Phi voices fractional / microtonal pitch as nearest semitone + bend.
-
double startBeat = 0.0#
-
class clip#