I’m debugging a strange issue that sometimes leads to Pluginval’s state restoration test to fail. This is with an AU plugin, I’m not sure yet if it also happens with the VST3.
The test checks if the sum of parameter values is the same before and after a state restore. Under some circumstances, when the test starts, the two AudioParameterBools that the plugin uses have random values that are not 0.f or 1.f. After saving and restoring the state they are correctly set to either 0.f or 1.f, and thus the test fails because of the difference.
Whether the test fails depends mainly on which other tests have run before. There seem to be several tests that somehow manage to produce these odd parameter values.
Anyone ran into this problem before? I think it normally shouldn’t be possible at all to set AudioParameterBools to such odd values, especially from the outside.
Tracked the issue down further, and on develop it’s the same. AudioParameterBool can just be set to any float value. I’d propose the following change to fix it. That should somewhat guarantee non-surprising values for bool parameters.
As mentioned by @jacobweber, removing the guard clause from AudioProcessorValueTreeState::ParameterAdapter::setDenormalisedValue() also seems to do the trick (and perhaps is the better option?):
Thanks for reviving this. This has been lurking in my backlog for a while and is the only thing keeping me from enabling pluginval in my CI pipeline. Not sure though which fix would be the better option.
@dave96 mentions in the other thread that it might be required by auval that a parameter set to some odd value should return that odd value. But that feels like a weird requirement for any stepped parameter like bools or choices. For AudioParameterChoice I think there’s a similar logic like the one in my proposal to “snap” the normalized values to valid ones, IIRC.
it is unrealistic to assume that you can force the outside to put a parameter to integer values only, because parameters are just atomic floats on the inside, no matter what kinda wrapper juce invents over that. one of the major reasons why i’m a huge fan of not even using parameterBool and parameterChoice at all and instead using parameterFloat, but then come up with normalisableRanges that make it act steppy on the plugin gui
The AudioParameterBool and AudioParameterChoice are useful, and I would encourage anyone to use that consistent interface to access the parameters, so that normalising is never done through an independent code path that might create inconsistent behaviour.
The API has a consistent interface to set values and they are usually set to legitimate values. To allow random numbers was never the intention of the API creators, however it is sensible that the JUCE code should take care that the values are still valid in any case. Should be simple enough to be fixed, some possible fixes are already in this thread.
Bringing back this topic, as we are improving our automated testing game:
Is there a plan to solve this? And on which end should it be solved?
Option a) saving an odd value, like @dave96 e was quoted before?
Or shouldn’t a host as well as a test program respect the settings? The AudioProcessorBoolean has getNumSteps() = 2, isBoolean and isDiscrete set, so the host and pluginval would be perfectly able (and obliged IMHO) to check if a legal and correct value is returned.
Can someone summarise this for me please so I can refresh my mind on the topic? I don’t have much bandwidth for pluginval these days so am a bit rusty…
Dave, thanks for chiming in. I’ll try to refresh, although it’s been a while since I investigated this.
IIRC, the current implementations in JUCE of AudioParameterBool and AudioParameterFloat allow setting them to any float via setValue(), which is not valid as they are stepped parameters. I think when saving and restoring the patch they are converted back and forth and in the process are snapped correctly to legal values (not sure right now if that happens during save or load, or both).
The pluginval test fails because the values before and after save/restore don’t match (as it sets random float values and compares the sum before/after). That happens only sporadically. I see this here with both AU and VST3 versions. Seems like in the “before sum” the unsnapped odd value is added, and in the “after sum” the snapped one.
Interestingly, for the AU version it can be fixed by fixing the AudioParameterBool in the plugin only, with the patch proposed above. The VST3 version however still fails sporadically, which can also be fixed by applying the same patch to pluginval’s underlying JUCE and rebuilding it.
I’m not sure though if my proposal is the “right” way to fix this behavior. I feel like it’s an ok idea to simply snap values when the host (?) tries to set it to odd values.
practically speaking this problem was already solved a long time ago when it was fixed from only being true if the value is not 0 to being true if the value is above 0.5. there was a problem where the fl studio parameter randomizer kept silencing plugins because it was unlikely for the hidden bypass parameters to be true. I personally haven’t encountered a related problem ever since that was solved
Is the snapping algorithm consistent though? Isn’t it up the the plugin how it snaps values?
For example, for binary parameters, how do they snap a value of 0.5? Does it round up or down? Or do they just store the 0.5 and use it internally as a true or false?
So the test could not validate what the plugin would do for values at the snap boundaries. But the test would not send those values, like a sane host would not.
I think that situation would be better than those false positives and skipping the discrete tests.
Are you sure that’s the only way to snap a normalised float value to a discrete num steps though?
This example shows you get different results if you truncate instead of rounding:
Then there are different rounding modes that round 0.5 up/down etc.
I’m just not sure if this fixes things in all situations?