parameterValueChanged behaving differently in VST vs VST3 in Cubase

My plugin calls the following when changing a value:

setParameterNotifyingHost(controlID, value);

Which then eventually comes around to parameterValueChanged via the following stack:

PrimerAudioProcessor::parameterValueChanged(int, float)
AudioProcessorParameter::sendValueChangedMessageToListeners(float)
AudioProcessorParameter::setValueNotifyingHost(float)
AudioProcessor::setParameterNotifyingHost(int, float)

In parameterValueChanged I add the change to an array, and check this array in processBlock, at which point the changes are implemented. This works fine in VST (and AU). However, in VST3, in Cubase, on Mac, while that entire chain does happen, parameterValueChanged gets called again via the following:

PrimerAudioProcessor::parameterValueChanged(int, float)
juce::AudioProcessorParameter::sendValueChangedMessageToListeners(float)
juce::JuceVST3Component::processParameterChanges(Steinberg::Vst::IParameterChanges&)
juce::JuceVST3Component::process(Steinberg::Vst::ProcessData&)

This results in several extra calls for every parameter. Which I could live with, except when it comes to comboboxes, the second call sends in the old value. So whenever a change is made via combobox it immediately gets set back to the previous value (Buttons and rotaries send in the new value).

I’m trying to weed out why this second call is happening in VST3 only. Can anyones shed some light on the subject?

After snooping around the juce plugin demos, I’ve figured out the following:

  1. The reason the comboboxes are the only controls to experience this issue, is because they’re using AudioParameterChoice
  2. The only juce plugin that uses AudioParameterChoice is the DSPModulePluginDemo. The comboboxes of the VST3 version of DSPModulePluginDemo in Cubase works fine, HOWEVER, it doesn’t use setValueNotifyingHost, but instead uses operator=()
  3. When I switch my model to use operator=() it fixes the problem

Which leads me to two questions:

  1. Is this the intended behavior of AudioParameterChoice? Or is this is a bug?
  2. When using operator=() is the host still notified?

Looks like it does still use setValueNotifyingHost():

https://github.com/WeAreROLI/JUCE/blob/master/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp#L265

Not exactly sure why using only operator=() would work instead of setValueNotifyingHost()… Have you tried switching the calls in DSPModulePluginDemo to use setValueNotifyingHost()?

Maybe the original issue is somehow tied to your usage of setParameterNotifyingHost(). It’s mentioned in the header the method will eventually be deprecated/removed and that you should be using AudioProcessorParameter::setValueNotifyingHost() instead

Are you managing parameters manually or are you using juce::AudioProcessorValueTreeState?

2 Likes

Ah! operator=() calls convertTo0to1 on the value before sending it in. That’s the difference. Thanks Tony.

1 Like