Cantabile and external clock sync

I’m struggling with Cantabile’s external midi clock sync (Cantabile Performer as slave) and wondering if anyone has any advice.

Background: My band recently switched to a centralized midi clock sent from Playback. Even though it works on Cantabile most of the time, some of my VSTs occasionally run completely wrong tempos. Today Omnisphere’s arpeggiator was going at completely the wrong speed even though its LFOs (in the same Omnisphere instance!) were correctly tempo-locked. Other times I’ve faced the opposite (LFOs not synced, but arps working fine). This never happens when Cantabile’s transport is set to Metronome, and sometimes external sync works flawlessly—even for the same song. The problems are unfortunately intermittent and unpredictable.

Working theory: My best guess is that many VSTs don’t react well to sudden tempo changes, but when Cantabile transport is externally synced, it sends a slightly different tempo on every audio cycle (e.g., 75.9934 instead of 76). I think Playback might also jump the tempo and song position at song changes in a chained sequence of songs without sending any Transport Stop or Start messages, and I think this might cause some VSTs to miss tempo changes.

My questions: (Answers or guesses at any of these are welcome.)

  1. Has anyone seen the above before? Is this a well-known issue with a well-known fix?

  2. Is there any way to tell Cantabile to round tempos to the nearest whole or half bpm when sending them to plugins (e.g., in the ProcessContext struct sent to VST process() calls)?

  3. Is there any way to create a binding that changes the transport source to Metronome in case of emergency (and not stop the transport but leave it running at the Metronome-defined tempo from whatever song position it was already at)?

  4. Is there any way to script modifications to MIDI clock messages before Cantabile sends them to all the plugins (e.g., to insert MIDI Stop/Start messages, etc.)? I’m willing to roll my own plugin, but my understanding is that Cantabile doesn’t consume MIDI clock messages produced by plugins, or even loopback ports, so I’m not sure how that could be done.

Thanks for any guidance.

–Kevin

Here are a couple more questions that maybe only @brad can answer?

  1. Cantabile has a “Fast / Balanced / Slow” MIDI sync option (documented here). What does it do exactly? (My guess: Maybe Cantabile computes tempo from the number of clock messages received over the past t seconds, and Fast / Balanced / Slow changes the duration of time window t? But if so, what values are assigned to t for each setting?)

  2. The release notes say build 4223 introduced “updates to transport timing update calculations”. That sounds like it might be relevant, but what does it mean? Build 4221 apparently added a diagnostic option related to it…?

  1. Has anyone seen the above before? Is this a well-known issue with a well-known fix?

Most certainly, which is why I avoid MIDI clock like the plague, especially when trying to run a device that is also sync’d to a word clock. MIDI Clock is a 24 ppq protocol which relies on the receiver interpolating between those clocks. An early edition of Cubase (1980s) famously quantized its vaunted high resolution down to 24 ppq when sync’d via MIDI clock, rendering anything ‘real-time’ a total disaster. A message came back from Steinberg that it was impossible to improve on this due to the limitations of MIDI Clock. They soon discovered how to interpolate the incoming clock following a stream of rather embarrassing (for them) communications

Years ago (35-40?!) I had a device called a Bokse US8, which could read a MIDI clock and output anything up to 1536 ppq, to drive various non MIDI devices. Its display fluctuated alarmingly as it adjusted itself. I was never totally convinced by MIDI clock, and you’re reminding me why.
Have you considered matching your devices manually and employing a common start command? The chances are that would be way more stable. I understand this may not be practical if you’re using tempo changes.

2 Likes

Hi @Ade: I really appreciate the reply. It sounds like your experiences match mine. I’m unfortunately stuck with whatever MIDI clock Playback sends, which I think just consists of a 24ppq MIDI clock message, which abruptly jumps to a different rate when it switches songs in a playlist.

I wonder whether it would be crazy to suggest to @brad that Cantabile should have a “hybrid” clock sync mode in which the tempo is always equal to the Metronome tempo, but the song position is drawn from the external clock, and MIDI start/stop is sent to all VSTs at transport stop/start? I think this might solve many problems, since it would keep the tempo consistent (I always have a Cantabile playlist set in advance with all the correct tempos), and it would allow users to send MIDI clock start/stop at song switches via bindings, etc.

Hi @Hamlen,

Unfortunately, I think you’re hitting issues with MIDI Clock resolution and the way it needs to be measured to generate a tempo that some plugins depend on. Some plugins synchronize by tracking the tempo rather than the transport position which leads to accumulated rounding errors. In this case, this needs to be fixed in the plugin - or perhaps check the plugin for different tempo sync modes.

Is this a well-known issue with a well-known fix?

Not really.

Is there any way to tell Cantabile to round tempos to the nearest whole or half bpm

No, and I think that would make the issue worse.

Is there any way to create a binding that changes the transport source to Metronome in case of emergency

No, and that would be rather complex to implement

Is there any way to script modifications to MIDI clock messages before Cantabile sends them to all the plugins

No, and again I think that would be complex and possibly make things worse.

Cantabile has a “Fast / Balanced / Slow” MIDI sync option (documented here). What does it do exactly?

Cantabile uses a Delayed Lock Loop (DLL) for calculating the tempo from incoming MIDI Clock ticks. The fast/balanced/slow values change the omega based coefficients used by the DLL. Basically it provides a way of controlling tempo responsiveness vs stability.

The release notes say build 4223 introduced “updates to transport timing update calculations”.

This was a reworking of where transport calculations were are done. The used to be done as part of the audio engine’s parallel thread execution worker, but when routable metronome sounds were introduce this was causing issues. The calculations are the same, just now they’re done before the multi-threaded part of audio processed kicks off.

What build are you running? There was a small fix introduced in 4301 relating to the timing info being slightly off with some MIDI clock sources.

1 Like

I’m thinking that it should be possible to issue a midi command from Playback which simply starts the Cantabile transport. Are you using tempo changes? Location jumps?

Thank you @brad for the thorough answers!

I think what I’m seeing is related to abrupt tempo changes, not gradually accumulated rounding errors. For example, when we set up a playlist of multiple songs with different tempos in Playback, playing any individual song in the list works fine—no sync problems. But when rehearsing the full playlist (in which the songs play back-to-back with no gaps), suddenly some of my plugins will be completely off for one or more of the later songs (never the first song). I’m not sure whether it’s continuing to use an old song tempo or has switched to some completely wrong one, but it’s not a gradual change. The switch from correct sync to completely wrong sync happens roughly at the song boundary.

But what about bindings that target the UI? I can make one that pops up the Transport Source dropdown box, but I’m not sure how to make it select anything in there. (It would also be nice to have a reverse-binding, so that we could have a controller light that indicates transport source, but I guess maybe that’s more difficult?)

I was on 4225, but I just switched to 4302. Will find out next rehearsal whether it changes anything.

I think when we run a playlist, Playback issues transport-start whenever the Playback user presses the start button, but doesn’t issue any transport start/stop between songs. It just abruptly switches the tempo. I’m not sure whether it jumps the song position back to 1 at the start of each song; it might just treat the entire playlist as a single “song”. (Playback’s documentation doesn’t answer this question afaik.)

I imagine you had already sequenced all tempo changes in Cantabile, prior to Playback taking over master clock duties?
If so, how well was that functioning?

Yes, I was previously setting up my playlist in Cantabile as a sequence of song states, each with its own tempo. Master Transport was set to “Metronome”. As each song started, I tried to hit my transport-start button exactly in time with the click, which was very difficult. But when I could start it perfectly, it stayed perfectly in sync with the song through to the end.

That’s why I asked about some kind of “hybrid mode” that could use external clock for starting alignment but just stick with the metronome for tempo after that. Or maybe a binding that could switch to Metronome without missing a beat. Cantabile’s metronome is very stable—it stays exactly in sync with even the longest songs if I can just get it started at the right moment.

I would suggest you don’t need an external clock of any sort if Playback can be config’d to issue a midi event which can be bound to Cantabile start. Is that possible?

Yes, that’s an idea I’ve considered too. The trouble is that Cantabile bindings are too slow for that. Even when I bind a controller button to transport-start, I’ve learned that I must manage to press it about 20ms before I hear the click in order for the transport to be aligned with the click (which is one reason it’s so hard to do manually).

I think that’s why @brad coded Cantabile with a special input path for MIDI clock that doesn’t go through the normal processing path. To avoid delays, clock gets processed directly by Cantabile and delivered to plugins as process context info during the audio cycle, not as events. And Cantabile uses the history of prior clock events (the Delay Lock Loop) to achieve more precise timing info than can be extrapolated from only one event.

All of this works brilliantly to find a suitable clock alignment in under a second. I just wish I could somehow use the alignment that Cantabile has inferred without being shackled to external clock for the duration.

Silly question, but why aren’t you allowed to drive?

You mean why can’t I set Cantabile as master? Because we use multitracks (paid subscription), lighting cues, etc., all driven by Playback, so Playback needs to be the master. I’m a very small cog in a large machine with many players. :slight_smile:

OK- understood.
Sticking with the idea of you running on an internal clock with start handled by Playback, here’s a suggestion that will take some experimentation:
You could use the count off bar to ‘goose’ Cantabile’s tempo so that you’re bang on by the time you get to the song proper. Make a MIDI file. Cubase requires a couple of real events in a midi track to allow export. I just made a file where the first 8th note was at one tempo and then a designated tempo for the remainder. Make the media player the master.
If the midi binding to start is consistent, there’s almost no doubt you could compensate for the delay. Worth a try?

Ok, I tried an experiment that I think is equivalent to your idea except was easier for me to set up:

Experiment: I created a binding with a timed delay that’s triggered by a MIDI event sent by Playback during the count-off. After the specified delay (e.g., 20ms), it starts Cantabile’s transport (source set to Metronome) at the proper tempo. Then I tweaked the delay until the Cantabile’s click was bang on with Playback’s click. (Correct delay for this song turned out to be 24ms.) Then I ran the experiment a bunch of times.

Results: Sadly, the results corroborate your tale about Steinberg’s misunderstandings—sometimes the metronome starts in sync but many times it’s unpleasantly off. Using a single event as trigger apparently can’t achieve the fidelity that comes from interpolating a short sequence of clock events, even if the sequence is very short (e.g., six pulses (one 16th note) seems enough, but one pulse isn’t).

Failure analysis: Looking at the MIDI monitor, the timing of the MIDI event from Playback seems reasonably reliable (around +/- 5ms, which is probably okay), and the timing delay of the binding is very reliable (almost exactly 24ms every time), but the time between when the MIDI event arrives and when the binding awakes (e.g., starts its 24ms delay or takes any other action) is all over the place. That’s probably because Cantabile bindings aren’t designed to be triggered so precisely. They run in a different thread than the audio cycle, so they trigger whenever that thread is ready. I think this means that any solution that involves triggering a binding to start the transport can’t work reliably.

Follow-up idea: What about my idea of creating a binding that switches Cantabile’s transport source from external to metronome? Brad says it can’t be done, but I don’t understand why a UI-targeting binding wouldn’t work. I can already create a binding that opens the transport source dropdown selection box; I just don’t know how to make it select one of the options in there. Is there a way?

Even if the binding’s timing isn’t consistent, I don’t think it would matter. Whenever it gets around to switching the transport source, the clock alignment would be whatever it’s supposed to be at that moment, and I’d be on internal clock at correct alignment henceforth, right?

Start/Stop sent from Cubase.
No midi clock used on any of the following tests.
A midi file which bumps the initial tempo in Cantabile appears to achieve far more reliable sync. Rough n ready phone voice note demo:
sync test.zip (1.4 MB)

1 Like

Some additional info:
I ran a similar test using tempo events issued from the timeline. Not as tight as using a midi file in the Media Player. Far more erratic in my 5 minutes of start/stop, although very convenient for editing. That doesn’t win prizes in this case.
In order to manipulate the midi file easily, I grabbed a free open source editor that someone else recommended on this forum, Sekaiju
I mean, it could be anything, but this can be put up very fast and tempo edited to 100th of a BPM with events set to bars or time.
Slower tempos reveal errors more readily, and I didn’t get into rendering audio files to compare spike positions. It was very apparent just listening to what was working and what wasn’t.
Goosing tempo event at 0 and the actual required tempo at 100 ms.
This allows for a fair amount of fine tuning. Any variation in the start time seems well within tolerable limits, and demonstrably better than MIDI clock sync.
The only question would be how this approach responds with Cantabile under any significant load. My test is bare bones.

Hi @Ade: This is amazing work—thank you so much for your efforts.

Yep, this is exactly what I’ve been struggling with. Right after a song-switch, when load pretty much peaks, I can’t seem to get consistent timing from any binding whose source is a solo midi event. Cantabile sees the event at pretty consistent times (I see its timing in the MIDI monitor), but bindings that react to it fire at variable times, probably due to lots of threads loading/unloading VSTs, etc.

Out of curiosity, what happens on your bare-bones setup when you simply use a time-delayed binding that starts the transport 100ms after seeing the Playback-sent event rather than using the Media Player to create the delay? It’s surprising to me that there would be any difference in fidelity between those two approaches.

I’m just wondering whether placement in the bindings list influences this.
Have you tried moving those bindings to the top?
Also, are you using a midi event of some sort to fire the start command, as opposed to a real midi start command from Playback?

I’ll certainly run a test but I want to make sure I’m following your process. Obviously, a delay means that Cantabile is not starting with Playback. Are you delaying by a single clock cycle and fine tuning that? If so, how are you comparing metronomes?
Sorry if I’ve misunderstood your thinking.

Ok - ran a test with start delayed by one beat. Cubase told me delay in ms for that beat and then use binding delay to fine tune.
What we’re looking for is consistency. While near perfect sync is achievable, my sense over 5 minutes of start stop was that the media player approach was more robust .

Regardless, it appears that all of this is more reliable than using midi clock.