Skip to content

Commit 38e61d7

Browse files
committed
Only send 0 or 1 to two-step parameters below strictness level 8
Some plugins keep in-between values for on/off parameters rather than mapping them to a step (e.g. juce::AudioParameterBool), which made the plugin state restoration test fail at level 6. Arbitrary values are still sent to these parameters at level 8 and above. Hosted VST3 parameters don't report isBoolean, so two-step parameters are identified by their number of steps as well.
1 parent 0507946 commit 38e61d7

5 files changed

Lines changed: 28 additions & 8 deletions

File tree

‎CHANGELIST.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- `--help` output is now generated by CLI11
1616
- Added a "Discrete parameter state restoration" test (strictness 8) which checks a discrete parameter has the same value after restoring a state, whatever value it held beforehand. This fails for parameters that keep the raw normalised value from the host instead of mapping it to a step (e.g. `juce::AudioParameterBool`)
1717
- Fixed false failures in the "Plugin state restoration" test where the first parameter was compared against the last value sent by a previous test rather than the plugin's own value
18+
- Below strictness level 8, two-step (on/off) parameters are now only sent 0 or 1 when tests randomise parameter values. Arbitrary values are still sent to them at level 8 and above, and to all other parameters at every level
1819
- Enabled the editor stress and extreme (real-time allocation / oversized block) tests that were present in the source tree but had not been compiled into the build
1920

2021
### 1.0.5

‎CLAUDE.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ static MyNewTest myNewTest;
405405

406406
Located in `TestUtilities.h`:
407407
- `getNonBypassAutomatableParameters()` - Get automatable params
408+
- `getRandomParameterValue()` - Random value to set on a param (only 0 or 1 for two-step params below strictness 8)
408409
- `fillNoise()` - Fill buffer with random audio
409410
- `countNaNs()`, `countInfs()`, `countSubnormals()` - Audio validation
410411
- `ScopedEditorShower` - RAII editor creation/destruction

‎source/TestUtilities.h‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,23 @@ static inline juce::Array<juce::AudioProcessorParameter*> getNonBypassAutomatabl
5353
return parameters;
5454
}
5555

56+
/** Returns a random normalised value to set on a parameter.
57+
58+
Below strictness level 8, two-step (on/off) parameters are only sent 0 or 1.
59+
Any value is valid, but some plugins keep the values in between rather than
60+
mapping them to a step, which the state restoration tests then pick up.
61+
*/
62+
static inline float getRandomParameterValue (juce::Random& r, const juce::AudioProcessorParameter& parameter, int strictnessLevel)
63+
{
64+
// N.B. hosted VST3 parameters don't report isBoolean so also check the number of steps
65+
const bool isTwoStep = parameter.isBoolean() || parameter.getNumSteps() == 2;
66+
67+
if (isTwoStep && strictnessLevel < 8)
68+
return r.nextBool() ? 1.0f : 0.0f;
69+
70+
return r.nextFloat();
71+
}
72+
5673
//==============================================================================
5774
template<typename UnaryFunction>
5875
void iterateAudioBuffer (juce::AudioBuffer<float>& ab, UnaryFunction fn)

‎source/tests/BasicTests.cpp‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ struct PluginStateTest : public PluginTest
347347

348348
// Set random parameter values
349349
for (auto parameter : getNonBypassAutomatableParameters (instance))
350-
parameter->setValue (r.nextFloat());
350+
parameter->setValue (getRandomParameterValue (r, *parameter, ut.getOptions().strictnessLevel));
351351

352352
// Restore original state
353353
callSetStateInformationOnMessageThreadIfVST3 (instance, originalState);
@@ -388,7 +388,7 @@ struct PluginStateTestRestoration : public PluginTest
388388
for (auto parameter : getNonBypassAutomatableParameters(instance))
389389
{
390390
const auto originalValue = parameter->getValue();
391-
parameter->setValue(r.nextFloat());
391+
parameter->setValue (getRandomParameterValue (r, *parameter, ut.getOptions().strictnessLevel));
392392

393393
// Restore original state
394394
callSetStateInformationOnMessageThreadIfVST3(instance, originalState);
@@ -539,7 +539,7 @@ struct AutomationTest : public PluginTest
539539
for (int i = 0; i < juce::jmin (10, parameters.size()); ++i)
540540
{
541541
const int paramIndex = r.nextInt (parameters.size());
542-
parameters[paramIndex]->setValue (r.nextFloat());
542+
parameters[paramIndex]->setValue (getRandomParameterValue (r, *parameters[paramIndex], ut.getOptions().strictnessLevel));
543543
}
544544
}
545545

@@ -617,7 +617,7 @@ struct EditorAutomationTest : public PluginTest
617617
while (--numBlocks >= 0)
618618
{
619619
for (auto parameter : parameters)
620-
parameter->setValue (r.nextFloat());
620+
parameter->setValue (getRandomParameterValue (r, *parameter, ut.getOptions().strictnessLevel));
621621

622622
ut.resetTimeout();
623623
juce::Thread::sleep (10);
@@ -767,7 +767,7 @@ struct BackgroundThreadStateTest : public PluginTest
767767

768768
// Set random parameter values
769769
for (auto parameter : parameters)
770-
parameter->setValue (r.nextFloat());
770+
parameter->setValue (getRandomParameterValue (r, *parameter, ut.getOptions().strictnessLevel));
771771

772772
// Restore original state
773773
callSetStateInformationOnMessageThreadIfVST3 (instance, originalState);
@@ -804,6 +804,7 @@ struct ParameterThreadSafetyTest : public PluginTest
804804
auto parameters = getNonBypassAutomatableParameters (instance);
805805
const bool isPluginInstrument = instance.getPluginDescription().isInstrument;
806806
const int numBlocks = 500;
807+
const int runStrictnessLevel = ut.getOptions().strictnessLevel;
807808

808809
// This emulates the plugin itself setting a value for example from a slider within its UI
809810
juce::MessageManager::callAsync ([&, threadRandom = r]() mutable
@@ -812,7 +813,7 @@ struct ParameterThreadSafetyTest : public PluginTest
812813

813814
for (int i = 0; i < numBlocks; ++i)
814815
for (auto param : parameters)
815-
param->setValueNotifyingHost (threadRandom.nextFloat());
816+
param->setValueNotifyingHost (getRandomParameterValue (threadRandom, *param, runStrictnessLevel));
816817

817818
endWaiter.signal();
818819
});
@@ -842,7 +843,7 @@ struct ParameterThreadSafetyTest : public PluginTest
842843
addNoteOff (mb, noteChannel, noteNumber, 0);
843844

844845
for (auto param : parameters)
845-
param->setValue (r.nextFloat());
846+
param->setValue (getRandomParameterValue (r, *param, runStrictnessLevel));
846847

847848
fillNoise (ab);
848849

‎source/tests/ParameterFuzzTests.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct FuzzParametersTest : public PluginTest
4444

4545
for (int i = 0; i < 5; ++i)
4646
{
47-
const float value = r.nextFloat();
47+
const float value = getRandomParameterValue (r, parameter, ut.getOptions().strictnessLevel);
4848

4949
parameter.setValue (value);
5050
const float v = parameter.getValue();

0 commit comments

Comments
 (0)