Best way to update parameter values for DSP

What’s the best practice for updating parameter values for DSP use?

As a beginner I’ve gone from using the tree values directly via apvts.getRawParameterValue(paramId) inside the parameterChanged(paramId, newValue) function, to then using the more accurate newValue to update my member variables.

Now I’ve heard that that’s still not good enough for offline rendering and automation because tree values run on a timer, and I should instead be grabbing the values directly inside processBlock. That is, by “keeping a pointer to the parameter and then getting the value inside processBlock.”

Is using parameterChanged() and newValue enough, or is that only really useful for GUI? And if it’s better to grab parameter values directly inside processBlock, where do I grab them from if not from the tree? My guess is grabbing them using getRawParameterValue(paramId) inside the processBlock will get the most accurate value.

Any help is much appreciated!

I would say the newValue from parameterChanged is the best you can get now (before JUCE 9 introducing sample-accurate automation, hopefully). But sometimes I do grab them from the tree directly if it is something as simple as a bypass flag. In such case, you can store a reference to the atomic to avoid looking up the tree via getRawParameterValue(paramId).

std::atomic<float> &bypass_;
...
bypass_(*parameters_.getRawParameterValue(zlp::PBypass::kID)) // at constructor
...
if (bypass_.load(std::memory_order::relaxed) > .5f) { // in processBlock
...

Well that’s a relief. I’m still wrapping my head around anything synchronous and asynchronous so I think I was getting confused. I take a similar approach for bypassing. Thanks a lot! I’ll keep this open to see if anybody has differing opinions or workflows.