Ardour3 LTC+MTC Sync

17:20 < las> JAD_: to sync ardour to an external timecode master, you need to implement either LTC or MTC or write a new slave. rgareus happens to be the currently undisputed heavyweight master of this, worldwide
Paul Davis on #ardour Nov 6 2012


Recent work on the Ardour Digital Audio Workstation added support for Linear Timecode (LTC) synchronization, via any audio input, according to SMPTE 309M-1999 and SMPTE 12M-1999 and dramatically improved MIDI Time Code (MTC) synchronization. As far as we know this marks the first software solution of a latency free sample-accurate timecode repeater, and for sure the first one that is free-software. At the core are libLTC and a Delay Locked Loop (DLL). The feature is available and fully tested as of Ardour3 svn rev13418 (Fri, 09 Nov 2012).

Screenshot showing A3 with incoming(green) and re-generated(red) LTC waveform

Kudos to Chris Goddard who spent countless hours staring at scopes, listening to LTC and doing real-world tests to assure sample accuracy and quality in general. It was also him who supplied the scope shots and did the QA.

The LTC repeater and latency compensation

The LTC generator in ardour can re-create an incoming MTC or LTC sync signal at zero latency and act as a timecode repeater.

In order to make this work with sample accuracy, the latency introduced by the audio-setup needs to be known and compensated for. As described in jack latency tests, the total round-trip Latency of the system depends on many factors. On a general purpose computer system the only way to accurately learn about the total latency is to measure it.

The JACK server has options to set the extra input/output latency so that applications can compensate for it.

This is where jack_delay comes into play. A derivative of jack_delay is jack_iodelay which comes with JACK. The idea is that you connect a patch-cable from a soundcard output and loop it back to a soundcard input: jack_delay → playback_port → cable from soundcard output to input → capture port → jack_delay

“To determine the correct values for jack's -I and -O, set both of them to zero ('default' in qjackctl) and measure the latency using the -E option. Then set each of the -I and -O options to half the value displayed.” [from the jack_delay README]

Frame Sample Alignment

According to the SMPTE 12M-1999 spec, the first bit of an LTC-Frame is aligned to different Lines of a Video-Frame, depending on the TV standard used. Only for Film does the LTC-Frame directly match the video Frame boundaries. libLTC supports these different alignments.

Initial testing

Initial testing was performed by recording LTC on an Ardour audio-track while Ardour was slaved to LTC. The recorded LTC signal was analysed with ltcdump to make sure it was positioned correctly. Similarly the LTC generator was tested by recording its output to an Ardour track.

MTC sync was tested using the jltc2mtc utility as well as jmtcgen: a jack-transport MTC generator, with ardour printing transport frames. It was later verified via physical I/O using Jakob Flierl's MIDI to Audio Adapter.

jltc2mtc and ltcdump are part of LTC-tools. jmtcgen is part of the MTC-tools set.


To verify accuracy the incoming LTC signal is decoded and Ardour's transport slaved to it. Then Ardour generates a new LTC signal from its transport.

The original signal is compared with the LTC that is generated by Ardour.

Because the LTC takes the same path as any other audio-signal through JACK, alignment of audio is guaranteed.


Jitter measurement The first measurements were taken with an m-audio delta44 sound-card that was not sample-locked with the LTC generator. In this case a small amount of jitter is expected and unavoidable. For this setup the jitter was quantified to ±2 audio-samples or rather -1..+3 samples using 29.97df timecode @ 48KSPS and is depicted in the following scope screenshot:

The difference in polarity is explained by the Hardware LTC generator (MOTU) not setting the parity bit, while libltc keeps the parity constant on the re-generated signal. The scope is triggered by a B&B signal at the beginning of the LTC sync word.

You can also clearly see the Gibbs effect on the generated LTC signal. This is because the sound-card cannot properly produce a 25us rise-time for the LTC signal @48KHz, and is also to be expected when passing a square wave through the anti-alias filters of an D to A converter. An example of the Gibbs phenomenon:

Gibbs phenomenon

This measurement was taken with a Delta 1010 while locked via word clock to the LTC generator @25 fps. It is a long-term jitter measurement. The result: no drift, no jitter (or jitter « 1μsec).


The LTC slave and generator provide for perfect synchronization at integer frame-rates (any fps that yields an integer audio-samples-per-timecode-frame number). In the case when the soundcard is not sample-locked, the jitter is ± 0.5 audio-sample in the case of integer frame rates and ± 2.5 samples for non-integer frame-rates (such as 29.97 fps). However, in the case of using the Slave, the DLL in ardour does average that out.

This is more that sufficient for the vast majority of use-cases.

The MTC slave is similarly robust and accurate. Zero-latency for MTC is only true for local inter-application communication or when transmitting MIDI data via netjack2. Jack does not [yet] provide options to compensate for MIDI I/O latencies.

There is some minor work left to round things up. The technical aspects are solid and now the interaction and usability can be improved e.g. a monitor-window that shows all incoming slave timecodes is being planned. Furthermore per slave and per generator time-offsets and persistent port connections are on the ToDo list. Eventually a DLL and re-sampler could be added to the LTC generator with the aim to further reduce the 2.5 sample jitter for fractional frame-rates to - at best - ± 0.5 samples. Oh and the MTC generator should be overhauled..

wiki/a3extsync.txt · Last modified: 27.06.2013 22:30 by rgareus