You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
"Plugin state restoration" fails discrete parameters after "Fuzz parameters" in randomized order #188
With --strictness-level 10 --randomise (for example --random-seed 0x471e459), "Fuzz parameters" can run before "Plugin state restoration". Fuzzing sets a boolean or other discrete parameter to an arbitrary normalized value such as 0.2007; the plugin stores the parameter's logical value (off) in its state.
After setStateInformation, the restoration test compares the parameter's value with the raw 0.2007 it set. For a VST3, the value it reads comes from the host-side cache of the last value written, so the comparison fails although the plugin restored exactly what the parameter can hold.
Could the test compare discrete parameters by their logical value (snapped to the parameter's steps, or by getText) rather than the raw normalized value, or skip values set by the fuzzer that a discrete parameter cannot hold?
Seen with pluginval 1.0.4 on JUCE 9.0.2 plugins (VST3, macOS); reproduces with --random-seed 0x471e459.
Thanks for the report and the seed. There are two separate causes here, one in pluginval and one in JUCE.
pluginval: hosted VST3 and AU parameters report the last value the host sent until a state is restored. "Plugin state restoration" read its "original" value without restoring first, so it could pick up whatever a previous test (such as "Fuzz parameters") had left behind. #191 fixes this by restoring the original state once before reading any values. That removes the false failures for choice and other multi-step parameters.
JUCE:juce::AudioParameterBool::setValue keeps the raw normalised value it is given, while the state it saves holds the on/off step (checked against JUCE 9.0.3; Choice, Int and Float snap). The value a bool reports therefore depends on how it got there, and that still fails at strictness 8 and above after #191. The JUCE-side fix is value = convertFrom0to1 (newValue) in AudioParameterBool::setValue, matching the other parameter types.
Below strictness 8, two-step (on/off) parameters are only sent 0 or 1, so these failures go away at levels 6 and 7.
At 8 and above pluginval still sends arbitrary values, since any normalised value is valid for a host to send. A new "Discrete parameter state restoration" test reports the bool behaviour explicitly.
We decided against comparing by snapped value or getText, because only the plugin knows how a normalised value maps to a step.
Until the JUCE change lands, at strictness 10 you can either snap the value in your own bool parameter, or pass --disabled-tests with a file listing "Plugin state restoration" and "Discrete parameter state restoration".
Activity
drowaudio commentedon Oct 13, 2026
Thanks for the report and the seed. There are two separate causes here, one in pluginval and one in JUCE.
pluginval: hosted VST3 and AU parameters report the last value the host sent until a state is restored. "Plugin state restoration" read its "original" value without restoring first, so it could pick up whatever a previous test (such as "Fuzz parameters") had left behind. #191 fixes this by restoring the original state once before reading any values. That removes the false failures for choice and other multi-step parameters.
JUCE:
juce::AudioParameterBool::setValuekeeps the raw normalised value it is given, while the state it saves holds the on/off step (checked against JUCE 9.0.3; Choice, Int and Float snap). The value a bool reports therefore depends on how it got there, and that still fails at strictness 8 and above after #191. The JUCE-side fix isvalue = convertFrom0to1 (newValue)inAudioParameterBool::setValue, matching the other parameter types.What changes with #191:
We decided against comparing by snapped value or
getText, because only the plugin knows how a normalised value maps to a step.Until the JUCE change lands, at strictness 10 you can either snap the value in your own bool parameter, or pass
--disabled-testswith a file listing "Plugin state restoration" and "Discrete parameter state restoration".