VST3 Wrapper ping-pong bug / Cubase processParameterChanges

Cubase 9.5.20 / 64 bit/ Windows
latest juce/develop
VST3

(double checked with JuceDemoPlugin)

once a parameter is not null, cubase will send processParameterChanges for it with every callback.

this is NOT the natural cubase behaviour

–> this is caused by a problem from the VST3 Wrapper

because in JuceVST3Component::processParameterChanges

this line will be called

param->sendValueChangedMessageToListeners (floatValue);

which calls the

l->audioProcessorParameterChanged (processor, getParameterIndex(), newValue);

and then again will result calling

JuceVST3EditController::audioProcessorParameterChanged

and then might because of rounding errors (because juce unfortunately uses the non-normalized as basis which is a design mistake), or whatever, cubase again sends a parameter change with the next callback.

This can be solved easily, by not calling the AudioProcessorListener every-time cubase sends a parameter change, only call AudioProcessorParameter::Listener inside AudioProcessorParameter::sendValueChangedMessageToListeners

Maybe add a bool parameter, to control if the AudioProcessorListener also should be called, and use false if its called from JuceVST3Component::processParameterChanges

The current behaviour causes weird bugs, restore the plugin-state will not always work (A/B compare), because of the massive pseudo parameter changes which come from the audio-callback will interact wrongly with the GUI-classes.

Please check also the other wrappers, which may have the same problem.

@fabian @ed95

this should be fixed on the master too, because its affects the parameter restoring.

You can easily reconstruct the issue with the JuceDemoPlugin. Just compile it as a VST3, Open it in Cubase, change one parameter,
—> Cubase will endlessly send parameter changes

This could be a quick fix proposal:

void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue, bool sendAlsoAudioProcessorParameterChange /* = true */)
{
    ScopedLock lock (listenerLock);

    for (int i = listeners.size(); --i >= 0;)
        if (auto* l = listeners [i])
            l->parameterValueChanged (getParameterIndex(), newValue);

    // audioProcessorParameterChanged callbacks will shortly be deprecated and
    // this code will be removed.

	if (sendAlsoAudioProcessorParameterChange)  // <--- NEW
	{
		for (int i = processor->listeners.size(); --i >= 0;)
			if (auto* l = processor->listeners[i])
				l->audioProcessorParameterChanged(processor, getParameterIndex(), newValue);
	}
}

in juceVST3Component:

    void processParameterChanges (Vst::IParameterChanges& paramChanges)
    { 
        ......

            param->setValue (floatValue);
            param->sendValueChangedMessageToListeners (floatValue,false /* NEW */);
        .....
    }

Its really important to fix this quickly, because the current experience in Cubase buggy.
Also its inefficient, because parameter-coefficents will be calculated with every callback.

Thanks for reporting this - we have a fix arriving shortly.

2 Likes

We think this might be caused by the same issue:

Hi all - looks like you’re on top of it, but just wanted to note that I have this problem with the VST wrapper (not VST3), and it causes a stack overflow on Adobe products (Premiere, Audition) as soon as a parameter is changed from the host, and when restoring the plugin when re-opening a saved project.

Cheers,
Mark

Apologies for the delay - I was on holiday all of last week.

Once this has gotten a bit of exposure on the develop branch I’ll cherry pick it onto the master branch.

1 Like