Edit: I'm not actually looking for a solution, because short of syncing the hardware clocks (which I can't do) there isn't one. What I'm looking for is an explanation of where the magic -8.4ms I seem to have identified is coming from.

I have a hardware music sequencer (Squarp Pyramid), a laptop, a digital MIDI-triggered drum synthesizer (Roland TR-8), and an audio mixing console with built-in USB audio (Soundcraft Signature 12 MTK). Using my laptop with DAW software (Reaper), I record a sequence of drum beats from the TR-8, triggered over hardware MIDI from the Pyramid:

Audio setup

What I find is that the beat-markers in Reaper drift over time compared to the onsets of beats in the recorded audio - between 10ms and 20ms per minute of audio, depending on the BPM. This is expected, of course, but I'd like to reduce it as much as possible.

I don't have access to a reliable way of keeping the clocks in sync. The solution I'm working with right now is to use a slightly modified BPM on Reaper to compensate for the drift. For example, for 125BPM on the Pyramid, I set reaper to 125.02BPM. For 117BPM on the Pyramid, I set Reaper to 117.0382BPM. This reduces the drift to fractions of ms per minute of recorded audio, which I can live with - but I have to work out the drift by hand, and it's different for each BPM.

My method for determining the drift amount is as follows:

  1. Record 10 minutes of audio with beat pulses at a particular BPM.
  2. Align the onset of the 0th recorded audio beat with t=0 in Reaper.
  3. Find the nearest Reaper beat marker to t=10mins, and measure the distance between it and the onset of the corresponding audio beat. This distance represents the clock drift over 10 minutes.

95ms clock drift over 10 minutes at 125bpm Negligable clock drift over 10 minutes at 125.02bpm

For 125BPM, the drift over 10 minutes is -95ms, giving me -9.5ms of drift per minute. \$\frac{60000}{59990.5}*125 = 125.02\$, so I set Reaper to 125.02BPM and the drift over 10 minutes becomes small enough to not be a problem any more. Unfortunately this has to be re-calculated for every BPM I set on the Pyramid. I figured out I can streamline this process by writing a C++ app that uses the RtMidi library to sample incoming MIDI clock pulses from the Pyramid’s USB output, calculating a rolling offset error to estimate drift from an expected BPM.

USB sampling setup

For 125BPM, the USB samples exhibit a clock drift of -1.1ms per minute, and I have to add a magic number of -8.4ms of drift per minute to match what I'm seeing when I line things up by hand in Reaper. I've tried this across multiple BPMs and the -8.4ms seems consistent (+/- 0.2ms). This method gives me reliable predictions for a BPM to use in Reaper to get the beat marks to line up with the audio, but the -8.4ms magic number is troubling.

Where is this magic -8.4ms coming from? I figure there are three clocks involved:

  1. Pyramid (P)
  2. My laptop (L)
  3. The USB audio module in the mixing console (M)

I suppose that the tweaked BPM in Reaper needs to be based on driftPM (clock drift between Pyramid and mixer's USB audio). My USB capture method is giving me driftPL. The magic -8.4ms must then be driftLM. So driftPM = driftPL + driftLM.

Does this seem correct? It appears to work in practise but I feel like I’m stabbing in the dark. Is there an easier approach?

  • \$\begingroup\$ you need a realtime kernel on pc, before taking any conclusons. \$\endgroup\$ Aug 13, 2019 at 10:14
  • \$\begingroup\$ @MarkoBuršič for brevity I didn't clarify, but my estimation method of USB sampling + magic -8.4ms reproduced observations accurately (+/- 0.2ms drift per minute) in 6/6 verification cases, and was able to accurately predict 2/2 test cases. \$\endgroup\$
    – damian
    Aug 13, 2019 at 10:16
  • \$\begingroup\$ you could draw a block diagram with circuit lab. it's not clear how do you measure and what peripheral io type you measure: midi pulses, wav file, ...etc \$\endgroup\$ Aug 13, 2019 at 10:20
  • \$\begingroup\$ @MarkoBuršič I added a couple of images and clarified how I'm sampling the USB midi - does this help? \$\endgroup\$
    – damian
    Aug 13, 2019 at 11:27
  • 2
    \$\begingroup\$ I don't know where your specific drift of -8.4ms comes from, but I came to think of something else which might be of use to you; Clock frequency can be (is usually) highly influenced by the temperature inside your devices. Perhaps you could experiment with cooling and/or heating the different devices in order to get their clock frequencies to be in sync and stable :P. I know it's a bit out there but well.. \$\endgroup\$
    – user173292
    Aug 13, 2019 at 12:20

2 Answers 2


Sequencer and soundcard clocks come from crystal oscillators.

8.4ms/min is a 140ppm difference in frequency, which is a bit high but not impossible, for example if both use 100ppm accuracy crystals and you get a bit unlucky.

It probably depends on temperature too, so if the temperatures of the sequencer and the USB soundcard inside the mixer vary, your "magic" -8.4ms/min may change.

  • \$\begingroup\$ Thanks, that's a good point. I really hope it doesn't change enough to mess up all my work from the past day! \$\endgroup\$
    – damian
    Aug 13, 2019 at 13:38

This is an issue that lies entirely within the Reaper software itself. Its "BPM estimator" algorithm has limited resolution, mainly due to the fact that it makes its estimate over a time interval that is much shorter than 10 minutes(!).

It then tries to round its result to a "reasonable" number, such as an integer number of BPM. But as peufeu says, it's using the computer timebase as a reference, which is not linked in any way to the original Pyramid sequencer timebase. Even if both are crystal-controlled, a 140-ppm total error is not outside the realm of possibility.

This sort of issue is exactly why music studios, etc. use a "global clock" or "house clock" to synchronize all of the equipment together.

  • \$\begingroup\$ I'm not actually using Reaper's "BPM estimator" (I assume you mean the thing that is supposed to sync Reaper to incoming MIDI time code pulses?) \$\endgroup\$
    – damian
    Aug 13, 2019 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.