Accessing system time (ticks) from audio processor

Hello!

I’m building the VST version of my looper app, and running up against a brick wall: in order to sync with external events, like incoming UI events or OSC messages, or Ableton Link synchronisation, I need access to the system time (host ticks) from the audio processor. Ableton Link, for instance, works in beats and in host ticks, so it’s the only way to perform sync. Incoming UI and OSC messages don’t have access to any other time base than the system time, so it’s the only way to sync with those too, unless I’m willing to accept only buffer-level timing accuracy (not really acceptable for a looper).

However, at least in Ableton Live, despite returning kNeedSystemTime in getProcessContextRequirements, the kSystemTimeValid flag is never set in the ProcessContext passed to the processor, and system time is always zero. Worse, although I haven’t tried it myself, in FL Studio, the system time is passed in, but it wraps around every 4.2ms because the 64-bit value’s being truncated to 32 bits!

I’ve experimented with generating my own estimate of the system time by fetching the current time initially (using mach_absolute_time, for instance, on macOS), and incrementing it by the frame size each call. However, this drifts quite badly, and just doesn’t appear workable. Similarly, just fetching the system time with mach_absolute_time/etc whenever I need it leads to jitter nastiness and general inaccuracy, because the time the code is running isn’t the same as the audio presentation time.

I can’t imagine my needs are particularly unique here, syncing with UI events/etc: what am I missing? How do I access the system time from the audio processor?

I see that 3.7.9 of the VST SDK introduces Vst::IComponentHandlerSystemTime (“API to query the system time from the controller.”); might this provide the solution? I notice it says “controller” rather than “host”, so I’m not sure how that helps.

I’m furiously crossing my fingers that I’m not going to have to go hounding all the DAW developers begging them to pass in the system time :smile: :sob:

At this point, my plan B is to basically create a separate audio engine running within the VST to provide the system timestamps, but that feels dreadful.

Many thanks in advance!
Michael

FYI, until I figure out a better solution, I’ve sorted a workaround that uses Ableton Link to calculate the system time, like this:

TPHostTicks LPWrapperImplementationCalculateHostTime(__unsafe_unretained LPWrapperImplementation * THIS, const LPTimingInfo * timingInfo) {
    // Use Ableton Link, in combination with the timeline position provided by the host, to calculate an accurate system time.
    // Link maps beats to system time; we have the timeline position from the host, but not the system time. So we query Link
    // for the system time that corresponds to the timeline position.
    
    // The timeline position should line up with the Link beat grid, but at a different timeline position, so we need to
    // determine the Link timeline position based on the current time, relative to the beat position from the host timeline.
    // We'll round to beats.
    
    if ( !LPLinkClockInterfaceIsConnected(THIS->_linkClockInterface) ) {
        return 0;
    }
    
    // Retrieve the current Link timeline position based on the current host ticks
    TPBeats linkTimeline = LPLinkClockInterfaceGetTimelinePosition(THIS->_linkClockInterface, AECurrentTimeInHostTicks());
    
    // Get the host's timeline position (e.g., in beats) from the provided timing info
    TPBeats hostTimeline = timingInfo->timelinePosition;
    
    // Extract the fractional beat offset from the host timeline
    TPBeats hostBeatOffset = fmod(hostTimeline, 1.0);
    
    // Compare with Link's fractional beat offset, to make sure they're adequately synchronised
    TPBeats linkBeatOffset = fmod(linkTimeline, 1.0);
    if ( fabs(hostBeatOffset - linkBeatOffset) > 0.1 ) {
        // Not synced; bail
        return 0;
    }
    
    // Calculate the corresponding Link timeline position adjusted to the host's beat offset
    TPBeats targetLinkTime = floor(linkTimeline) + hostBeatOffset;
    
    // Query Link for the system time (host ticks) corresponding to the adjusted Link timeline position
    TPHostTicks hostTime = LPLinkClockInterfaceGetHostTicksForTimelinePosition(THIS->_linkClockInterface, targetLinkTime);
    
    return hostTime;
}

The [3.7.9] Get Current SystemTime - VST 3 Developer Portal (steinbergmedia.github.io) could be used by the Controller part to ask for systemTime, not for the processor which normally, when this supported by the host, get the systemtime from each audioblock.
You could approach The Ableton Live developer / FL Studio to ask them to support the systemTime info…