When adding Parameters to my AudioProcessorValueTreeState my AudioProcessorValueTreeState::Listener::parameterChanged() gets called for every non-zero default parameter value.
There seem to be some kind of “optimization” preventing the initial setting of value=0.
The parameter class is probably constructed with a default value of 0, and explicitly setting it to 0 again does not notify the processor class.
Is this a bug or a feature? Or in other words: should I enforce notifying the processor with an initial parameter setting of zero by myself or will you allow notifying the processor even when the parameter is constructed with a default of 0. (The current behaviour seems to be inconsistent to me.)
I think it’s just that parameter values are set to their default values shortly after construction. You receive the parameter changed notifications for every case where the default value is not equal to zero (which is the initial value).
It’s only an “optimisation” in the sense that if a user of a plug-in triggered a setValue call which didn’t actually change the value then you wouldn’t get a callback - which is the desired behaviour.
thats pretty much what I say in the OP. But the question remains: Will you change the behaviour so AudioProcessor::parameterChanged() is always called initially? Or should I work around that feature? Its pretty obvious that all algorithm parameter need to be initially set, wether they are zero or not.
where you explicitly set the parameter after adding a listener. This is a clearer solution than making parameters broadcast their values whenever a new listener is added.
I didn’t try that particular example. What I did was load some saved state (from REAPER) where the saved parameter value was 0.5. In this case you don’t get a parameterChanged callback because the parameter hasn’t changed from it’s default value. If you set the value explicitly then you will get the callback.
But its all about promoting the default value of zero initially: I guess the same mechanism will prevent promoting when explicitly setting the default value of zero to zero again.
in my AudioProcessor constructor I create AudioProcessorValueTreeState managed parameters with createAndAddParameter() followed by addParameterListener().
For all non-zero default parameters I receive a AudioProcessorValueTreeState::ListenerparameterChanged() notification.
I’ve tried the code I posted (a very slightly modified version of the code from the tutorial at https://www.juce.com/doc/tutorial_audio_processor_value_tree_state), in REAPER and the JUCE Demo Host. Neither produce a parameterChanged callback before I change the parameters manually.
Aaah, OK. The VST and VST3 wrappers are handling how they set the default parameters differently. I was testing with VST and no callbacks are received until either the host loads some saved state or the plug-in user changes a parameter. The fact that you get any callbacks before then is a “feature” of the VST3 wrapper. However, setting the default value explicitly as in my code example should provide you with the callbacks you want in any case.
well, as mentioned: not exactly, since setting the values explicitly is calling the virtual notification from the constructor which prevents inheriting from such a class.
and initialize it to something invalid (outside the normalized range) to indicate it has not been set yet.
This will allow to initially notify the parameter about its new value:
I don’t think your change will improve things significantly for JUCE users - the behaviour for VSTs is already different (as evidenced by the fact that I struggled to reproduce the behaviour you were seeing) so if we were going to fix it we would want to harmonise the behaviour across AU, VST, VST3 and AAX. I’m also not that keen on initialising the parameter to an invalid value.
This is something we’ll look at, but I can’t promise anything happening soon.
Yes, I agree: it needs to be fixed so its working consistently across all plugin formats. But actually thats what I was expecting in the first place. Thats not a nice to have. Thats the solely reason to use an abstraction framework.
And yes, there might be better solutions.
But why would be initializing the parameter to an arbitrary valid value be more adequate? Initializing it to a valid value hides the fact that it never was intentionally set at all.