Safely deferring process callback parameter changes

Hello! I am working on a plugin that has expensive non-realtime-safe responses to parameter changes in the audio processor. As parameter changes come in on the render thread, I am hoping to defer them to be handled on the main thread.

Aside from the downside of missing out on sample-accurate param changes and assuming the plugin itself is dealing with these parameter updates between the UI and audio correctly in terms of thread safety, is it generally legal in VST3 to deal with audio thread param changes asynchronously? (Even in the worst case, where every plugin parameter is non-realtime safe and deferred?)

The main thing I’m worried about is whether edit controller “parameter changed” notifications are expected to be sent back synchronously on the render thread in response to inputParameterChanges in order for things like automation to function correctly (appears that’s how JUCE implements it in juce_VST3_Wrapper) or if it is ok for those parameter changed notifications to come back to the edit controller on the main thread.

But I imagine there might be other gotchas when it comes to parameter changed notifications or generally just not handling process-callback parameter changes immediately. For instance, if a DAW implemented automation by performing a “get” on the main thread after sending the parameter changes on the audio thread, then we might have a race condition where the get happens before the deferred “set” happens. In that case I would worry that the DAW might think that the “set” failed, because the plugin’s value was different from the expected value that it had just set. But that’s just a hypothetical scenario, maybe someone can convince me it is an irrelevant concern, either because DAWs don’t do this “constant get” approach when playing back automation or because parameter “failed sets” aren’t a big deal?

Would be helpful to know if others are deferring parameter changes in this way and whether it has resulted in host bugs around automation/undo/etc.

If you have decoupled your edit controller and audio processor parts of your plug-in (which is not possible with JUCE) it’s absolutely possible to do what you want to do. In a well implemented plug-in the edit controller does not need to know anything about the current state of the parameters in the audio processor as both have a distinct set of parameters which may not have the same state at any time.
In your case, you just handle the incoming automation changes in the realtime audio process and defer it onto another thread, by using a wait-free queue (remember you are not allowed to use any locks, mutex or how they are all called in the realtime thread), perform whatever tasks you need on a secondary thread and then push back the results again via a wait-free queue to your audio processor.

1 Like