Breaking Change: Audio Parameter ID Support

On the current tip of develop you’ll find a new feature which now correctly reports the IDs of parameters to the DAW - previously the index of the parameter would be reported to the DAW and not the ID. This fixes a long standing issue with JUCE, where adding a new parameter to your plug-in would potentially break customer’s projects such as the association of automation data with certain parameters. This also fixes and issue with VST3 bypass when adding parameters to your project.

The new feature will only be used if you are using the managed parameter system and all your parameters derive from AudioProcessorParameter (such as AudioParameterFloat, AudioParameterChoice, AudioParameterBool and AudioParameterInt) or when using the AudioProcessorValueTreeState. Note that if you have released a plug-in which is already using the managed parameter system, then this build will break your customer’s projects. However, we’ve added a new define to force JUCE to use the legacy param ids (see screenshot below). If this is enabled then JUCE will report parameter indices as IDs just like in older JUCE versions and your customer’s projects will remain in tact.

If you are still using the legacy parameter system (i.e. GetParameter/SetParameter) then everything will be as before and this change also won’t break your user’s projects.

I’m looking forward to your feedback. Please have a go and test this in every DAW possible!!

Good job with this one! Thanks.

However, If I remember correctly, VST2 does not support this kind of id, i.e. it only has the concept of indices to address automation parameter.

Can you explicitly state how does this change apply to VST2 plug-ins?

It doesn’t: VST2 still uses parameter indices. Thank you for pointing this out.

1 Like

Hi fabian,

This looks good. Is there a reason not to expose getParamChecked() as a protected member of AudioProcessor in order to allow us to use a similar pattern to test the properties of AudioProcessorParameters subclasses other than IDs?

Dan

1 Like

Will there be a warning if you updated the project and forget to activate the legacy parameter support? If not, there should be one

1 Like

What does it mean? When do i have to use a macro? I’m confused again. Its used only when AudioProcessorParameterWithID or AudioProcessorValueTreeState is used, so why plugins which are not using AudioProcessorParameterWithID have to use this macro?

I’m having a look at the AudioProcessorParameterWithID class.

The AudioProcessorParameterWithID::label String member variable is private and I can’t find anywhere where it could be defined.

Of course inheriting classes can override getLabel(), but as it’s implemented AudioProcessorParameterWithID::getLabel() could simply return an empty string rather than the never-defined not-assignable ‘label’ member. Otherwise, the full interface around the label (in constructor and/or as a setter) could be added to the AudioProcessorParameterWithID class…

Could someone at ROLI have a look please?

Also, I see that for VST3 the parameter id is a hash of the string defined in AudioProcessorParameterWithID, which does not prevent a rare but silent collision of multiple parameter IDs; what about either asserting that all parameter ID hashs are distinct at runtime, or defining this ID directly as a 32bit int (breaking change)?

You should be using this macro if you have already released plug-ins to the public using AudioProcessorParameterWithID or AudioProcessorValueTreeState before this fix was done. This is because the IDs of both classes was not reported to the host.

Yes that doesn’t seem to make much sense. Thanks for spotting this. I’ve made the label public. You can find the change on the develop branch.

The AAX/RTAS backends use strings for parameter ids. AUv3 uses int64s. I believe using a string as a parameter id is the best and simplest way to abstract away these differences given that a hash collision will be extremely rare.

Good idea! I’ve added this to the develop branch.

A four char code is the least common denominator of all the Parameter ID formats - it can be a 32-bit int, a string, or the lower half of a 64-bit int. It’s also human-readable and can be set up to make it easy to follow in a debugger (‘inpg’ is much easier to identify as the ID associated with input gain than 0x047b298d)

I haven’t dug through the changes (I rolled my own parameter handling before it was added to JUCE and have been avoiding anything post-4.0 until the channel handling settles). Does the current JUCE implementation create the Parameter ID hash off the parameter name? If so, you’ve only traded one limitation (Param IDs coupled to param order means you can’t reorder parameters) for another (Param IDs based on param name means you can never rename parameters). The Param IDs should be COMPLETELY INDEPENDENT of both the name and order of parameters. That’s the whole reason they exist. Hopefully I’m misinterpreting the discussion about the hash implementation.

Parameter ids are based on the parameter id string (normally never seen by the user) and not on the parameter name.

Yeah I see your point but I also think you could argue the other way around: a string can also be converted to any of the data formats but provides the most information and therefore is more future proof. In the end I decided for a string so that people could internally group their parameters, by giving them ids like “oscillator1/tune” etc.

1 Like

Sorry I’m confused. My plugin is using the managed parameters system but with AudioProcessorParameter and not AudioProcessorParameterWithID.

So when i read the code right, i have to use the macro, because the behavior in the wrappers looks like completely different from what they do in the previous version also when using AudioProcessorParameter instead of AudioProcessorParameterWithID

Edit:
Further explanation, it looks like with AudioProcessorParameter, there will be a hash generated from the parameter number, so this is completly different

You should be using this macro if you have already released plug-ins to the public using AudioProcessorParameterWithID or AudioProcessorValueTreeState before this fix was done. This is because the IDs of both classes was not reported to the host.

So this is also true if my plugin uses AudioProcessorParameter (if yes, your post was bit misleading )

1 Like

Yes this is true, I’ll amend my post.

I think using a macro this way is a very unhappy decision!

… the developer has to be forced to make a decision if he wants the new or the old system.

If not, the problem may appear after the plugin has rolled out to the costumer!

PS: most elegant solution is to check if the parameters were once saved with the old param-ID style, and use this dynamically

PS: the same goes for the parameter-fix for Studio One JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS