VST3 latency reporting in PreSonus Studio One fails


#1

Hi all,
when changing the oversampling settings in my plugin I call setLatencySamples() in the Processor. This seems to work in every host except for Studio One. It only affects the VST3 version. I’ve been in touch with the Studio One devs and they answered after investigation, that the restartComponent has to be called from the UI thread, while the JUCE wrapper is only calling it from the process-call. So Studio One is refusing to accept that call and insists on restartComponent being called from the UI-thread. Is there a quick fix or workaround?

thanks


#2

Well, I guess that you should just call it from somewhere else than the process callback.

TBH I’m not entirely surprised that some hosts would have a problem with that, it’s not the kind of operation you’d expect to be real-time-safe.


#3

Thank you for the quick reply and sorry, yes I agree, it’s not really safe to call setLatencySamples() in ProcessBlock.
I probably should have been more clear.:smile:
I’ve also tried to call setLatencySamples() at different places in the Processor (i.e. prepareToPlay instead of ProcessBlock). However each with the same outcome in Studio One.
So now I’ve called setLatencySamples() from my Editor and got it working in Studio One as expected :sunglasses: Kind of embarrassing, that I haven’t thought of this myself before posting. More coffee please on a Monday morning…


#4

To be fair, prepareToPlay is the place, where this call should happen, since you don’t have necessarily an editor open before playing back (restored session).
But prepareToPlay is called from the host, so if Studio-One calls it on a thread and complains afterwards about that thread, it sounds weird.


#5

PrepareToPlay() sounds sensible. If I call it from prepareToPlay() or anywhere in the Processor, the latency change is being shown immediately in Studio One’s Performance Monitor, where you can see the latency for each plugin instance. However, that latency isn’t updated in the main latency display at the bottom of the main Studio One window below the SampleRate display and isn’t applied accordingly. When I call setLatencySamples from the Editor it does work.

What I got from PreSonus was:
" /** Instructs host to restart the component. This should be called in the UI-Thread context!"

The question now is: how can it work properly, if you have a different latencies for offline render, i.e. needed by different oversampling settings for realtime and offline processing?


#6

Hmm, prepareToPlay is also a bad place to call this function, as far as hosts are concerned.

If you tell the host that the plugin’s latency has changed, the host may have to respond by re-building its entire audio graph, introducing different PDC delays, etc.

But when prepareToPlay is called, it means that the host has already built its audio graph, and just wants the plugins to start playing. It’s really too late for them to tell it that they’ve changed their mind about something as fundamental as their latency!


#7

But what would be the appropriate place then? I can only think of prepareToPlay() and probably reset() where I can setup the processing in the AudioProcessor, but Studio One apparently doesn’t accept calls to setLatencySamples (i.e. restartComponent) there. Any ideas?


#8

Well, sometimes you need to the samplerate to calculate the latency, for example a limiter with variable look ahead time. Otherwise it may change if you change a plugin parameter like oversample factor. Ideally hosts should just handle it right whenever the call is introduced.


#9

Yes, quite true. I’m not saying there’s a better place, just that this one is awkward, as it’ll sometimes cause the host to have to restart playback. Maybe that’s not a big deal in practice though.


#10

triggering the latency change from the GUI just feels wrong. So I’ve setup a Timer in the PlugInProcessor. In timerCallback() I check if the getLatencySamples matches the calculated latency I need to report. If these don’t match I’ll do setLatencySamples().
Awkward too, but it apparently works.
However, it only does for the realtime processing oversampling settings. On offline render Studio One still takes the latency that had been set during realtime processing and ignores the offline latency, even though my timerCallback() is spitting out the correct isNonRealtime state via DBG(isNonRealtime ? “offline” : “online”);