Beginners question - use of AudioFloatParameter


#1

Hi all,

In the past I’ve written some plug-ins with a few parameters with the old get/setParameter functions and a switch of the index in each of these.

I’m now trying to use the new AudioFloatParameter class and addParameter in the AudioProcessor’s constructor.

My question is about retrieving the values (I’m just using the hosts default GUI for now to test things). Say I have a delay class which I which I want to write into to change the delay time when the host GUI is changed. Previously I’d pick up the index and value in setParameter and pass down into my delay class here, subsequently being picked up in processBlock.

From the JUCE examples, I’m thinking I now need to do this in processBlock. Indeed this works, but is this correct? If there were then multiple parameters, I’d have to be updating all of them regardless in processBlock, which seems inefficient when that’s not the parameter being changed. Wasn’t this avoided using the old ‘setParameter’ through the switch (maybe this was inefficient though and I just didn’t realise?!)

Have I just misunderstood something here?!

Any help greatly appreciated.


#2

Yes, the new parameter classes make binding parameters changes to the processor a bit more complicated. If you look around there is a great solution using lambdas, alternatively you can still write your own methods the same was as you used to. Making a subclass of the parameter float class which has a listener API you could attach some callback functions to would be a good solution as well.


#3

Maybe take a quick look at this:


#4

Thanks for this. Seems that was the one thread I’d missed/mind skipped over when searching the forum before posting!

I moved to the AudioProcessorValueTreeState but still have a load of ifs in the listener callback to determine which parameter was changed. That was what I was hoping to avoid. I’ll get studying the lambda method and maybe one day understand these!


#5

One thing I tried with AudioProcessorValueTreeState was to have a key value pair container of parameterID’s as the keys and a callback lambda as the value.

So say:

std::map<String, std::function<void(float)>> parameterCallbacks; 

Then you can insert a key - value callback on a parameterID when constructing your processor:

//The this pointer is referring to your AudioProcessor and filter1 is some member DSP object
 auto cutoffParamCallback = [this] (float newCutoff) { this->filter1->setCutoff(newCutoff); };

parameterCallbacks.insert(std::make_pair(cutoffParameterID , cutoffParamCallback ));

Then finally in your AudioProcessorValueTreeState::Listener (probably your processor) callback you do:

void MyCoolProcessor::parameterChanged(const String& paramID, float newValue)
{
    auto callback = parameterCallbacks.find(paramID)->second;
    
    /**
     * callback should be our lambda object so we can just use the call operator to trigger the callback
     * on parameter change. 
     */
    callback();
}

Apologies if there is any dodgey syntax there. Just typed it in directly on the forum.

Someone more learned might not agree with the approach but I think it’s sound to avoid all the if else checking? (stand by for a JUCE pro to trash this…) Not sure about the overhead of searching the map vs the conditional checks when you start to have a large number of parameters (might be something to look into)