projectTimeSamples not always as expected?

We keep track of the current sample position during playback, to correctly align a graph and corrections made by the user with the audio. For this, we need to detect if there is a jump or loop-back, so that we cease working with the data we were using and fetch the data for the new location instead.

To accomplish this, inside process(), we record prevSamplePos = data.processContext->projectTimeSamples, and prevNumSampes = data.numSamples. On the next process() call, we expect that the new data.processContext->projectTimeSamples value will equal prevSamplePos + prevNumSamples, since the position plus the number of samples should get you to the first sample of the next block.

Unfortunately, sometimes Cubase (haven’t tested this in Nuendo) is off by 1, so our software thinks there has been a jump or loop, and it stops its current work and prepares for processing from the new location. For one test audio file that i use, this happens about 50% of the time, but always at the same location (or approximately the same location, I haven’t verified if it’s the exactly the same).

I’m not sure how to handle this safely. I am either recording data from the process() function, or using data previously recorded (and possibly modified) to write back to a known position. And the position has to match. Adding an extra sample or skipping a sample just isn’t acceptable. I can’t just ignore it, especially when recording the data.

Why does this happen? Is there any chance this difference will ever be MORE than 1 sample? If it’s only ever 1 single sample, then I can perhaps work around it by adjusting my copying of my internal process buffer to accommodate, and something similar when playing back later, and assuming that the current sample position is always accurate.

Or, could this be a bug in Cubase, where some kind of floating point error builds up over time until it adds a whole sample position? (If so, then I don’t get why it would happen sometimes, but not always, and why always in the same place in that one file?)

this is strange… which samplerate and audio blocksize are you using ?

The block size currently is 512 samples, and the sample rate is 44.1k. But this has happened for years, at various different settings, as far as I know. The new version I’m working on doesn’t handle that difference as easily as the existing one in the field, and I’d like to keep it that way, if possible. It doesn’t happen with other hosts (whether VST3 or AU or AAX), just Cubase/Nuendo as far as I know.

i have extended the VST3 Host Checker plugin to visualize this kind of discontinuity… no strange report so far with Cubase or Nuendo

Here is one test file we observe this happening on about half the time: (2.32 MB)

Thanks Howard, i was able to reproduce it… it seems like a rounding issue from converting between sample to second and back to sample…let´s see for a fix.

Ok, that’s good to hear. Thanks, Yvan!

We’ve seen rounding issues like that in several hosts over the years - is there a canonical way of doing the seconds-to-sample conversion?

For reference, internally we use something like:
samplePos = static_cast<int64_t> (std::floor (timePos * sampleRate + 0.5))

So we’re using a rounding window of 0.5 around each discrete sample position, and for both positive and negative time positions values exactly between two samples are always rounded to the left. This prevents all rounding issues internally, but some hosts seem to do it differently and sometimes even inconsistently, causing problems when going back and forth between plug-ins and hosts, hence the question.


Hi Stefan, do you know offhand other hosts that do this? In my testing so far, I’ve only seen it in Cubase, but I haven’t gone back and tried in a lot of hosts yet. If it’s still happening across hosts, I may have to find some way to figure out where in time I actually am, so that I store the correct number of data points for the sample position I assume.

Hi Howard, I recall situations like this in Logic (when using non-constant tempo maps, and depending on playback start position) as well as in Studio One (might have been related to ARA-only code there). There may have been other hosts too that I don’t recall right now. We’ve reported these issues whenever we encountered them so they may be fixed these days.
We’ve tried tracking time internally too for the same reasons, but that code turned out rather ugly and was introducing side effects in other hosts. If you can come up with something that works reliably, please share :wink: Thanks, Stefan

Looks like it happens in Logic, if you start at time 0. This is because (like Cubase), it actually starts a little before 0, and the zero-crossing causes an off-by-one error. I haven’t seen this happen at any other points in the timeline, though.

To get around it for now, I am adjusting my internal clock back by 1 if the time reported is one less than the time I expected. I’m not sure if this is going to suffice in the long run or not. More testing and analysis of my captured data is needed, which is difficult, since audio data is so huge and irregular. Maybe I need to create some pulse data (all zeros except 1s at regular intervals) to test with.