MIDISyncClock:
Filter:
ddwMIDI/Classes (extension) | External Control > MIDI

MIDISyncClock
ExtensionExtension

A clock that follows incoming MIDI clock messages

Description

A substitute clock that follows MIDI clock messages from an external source, with some caveats.

NOTE: If possible, for MIDI clock sync, it is recommended to use SuperCollider as the clock source, so that you can control for server latency. (See MIDIOut: -latency -- MIDI messages going out from SuperCollider can be delayed by an amount matching the server's latency. This will ensure better sync than is possible by responding to an external source.)

If it is absolutely necessary to follow an external source, use this class.

Usage

Recommended procedure:

  1. Be sure the clock source is not running.
  2. In SuperCollider (receiving machine), initialize MIDIClient (MIDIClient: *init).
  3. MIDIIn.connectAll. (I believe sysrt messages are received from any available port. If SC fails to respond, you might try connecting incoming port 0 to the device from which clock messages are coming: MIDIIn: *connect. In theory this should be unnecessary).
  4. Initialize MIDISyncClock (MIDISyncClock: *init).
  5. Start the clock source.
  6. (Optional) Set MIDISyncClock: *schedOffset

The clock source should begin by sending a MIDI clock "start" message, resetting MIDISyncClock to beat 0. This is essential for beat sync. If you start the clock source first, and then initialize MIDISyncClock, the beats will probably not line up.

NOTE: MIDI clock "tick" messages do not provide any information about the position within the bar. The only way to be sure beats are synchronized is to initialize MIDISyncClock first, and then start the external source. This is a limitation in the MIDI protocol; there is nothing I can do about that.

Latency compensation

A manual scheduling offset may be given by hand.

In theory, the number of ticks to offset should be server_latency.neg * tempo * ticksPerBeat (where the last is usually 24). But, you may need to add some amount for audio driver latency (making the offset closer to 0). Because audio driver latency is unknown within the language client, it is up to you to tune the scheduling offset by hand. (Important: Offset should be negative!)

Limitation: The offset depends on tempo. So, if the clock source's tempo changes, the offset will be incorrect. It is difficult to compensate for this (and, to be honest, I'm not that interested in the problem). So, for now, if you expect tempo changes, it's advised not to use schedOffset; instead, set server latency to nil and the soundcard to the smallest possible buffer size, to try to reduce the impact of latency.

Limitations

Class Methods

Most of the methods of MIDISyncClock attempt compatibility with TempoClock. Consult TempoClock documentation for details on scheduling events and managing metrical position.

One exception is TempoClock: -tempo. MIDISyncClock derives its tempo from the external source; for obvious reasons, then, you cannot override the tempo by tempo_.

.init

Initialize MIDISyncClock's internal state. Must be called before starting the external clock source.

.schedOffset

Change the MIDI clock's scheduling offset.

Arguments:

newOffset

An number of ticks by which to offset (recommended to be an integer). A negative offset shifts scheduling earlier. This is the normal case for latency compensation.

reschedule

A Boolean indicating whether or not to reschedule items currently on the clock to account for the new scheduling offset. The default is true, so that you should hear the result of the offset immediately.

Examples

This demonstration will generate MIDI clock messages within SuperCollider.