A hack to try to slave sc to external MIDI clock messages.
A singleton. No instance methods; the entire interface is through the class.
Limitations:
- All events are quantized to the nearest tick.
- Timing may not be reliable in high-pressure situations.
- Written in sc, not in c++, so it may be CPU hungry.
- Beats counter is OK. MIDISyncClock.seconds returns elapsed seconds since clock start.
- Server messaging latency is constant. If external tempo changes, notes will be out of sync with the external clock (but once the tempo returns to its initial point, the notes will again be in sync).
There is a workaround for the messaging latency issue. Schedule latency in terms of beats, and then with each event, divide the latency by the tempo to determine the number of seconds to use as the message latency. Note that the clock's tempo is an approximation based on the ticks coming in from MIDI, so you may lose some precision this way. If the tempo is changing, though, this is the only way to be close to on time.
var latency = 0.5; // half a beat r = Routine({ var synth; loop { s.sendBundle(latency / MIDISyncClock.tempo, [\s_new, \someGrain, -1, 0, 1]); (rrand(1, 4) * 0.25).wait; } }); MIDISyncClock.play(r, [4, latency.neg]); // start 0.5 beat before 4 beat boundary r.stop;
The clock responds to three kinds of MIDI clock messages:
- clock: Advances the clock by one tick (1/24 beat). The number of ticks per beat is configurable.
- start: Reset all counters to 0. This ensures that the MIDISyncClock will be synced with the MIDI clock.
- stop: Clear the queue. Since the clock is not running and times on the queue will be invalid once the clock restarts, the queue should be emptied.
More details in the help file.
MIDISyncClock.sc (updated 8/6/2005)
MIDISyncClock.help.rtf (updated 8/13/2004: simpler modifications to make event streams work with MIDISyncClock)