In the ProcessBlock method, I set/use this parameter doing: parameters.getParameter("someParamName")->setValueNotifyingHost(someValue);
and auto* param = dynamic_cast<juce::AudioParameterInt*>(parameters.getParameter("someParamName"));
My question is the following. Would I be ok to do set a variable to the result of parameters.getParameter("someParamName") once in the prepareToPlay method of the AudioProcessor, or even in the AudioProcessor constructor (and set an object member with this) or should I do the getParameter at each ProcessBlock ?
(the createParameterLayout method is only called once at object constuction time)
You’re perfectly fine storing the result of parameters.getParameter(“someParamName”) in the constructor or prepareToPlay as a member variable and reusing it in processBlock. This approach is more efficient and commonly used in JUCE plugins. Just ensure that your parameter layout remains static after initialization, and you should have no issues.
If you know the parameter IDs and layout won’t change, retrieving and storing the pointer in the constructor is the most efficient and clean approach.
If you need to defer initialization until the audio context is known (e.g., sample rate or block size dependencies), use prepareToPlay.
One last thing: If you need to cast to a specific type like AudioParameterInt, consider storing the casted pointer directly (e.g., juce::AudioParameterInt* someParamInt) to avoid repeated dynamic_cast operations in processBlock. Just ensure the cast is valid during initialization.
You should call this function in the message thread, not the audio thread.
Not sure I understand. In the context of a standalone app (not in the plugin context, where I can rely on the host automation), my goal is to be able to account for incoming MIDI CC at their planned time.
Some GUI slider (configured as juce::AudioProcessorValueTreeState::SliderAttachment) can also affect the same parameters. So I guessed it was a good idea to put the MIDI CC (normalized) values in the AudioProcessorValueTreeState and then to use their AudioProcessorValueTreeState::Parameter value in audio processing as well as propagating them to the UI.
Now I think I’m missing something. Are the incoming MIDI CC available elsewhere than in the processBlock method ?
Ahh, you want to use MIDI to automate some parameters in Standalone. Unfortunately, I am not familiar with this usage context. However, if you look at the source code, setValueNotifyingHost would introduce a CriticalSection, which looks suspicious to me. Perhaps you can use a timer to check if there is any parameter to update?
You may want to go through the following post before using SliderAttachment. If you call setValueNotifyingHost in the audio thread, then the real-time safety problem from SliderAttachment might be concerning,
To make sure I understand correctly: let’s say I remove all the calls to setValueNotifyingHost and ignore the MIDI CC handling—would simply reading the values from the tree for a parameter that has a SliderAttachment still be a problem?
I’m totally lost now. It seems that my case is common to almost every plugin having to
expose parameters readable/writable by the host and
have the same parameters readable/writable by the plugin GUI;
But now AudioProcessorValueTreeState and its AudioProcessorValueTreeState that seemed to be exactly designed to handle this is not a valid solution ?
Okay, it sounds like I’ll need to do a lot more reading to get this right—rather than trusting the mountain of tutorials that advocate using AudioProcessorValueTreeState and SliderAttachment in the GUI.
I initially chose JUCE assuming that these common problems had standardized, state-of-the-art solutions, but it seems I was overly optimistic!
(This makes me wonder if I should just use MIDI CC to control my parameters and skip the GUI entirely. Since MIDI events have sample-accurate timing, the resulting audio wouldn’t be affected by buffer size, (which is weird from the start), unlike parameter-based approaches.)
Sorry for the rant and thanks a lot for your help !
JUCE’s parameter handling was written when VST2 was the standard.
Since then the various audio plugin APIs that JUCE abstracts have added support for sample-accurate parameters, and often provide for thread-safe parameter updates also. It’s just that JUCE has not provided an abstraction for that yet (JUCE has plans to support sample-accurate parameters and also MIDI 2.0 in JUCE 9 though).
I understand abstraction can mean being stuck to the least common denominator. But VST3 brought sample-level parameter changes in 2008, that’s 4 years after JUCE 1.0 and 17 years ago!