Non-allocating alternatives for the IIR::Coefficients::make... functions

First of all: I really like the dsp classes :slight_smile:

However, when it comes to the IIR::Coefficient class, I feel like I’m missing something obvious. To calculate filter coefficients, there are a lot of nice make... functions. After having calculated the coefficients, these functions internally allocate a new coefficient struct to return and populate it with the calculated coefficients. While I like the ref-counted approach of this, it makes these functions unsafe for all situations, where the calculation would happen on the audio thread. This is especially the case, if coefficient recalculation happen on parameter changes, which are invoked from the audio thread in case of VST3 plugins.

As this seems to be such a normal use-case and the solution to this seems so easy to implement, I wonder if I’m really missing something obvious here? :sweat_smile: Is there any functionality I didn’t find to recalculate the coefficients and place them into an already existing, pre-alloated IIR::Coefficient struct, besides of implementing my own free function with basically a copy of the coefficient calculation code found inside the IIR::Coefficient class? Maybe @IvanC as the designer of the class could share some insight?

Bump

if only juce classes were allocator aware, or at least supporting c++17 pmr memory resources, this would be trivial to tweak by using a bump allocator with some preallocated block.

1 Like

Mhm, while these are interesting options for containers like AudioBuffer, Strings or all the Array classes, I’m not sure if this would be such a trivial solution to this problem, at least not from the viewpoint of every JUCE user. Not all of them are pro level C++ programers, if you come from a more DSP background reading something like std::pmr::polymorphic_allocator could maybe not seem like a trivial soultion to your problem :smiley:

What I think of would be something like adding a constructor like

IIR::Coefficients<NumericType>::Coefficients (int numCoefficient)
{
    coefficients.ensureStorageAllocated (numCoefficients);
    for (int i = 0; i < numCoefficients; ++i)
        coefficients.add (NumericType());
}

To create a pre-alloated coefficient array.

Then add a member functions like

void IIR::Coefficients<NumericType>::setCoefficient NumericType b0, NumericType b1,
                                                    NumericType a0, NumericType a1)
{
    // like the corresponding constructor
}

void IIR::Coefficients<NumericType>::setCoefficient NumericType b0, NumericType b1, NumericType b2,
                                                    NumericType a0, NumericType a1, NumericType a2)
{
    // like the corresponding constructor
}

Add non-static member function variantions of the make functions like

void IIR::Coefficients<NumericType>::computeFirstOrderLowPass (double sampleRate, NumericType frequency)

which contain the code of the current make ones but call setCoefficients where the current ones call new. The original make functions could remain and use the new constructor internally to first pre-allocate a new Coefficient struct, then call compute on it and return the newly allocated coefficients.

If I find some time next week, I could create a Pull Request with these changes, but some feedback from the JUCE team on what they think about all this would be great.

1 Like

bump