Availability of continousTimeSamples

In a class inheriting from AudioEffect, I’m attempting to use ProcessContext::continousTimeSamples [sic?] but it always seems to be coming back as 0. I’ve tried the following:

  • Originally, I was using version 3.6.14 of the SDK. In this version, the interface IProcessContextRequirements does not exist so there did not seem to be any steps I could take to ensure that continousTimeSamples was made available.
  • I upgraded to version 3.7.11, meaning that AudioEffect now implements IProcessContextRequirements. It appears that this implementation provides a field called processContextRequirements and you simply need to call needContinousTimeSamples() on this field to cause the proper flags to be returned when getProcessContextRequirements() is called. I’m calling this in initialize() but it seems to have no effect.
  • I tried overriding getProcessContextRequirements(), logging a message, and calling up to AudioEffect’s implementation. The message never appears in the logs, meaning that getProcessContextRequirements() never actually seems to get called by the host.
  • I’ve been testing this with the latest versions of Reaper and FL Studio. In Reaper, the kContTimeValid is not even set in ProcessContext::state. In FL Studio, the kContTimeValid flag seems to be set but the value of continousTimeSamples is still 0.

Is there something obvious that I’m missing here? I don’t want to jump to conclusions but can anyone confirm that this feature is implemented correctly in these hosts? Is continousTimeSamples even something I can rely on existing? It’s marked as “optional” in the documentation, I was hoping that just means “won’t be present unless you request it” rather than “this may not ever even be present in certain hosts”.

On that note, is there a more complete description of what continousTimeSamples represents? The documentation describes it as “project time, without loop”. What I’m really looking for is some value which increments every time process() is called and stays in sync across all plugins (something like “total number of samples processed”). I’m currently using projectTimeSamples but the issue there is that it does not get incremented when playback is not actively occurring (e.g. when the user stops the track and reverbs are trailing off but the playhead is not advancing, this value remains constant).

The only value in the ProcessContext structure that is continuously increasing is the systemTime. But as stated in the documentation this value is optional and only valid if the flags value has the kSystemTimeValid flag set.
Some hosts just don’t support all the values in that structure.

Ah, that’s too bad that the other values can’t be relied upon. For more context: I have two AudioEffects (call them A and B). Multiple instances of A feed into a single instance of B but B needs to process each A’s data individually, not summed as ordinary audio bus routing would do (I realize this is probably not a very common situation). I was attempting to have each A instance store off its processed data and use something like continousTimeSamples as a lookup key.

Now I’m looking into using an event bus (rather than an audio bus) to connect the A instances to the B instance. The A instances would cache off their audio data and send a custom kDataEvent event to B, telling it where to look to grab the stored audio data. From what I can tell, kDataEvent events need to be in the SysEx format (Reaper seems to discard the event if it’s not). I’m hoping that this will (a) actually work, and (b) be supported by all common hosts.

Well, using the event bus works great… in DAWs where that is supported, like Reaper. But in FL Studio, events don’t seem to actually run through mixer inserts at all, so I’m back to square one.

Unfortunately, even systemTime appears not to be reliable in some DAWs! In FL Studio, despite being an int64, it wraps around every ~4.2 billion nanoseconds (4.2 seconds), suggesting that it’s being truncated to uint32 at some point in the pipeline.

I assume such a thing doesn’t exist, but just in case I’ve been overlooking something obvious: is there any sort of unique value/ID that is available on a per-processing block basis? i.e. is the same across all plugins for a given processing block?

I’m guessing the answer is “no” and that the reason is that the VST3 API doesn’t enforce constraints on block sizes across different plugins (e.g. a host is allowed to make plugin A process 128 samples at a time and plugin B process 192 samples at a time as long as the host lines everything up at the end). If that’s the case, then I guess my fundamental approach might be flawed.

That is indeed the case. Cubase for example has “realtime” tracks that process with the block size the user has setup in the driver setting and tracks that are processed in advance with a multiply of the block size. They even are executed at totally different times.