The legacy parameter methods in AudioProcessor which were marked deprecated over four years ago.
Are they actually going to be removed from the interface (please don’t), or can we treat that as an advisement to use the AudioProcessorParameter classes (please do)?
I know myself and others have completely different abstractions for handling parameters, and removal of those methods will either force us to maintain a fork or write wrapping code around the parameter classes’ interfaces.
note that those AudioProcessor methods were deprecated, but the comments were not changed and still read: NOTE! This method **will eventually** be deprecated! instead of This method is deprecated!
btw, I noticed that AudioProcessor::setParameterNotifyingHost() is not deprecated. not sure if on purpose or not?
I don’t really understand what the wrapper classes help with? I’m trying to avoid AudioProcessorParameter and AudioParameterValueTreeState
Is there anything you cannot do if you use this wrapper? If you can present a compelling argument then that might stop us removing the methods.
It’s not so much what the abstraction can/can’t do so much as how they do it, and removing the “raw” parameter API will either force me to change designs or write a ton of boilerplate to fit a square peg into a round hole. That’s not to say I don’t use the classes ever, or think they don’t do their job, just that I would like the freedom to avoid them. I understand that “my code works now and won’t if you change stuff” isn’t the most compelling argument.
Here’s some arguments for keeping the API:
The Parameter/ValueTreeState classes are not zero cost abstractions and hide locking behavior (e.g. setValueNotifyingHost on a parameter with listeners which is called from operator=, which could be called from the audio thread, and I suspect plenty of people do).
The new-er API is not very cache-friendly (have to take care to deal with cache locality of parameters used together in the DSP)
Certain abstraction models, (like an Entity-Component System), are much simpler to deal with through the legacy API than the parameter classes.
With the exception of AUv3 (to my knowledge), all the plugin APIs have the same conceptual model for reporting parameters’ existence and changes to the host. If the primary goal of the AudioProcessor class is to serve as a least common denominator for those APIs, it does not make sense to abstract over an API that doesn’t need abstraction.
Not all of us are using AudioProcessor as the core of a product, rather as an API to target, or a prototyping system. The legacy API is easy to target or wrap, the Parameter classes are not.
I know maintaining an API is not free, and that there are probably features you intend to implement through the parameter abstraction (like you did with parameter groups, maybe sample accurate automation in the future?). But I don’t see any added value in removing the legacy API. To the contrary, it removes functionality that myself and others rely on.
You will not be able to avoid AudioProcessorParameter, though AudioParameterValueTreeState is completely optional.
The wrapper class shows how all of the deprecated AudioProcessor methods relate to calls via an AudioProcessorParameter. You can simply add those methods to your AudioProcessor subclass (or probably just remove override keyword) and have the wrapper call those methods on your subclass. There really isn’t much boilerplate required at all to keep your core functionality identical to how it was before - calls to the deprecated methods will simply be routed via the wrapper.
I am not 100% sure about how this works, but I do have a question.
Some plugins have hundreds of parameters. If I wrap a plugin the old way, then, as far as I understand, when it is queried about some parameter, it queries the hosted plugin. If that parameter is then left alone from that point on, nothing further happens. On the other hand, if I have to create objects to represent each parameter (and my current project will involve multiple instances of each plugin, so towards thousands of parameter-class objects, many of which may never need to be used), I’m just wondering if I’m using up memory needlessly by creating all those objects that may or may not be used, or may be set once and never changed.
Just pointing out, that to have a persistent value, you don’t need to create a parameter. The parameter classes are only needed, if you want to automate that value from the host.
You can put your state in the public AudioProcessorValueTreeState::state tree, so it will be conveniently saved alongside the parameters.
Or you write your bespoke save/load method in setStateInformation and getStateInformation.
But if you need the parameters exposed to host automation, I think the memory footprint of the parameter classes is rather small.
So, at compile time, my plugin won’t know how many parameters the hosted plugin will need. It also won’t know, at compile time, how many instances the user will need. If it’s possible to create these Parameter classes on the fly when one is changed, I can put that off until they’re changed, but it doesn’t sound like this is the case, as I’m being told I need to use another class as listener for each parameter in order to know when they change.
I suppose “rather small” is relative. I don’t know yet whether it will be bad to do it this way, but it sounds like it will indeed be more memory.
Yes, I also hit this restriction. It would be nice, if a plugin could dynamically add additional parameters, but the majority of hosts don’t allow that.
At the same time I can understand that, since considering, that changing one parameter could trigger a change of numbers of parameters, this is quite an amount of complexity on the host’s side.
I don’t mean changing the number of parameters a plugin registers with a host. I mean changing the number of AudioProcessorParameter objects I create to interact with the plugin.
I suppose most hosts aren’t also plugins, and don’t juggle 10-20 instances of each plugin.
If it comes down to it, I’ll happily use an outdated version of JUCE if I have to. It isn’t a project I expect to spend the rest of my life updating. I just saw this open question asking for disadvantages of “the new way”.
Then I’m not sure why this topic exists.
My understanding is that, e.g., “processor->getParameter (parameterIndex)” and “processor->setParameter (parameterIndex, newValue)” will some day no longer exist, and that AudioProcessorParameter objects are the replacement for them.
The action of getting and setting parameter values is obviously NOT only needed when changing the number of parameters a plugin registers with the host.
Ah, understood. Right, I do want to change the values of parameters, but not the number of them. It just seems odd to need to create permanent objects for all individual internal values when some may or may not need to be manipulated.