EDIT: It looks like it would be better to WAIT before using AudioProcessorValueTreeState
. One of the major issue at the moment (for me at least) is that AU parameters are listed in the DAW in random order. Check this AU Parameter Order
Plus, it seems like the JUCE team is still working on the new system: We are removing AudioProcessor-based parameter management
I’ll stick with my old method using just AudioProcessorParameter
for now. I’ll probably update this thread if things change.
Sorry for the long post, but I think there’s a need for a much more detailed tutorial for complex plugins with many parameters.
I’ve finally decided to test JUCE 5 and it seems like many nice things were added, as long as many breaking changes. I don’t plan to update my old plugins for now (JUCE 4 mess was enough…), but I’m considering releasing new stuff with JUCE 5. Looking at the examples and at the new tutorials, I see very different ways of dealing with parameters and setState/getState methods.
My old plugins are all using AudioProcessorParameter
and something like addParameter (Param = new FloatParameter (0, "Parameter", 0, *this));
in the constructor. So I have my nice FloatParameter
class were I deal with everything, with a big switch on the parameter index. The UI is synchronized with a timer and my custom sliders/buttons are linked to an AudioProcessorParameter*
. It works, it’s not elegant and probably not really efficient, but it works.
AudioProcessorValueTreeState
So, I want to improve how I deal with parameters, and the AudioProcessorValueTreeState
looks very promising but more confusing. This is what I found out so far.
Adding Parameters
It seems like we can only use Just found out that I need to declare the parameter as discrete.AudioProcessorParameterWithID*
with the createAndAddParameter
method. Why? Why can’t we use AudioParameterChoice
and AudioParameterBool
? It’s not a major issue, but it would be nice to show the correct representation of the parameter (button, choice list) in the DAW.
So, we have to do something like that for a bool parameter:
params.createAndAddParameter ("bypass",
"Bypass",
String(),
NormalisableRange<float> (0.0f, 1.0f, 1.0f),
0.0f,
[](float value) { return value < 0.5 ? "on" : "off"; },
[](const String& text)
{
if (text.toLowerCase() == "on") return 0.0f;
if (text.toLowerCase() == "off") return 1.0f;
return 0.0f;
},
false, // meta
true, // automatable
true); // discrete (for bool and choice params)
For a standard float parameter intead:
params.createAndAddParameter ("input",
"Input Gain",
String(),
NormalisableRange<float> (0.0f, 4.0f, skewGainConvertFrom0To1, skewGainConvertTo0To1),
0.5f,
parameterDecibelToString,
parameterDecibelToValue);
I’m using custom methods for skew and string/value returns. I really love this approach.
(get/set)StateInformation
Very easy now compared to the old way.
void getStateInformation (MemoryBlock& destData) override
{
auto state = parameters.copyState();
ScopedPointer<XmlElement> xml (state.createXml());
copyXmlToBinary (*xml, destData);
}
void setStateInformation (const void* data, int sizeInBytes) override
{
ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
if (xmlState != nullptr)
if (xmlState->hasTagName (parameters.state.getType()))
parameters.replaceState (ValueTree::fromXml (*xmlState));
}
Parameter Changes in Processor
Looking at the DSPModulePluginDemo I see that there’s a call to a updateParameters()
before the actual processing. For some parameters it’s actually much safer to check every time before the processing. But I don’t think that should be the case for all parameters.
For example:
void updateParameters()
{
if (type != *params.getRawParameterValue("type"))
{
type = *params.getRawParameterValue("type");
thingThatNeedsType.changeType(type);
}
}
So, some questions:
- is
AudioProcessorValueTreeState
stable enough to be used in a release? Is it going to be updated and stick around in the future, or is ROLI working on yet another system? -
will it be possible in the future to add properwe can just declare the parameter discretebool
andchoice
type parameters toAudioProcessorValueTreeState
? - is there a better way to deal with parameter changes in the processor (not in the UI) other than a
updateParameters()
before processing? I see there’s a listener with aparameterChanged
method. Is this method thread-safe? Is it called in any case a parameter has been changed (for example a default value, automation etc…)? - so basically what I’d like to know is, is it worth spending time to deal with
AudioProcessorValueTreeState
or should I stick with my old method with justAudioProcessorParameter*
?
Would be nice if someone from ROLI (@fabian?) could create a dedicated thread/tutorial with a better explanation of the parameters system.