Why is getRawParameterValue() called in processBlock - isn’t it better and ok to get the pointers somewhere that only gets called once (e.g. during construction of the Audio Processor)? I note that it does a linear search through the parameters every time this is called.
Are the raw values thread-safe? I’m guessing ‘sort of’ ?
Each time you have a call to PRocessBlock, the parameters may have changed.
In other frameworks, you would have a setValue() call of some sorts, so you wouldn’t have to check each time in the processBlock function these values.
I think this is the main drawback of JUCE at the moment (with the fact that you don’t get a parameter hierarchy).
In addition to the setValue() method there’s the (soon to be deprecated) parameterChanged() method in AudioProcesssor, where each plugin parameter is assigned an index and you can use a giant switch statement to set internal variables whenever a parameter is called.
One thing that I’m working on now is to derive a class from AudioProcessorParameter and give it a callback in the constructor. For example something like this
Then say we have a gain plugin, we can make the parameter class (which acts as a wrapper for an atomic variable) talk to an underlying variable in the plugin processor class by initializing the callback with a lambda expression when the parameter is constructed.
class GainPlugin : public AudioProcessor
{
public:
GainPlugin ()
: /* yada yada yada */
{
//initialize the callback with a lambda expression
addParameter (gainParam = new CustomParameter ([this] () -> void { this->gainVal = this->gainParam->getValue(); })
}
//..... etc etc
void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) override
{
for (int channel = 0; channel < buffer.getNumChannels())
{
float* channelData = buffer.getWritePointer (channel);
for (int sample = 0; sample < buffer.getNumSamples())
channelData[sample] = gain * channelData[sample];
}
}
private:
ScopedPointer<CustomParameter> gainParameter;
float gain;
};
I will say that I haven’t tested this thoroughly, but I needed to roll my own parameter class anyway and this made things easier. Hope this helps or gives you other ideas, I personally think the parameter classes are a little too dense and too OOP-y. I would much rather keep the parameterChanged() method around.
You don’t have to check all the parameters during every processBlock. Just add a parameter listener any/all of your parameters and then deal with whatever changed in the parameterChanged() handler.
The best way I found was using the SliderAttachments in AudioProcessorValueTreeState etc.
And if you like that pattern, I have the same done for the “normal” ValueTree, see here:
me too… It’s only for really simple stuff, and as soon as you start working with state (saving the plugin state, restoring it, changing presets), all hell breaks loose.
I don’t believe so. I just recently switched to using it in a very-close-to-release beta plugin with 76 parameters and it’s working very well…with some added parameter wrapper classes for utility functions.
And my setStateInformation() looks like this (minus some error checking):
ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
XmlElement* parmsXml = xmlState->getChildByName(kParmsStateTag);
XmlElement* globalsXml = xmlState->getChildByName(kGlobalsStateTag);
auto state = ValueTree::fromXml(*parmsXml);
parms.state = state;
And thanks to the Button & Slider attachments, the UI is always in sync. I did have to roll my own class for a MultiButton Attachment, but I basically modified the SliderAttachment code and made it work for an array of Buttons.
Honestly, having switched to the ValueTree parameters and the attachment class simplified my UI code tremendously.Everything stays in sync easily.
But there could definitely be some more example code for this as well as some more robustness to the AudioProcessorValueTreeState class and it’s parameters.
I had a binary state befre that I wanted to keep. But this worked, it’s the preset that didn’t. Now, I will try reading an XML again…
I still have the huge parameter mess. I’m not sure checking dozens of parametes in a ValueTree is really efficient!
Well, you’re really only checking the one that changed. Granted, you end up with a ton of if statements on a String. I don’t know why they didn’t make the paramID an int. In my wrapper class, I have an int ID and use that for a switch statement.
Indeed, tbut that’s when I have the ValueTree Listener.
The “harder” part was that you don’t have all the information in the tutorial, you need to dig here and there and there is no official proper pattern to solve these simple issues.
I’m new to JUCE and wonder if reading raw parameter values is possible in a fast way without always calling mytree.getRawParameterValue everytime. (costs much in processBlock())
I’d like to get back to this point of jimc’ original question:
I didn’t find any answer to this part of the question. (hope, i didn’t oversee it).
However I’ve tried exactly doing this in the constructor of my processor: