Breaking change: Added an option to declare plug-in parameters as either continuous or discrete, irrespective of their number of steps


#1

https://github.com/WeAreROLI/JUCE/commit/4dcce5083c9128989577617facf6bd7ed3bc67a3

Change

The method used to classify AudioUnit, VST3 and AAX plug-in parameters as either continuous or discrete has changed.

Possible Issues

Plug-ins: DAW projects with automation data written by an AudioUnit, VST3 or AAX plug-in built with JUCE version 5.1.1 or earlier may load incorrectly when opened by an AudioUnit, VST3 or AAX plug-in built with JUCE version 5.2.0 and later.

Hosts: The AudioPluginInstance::getParameterNumSteps method now returns correct values for AU and VST3 plug-ins.

Workaround

Plug-ins: Enable JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE in the juce_audio_plugin_client module config page in the Projucer.

Hosts: Use AudioPluginInstance::getDefaultNumParameterSteps as the number of steps for all parameters.

Rationale

The old system for presenting plug-in parameters to a host as either continuous or discrete is inconsistent between plug-in types and lacks sufficient flexibility. This change harmonises the behaviour and allows individual parameters to be marked as continuous or discrete.


[PATCH] stepped/ramped parameters for AAX, VST3 & AU
Fix for quantization of automation data by Logic
#2

I haven’t updated yet, but it seems to me that your commit breaks much more things than just this continuous/discrete thing.

you have replaced many calls like those:

audioProcessor.getParameterDefaultValue (parameterIndex)
processorParam->getDefaultValue()
 juceFilter->isParameterAutomatable (index))

by the (not so) new AudioProcessorParameter class ‘equivalents’:

processorParam->getDefaultValue()
param->isAutomatable()

Isn’t it going to break all the plugins for people that are still using those AudioProcessors methods?
I know those that are commented with :

 NOTE! This method will eventually be deprecated! It's recommended that you use
        AudioProcessorParameter::isAutomatable() instead.

but they haven’t been deprecated yet, and many people are not using AudioProcessorParameter yet:


#3

Ah, yes. That managed to sneak past us.

A fix has been pushed to the develop branch.


#4

Thanks so much Tom! This is looking great in most hosts so far.

One issue: REAPER doesn’t seem to correctly show discrete parameters with JUCE-made Audio Unit plugins — they still appear continuous and the string names aren’t shown. We’ve confirmed with our old non-JUCE, AU plugins that REAPER does correctly show discrete parameters. As far as I can tell, all the flags you’ve set are more or less the same as what we were doing in our AU wrapper, so I’m not sure why it doesn’t work or what’s different.


#5

I have a fix for this - it’s just working it’s way though testing and review.


#6

https://github.com/WeAreROLI/JUCE/commit/743c9d55e7eb5c1a204383ae0b0c3983e8016761


#7

Thank you! This fix is looking great, behavior is now matching our non-JUCE AU plugins. Glad to have this resolved, your work is very appreciated.


#8

Tom, there are still 2 calls to AudioProcessor::getParameters() lines 921 and 939 that won’t work when we don’t use the AudioProcessorParameter classes.

patch.txt (1,3 Ko)


#9

Another fix will appear on the develop branch shortly. Thanks again for reporting.


#10

Hello @t0m ! New issue report :wink:

Let’s say I create a new plug-in from scratch with the Projucer on macOS. In the PluginProcessor constructor, I add a new parameter that I have declared as an AudioParameterChoice in the header, and I provide three string values for the choices. I compile it in VST + AU formats.

Now in Reaper, if I open the AU version, I’ll see… the Hello World on the UI :smile: That’s fine. If I click on the “UI” button on the top right of the window associated with the plug-in, I’ll see a list of all the parameters available. That’s where the problem is…

Since we have now the isDiscrete option enabled for AudioParameterChoice, instead of a slider, we’ll see now in Reaper a ComboBox (with Reaper UI) displaying the available options. And I’ll see the three options I provided in the constructor of my PluginProcessor. If I click on the first, everything is fine. If I click on the second, it’s fine as well. But if I click on the third, for a reason I don’t get the plug-in itself works as the third was properly selected, but in Reaper it’s still the second that is displayed as the one I have clicked on.

This bug has a lot of implications, as I see the same behaviour in other DAWs, and strange things happening in Logic Pro X.

By the way, in the AudioProcessor classes, should we set the return value of “getNumSteps” for AudioParameterChoice and AudioParameterInt to other values than AudioProcessorParameterWithID::getNumSteps() a.k.a. AudioProcessor::getDefaultNumParameterSteps() since they are discrete now ?

Thanks in advance !


#11

Fixed:

https://github.com/WeAreROLI/JUCE/commit/598b7919642bd00cb1687797a70269fa6ba32baa

getNumSteps has already been changed from the default for AudioPrameterChoice (which is discrete), and I’ve now done the same for AudioPrameterInt (which is not discrete). For AudioPrameterInt this will let the user continuously select values in the automation lane, but Pro Tools, and perhaps other DAWs, can still indicate the steps in other places.


#12

Thanks t0m, and you’re right about AudioParameterInt, it shouldn’t be discrete :wink:


#13

I’m a little confused. So, to properly set the isDiscrete flag in createAndAddParameter(), I also have to override isDiscrete() and getNumSteps() and therefore, subclass AudioProcessorParameter ? But then I can’t use AudioProcessorValueTreeState.createAndAddParameter() ?

I’m definitely confused. What’s the proper way to create/use discrete parameters with AudioProcessorValueTreeState?

It always seemed odd to me that the AudioParameterFloat/Int/Bool/Choice classes did not have counterparts when using AudioProcessorValueTreeState.


#14

No, you don’t. The AudioProcessorValueTreeState::Parameter is a generic parameter, that has the same bas class like the AudioParameterFloat etc, which is AudioProcessorParameterWithID, hence you can use the same interface.

getNumSteps() is already implemented, it deduces the information from the NormalisableRange.

I think it is an alternative to the AudioParameterFloat/Int/Bool classes. But the AudioProcessorValueTreeState version has already a better interface providing the AudioProcessorValueTreeState::Listener and the different attachment classes, so IMHO there is no need for the subclasses any longer.

HTH


#15

Thanks for the reply.

This is very cool. I’ve always wondered why some other plugins’ parameters show up in MainStage’s parameter list with sliders, on/off buttons and comboBoxes when mine were all only sliders. I just added the isDiscrete flag to my parameters that are really ints & bools and viola…MainStage shows them correctly.

And now…let me see if this breaks already created automation…