MIDI Time Code (MTC)

MIDI Time Code (MTC) is a sub-protocol within MIDI, and is used to keep 2 devices that control some sort of timed performance synchronized.  MTC messages are an alternative to using MIDI Clocks and Song Position Pointer messages.  MTC is essentially SMPTE mutated for transmission over MIDI.  SMPTE timing is referenced from an absolute time, whereas  MIDI Clocks and Song Position Pointer are based upon musical beats from the start of a song, played at a specific Tempo. For many (non-musical) cues, it is easier for humans to reference time in some absolute way rather than based upon musical beats at a certain tempo.

There are several MIDI messages which make up the MTC protocol. All but one are specially defined SysEx messages.


Quarter Frame


The most important message is the Quarter Frame message (which is not a SysEx message). It has a status of 0xF1, and one subsequent data byte. This message is sent periodically to keep track of the running SMPTE time. It is similar to the MIDI Clock message. The Quarter Frame messages are sent at a rate of 4 per each SMPTE Frame. In other words, by the time that a slave has received 4 Quarter Frame messages, a SMPTE Frame has passed. So, the Quarter Frame messages provide a "sub-frame" clock reference. (With 30 fps SMPTE, this "clock tick" happens every 8.3 milliseconds).

But the Quarter Frame is more than just a quarter frame "clock tick". The Quarter Frame message's data byte contains the SMPTE time (ie, hours, minutes, seconds, and frames). SMPTE time is normally expressed in 80 bits. Obviously, this is too many bits to be contained in 1 8-bit data byte. So, each Quarter Frame message contains just one piece of the time (for example, one Quarter Frame may contain only the hours). In order to get the entire SMPTE time at any given point, a slave needs to receive several Quarter Frame messages, and piece the current SMPTE time together from those messages. It takes 8 Quarter Frame messages to convey the current SMPTE time. In other words, by the time that a slave can piece together the current SMPTE time, two SMPTE frames have passed (ie, since there are 4 Quarter Frame messages in each frame). So, MTC's version of SMPTE time actually counts in increments of 2 SMPTE Frames per each update of the current SMPTE time.

The first (of 8) Quarter Frame message contains the low nibble (ie, bits 0 to 3) of the Frame Time. The second Quarter Frame message contains the high nibble (ie, bits 4 to 7) of the Frame Time. The third and fourth messages contain the low and high nibbles of the Seconds Time. The fifth and sixth messages contain the low and high nibbles of the Minutes Time. The seventh and eighth messages contain the low and high nibbles of the Hours Time. The eighth message also contains the SMPTE frames-per-second Type (ie, 24, 25, 30 drop, or 30 fps). If you were to break up the Quarter Frame's data byte into its 7 bits, the format is:

0nnn dddd

where nnn is one of 7 possible values which tell you what dddd represents. Here are the 7 values, and what each causes dddd to represent.

Value          dddd
  0	   Current Frames Low Nibble
  1	   Current Frames High Nibble
  2	   Current Seconds Low Nibble
  3	   Current Seconds High Nibble
  4	   Current Minutes Low Nibble
  5	   Current Minutes High Nibble
  6	   Current Hours Low Nibble
  7	   Current Hours High Nibble and SMPTE Type
0xF1 0x25

means that the 5 is the low nibble of the Seconds Time (because nnn is 2). If the following Quarter Frame is subsequently received,

0xF1 0x32

then this means that 2 is the high nibble of the Seconds Time. Therefore, the current SMPTE Seconds is 0x25 (ie, 37 seconds).

In the data byte for the Hours High Nibble and SMPTE Type, the bits are interpreted as follows:

0nnn x yy d

where nnn is 7. x is unused and set to 0. d is bit 4 of the Hours Time. yy tells the SMPTE Type as follows:
0 = 24 fps
1 = 25 fps
2 = 30 fps (Drop-Frame)
3 = 30 fps

When MTC is running in the forward direction (ie, time is advancing), the Quarter Frame messages are sent in the order of Frames Low Nibble to Hours High Nibble. In other words, the order looks something like this:

0xF1 0x0n
   where n is the current Frames Low Nibble

0xF1 0x1n
   where n is the current Frames High Nibble

0xF1 0x2n
   where n etc.

0xF1 0x3n

0xF1 0x4n

0xF1 0x5n

0xF1 0x6n

0xF1 0x7n
When MTC is running in reverse (ie, time is going backwards), these are sent in the opposite order, ie, the Hours High Nibble is sent first and the Frames Low Nibble is last.

The arrival of the 0xF1 0x0n and 0xF1 0x4n messages always denote where SMPTE Frames actually occur in realtime.

Since 8 Quarter Frame messages are required to piece together the current SMPTE time, timing lock can't be achieved until the slave has received all 8 messages. This will take from 2 to 4 SMPTE Frames, depending upon when the slave comes online.

The Frame number (contained in the first 2 Quarter Frame messages) is the SMPTE Frames Time for when the first Quarter Frame message is sent. But, because it takes 7 more Quarter Frames to piece together the current SMPTE Time, when the slave does finally piece the time together, it is actually 2 SMPTE Frames behind the real current time. So, for display purposes, the slave should always add 2 frames to the current time.


Full Frame


For cueing the slave to a particular start point, Quarter Frame messages are not used. Instead, an MTC Full Frame message should be sent. The Full Frame is a SysEx message that encodes the entire SMPTE time in one message as so (in hex):

F0 7F cc 01 01 hr mn sc fr F7

cc is the SysEx channel (0 to 127). It is suggested that a device default to using its Manufacturer's SysEx ID number for this channel, giving the musician the option of changing it. Channel number 0x7F is used to indicate that all devices on the daisy-chain should recognize this Full Frame message.

The hr, mn, sc, and fr are the hours, minutes, seconds, and frames of the current SMPTE time. The hours byte also contains the SMPTE Type as per the Quarter Frame's Hours High Nibble message.

The Full Frame simply cues a slave to a particular SMPTE time. The slave doesn't actually start running until it starts receiving Quarter Frame messages. (Which implies that a slave is stopped whenever it is not receiving Quarter Frame messages). The master should pause after sending a Full Frame, and before sending a Quarter Frame, in order to give the slave time to cue to the desired SMPTE time.

During fast forward or rewind (ie, shuttle) modes, the master should not continuously send Quarter Frame messages, but rather, send Full Frame messages at regular intervals.