Std::vector of dsp::FIR::Filter => attempting to reference a deleted function

dsp_module

#1

Hi folks,

I am trying to implement a MIMO (multiple input multiple output) FIR filter using dsp::FIR::Filter.
Therefore I want to create a std::vector of multiple dsp::FIR::Filter. My problem is that I get the following error:
Error C2280 ‘juce::dsp::FIR::Filter &juce::dsp::FIR::Filter::operator =(const juce::dsp::FIR::Filter &)’: attempting to reference a deleted function

class mimo
{
public:
    mimo(int numberOfInputChannel, int numberOfOutputChannel, int samplesPerBlock)
        {
            firFilter.assign(numOutputChannels * numInputChannels, juce::dsp::FIR::Filter<float>());
        }
private:
    std::vector<juce::dsp::FIR::Filter<float>> firFilter;
            ....
};

Does anyone know what the cause is and how to avoid it?

Thanks a lot!


#2

That error is because the Filter class doesn’t support copy assignment, which std::vector requires for that operation. You could instead do something like:

std::vector<juce::dsp::FIR::Filter<float>> tmp (numOutputChannels * numInputChannels);
firFilter.swap (tmp);

#3

Thank you for the fast response! I will try that :hugs:


#4

Okay that worked fine. But now I’ve got another problem regarding dsp::FIR::Coefficients. I make a vector of dsp::FIR::Coefficients, initialize them and then I assign them to the corresponding dsp::FIR::Filter with

firFilter.at(n * numberOfInputChannel + m).coefficients = &filterCoefficients.at(n*numberOfInputChannel + m);

My class now looks like that:

class mimo
{
public:
    mimo(int numberOfInputChannel, int numberOfOutputChannel, int samplesPerBlock, const std::vector<float>& firFilterCoefficients)
    {
        filterLength = firFilterCoefficients.size() / (numberOfInputChannel * numberOfOutputChannel);

	filterCoefficients.assign(numberOfOutputChannel * numberOfInputChannel, juce::dsp::FIR::Coefficients<float>(filterLength));

        for (int n = 0; n < numberOfOutputChannel; n++)
	{
	    for (int m = 0; m < numberOfInputChannel; m++)
	    {
	        auto* c = filterCoefficients.at(n*numberOfInputChannel + m).getRawCoefficients();
		for (int i = 0; i < filterLength; i++)
		{
	            c[i] = firFilterCoefficients.at(n * numberOfInputChannel * filterLength + m * filterLength + i);
		}
            }
        }

        std::vector<juce::dsp::FIR::Filter<float>> tmp(numberOfOutputChannel * numberOfInputChannel);
	firFilter.swap(tmp);

        for (int n = 0; n < numberOfOutputChannel; n++)
        {
            for (int m = 0; m < numberOfInputChannel; m++)
	    {
	        firFilter.at(n * numberOfInputChannel + m).coefficients = &filterCoefficients.at(n*numberInputChannel + m);
	    }
        }
    }
private:
    std::vector<juce::dsp::FIR::Coefficients<float>> filterCoefficients;
    std::vector<juce::dsp::FIR::Filter<float>> firFilter;
            ....
};

That code compiles but when I start debugging, I get an exception at this jassert() :

bool decReferenceCountWithoutDeleting() noexcept
    {
        jassert (getReferenceCount() > 0);
        return --refCount == 0;
    }

I hope someone can give me a hint :sweat_smile:

Thanks!


#5

IIRC the Coefficients class is a ReferenceCountedObject, so you are taking the address of the Ptr object, which references it without changing the reference count. But when the stack is unwound, the reference count is decremented twice for the same Ptr.

The copy constructor was probably disabled for a purpose…


#6

@daniel How could I avoid that? How can I create dsp::FIR::Coefficients with custom values for the coefficients and pass them to the belonging dsp::FIR::Filter object? I see that in the FirFilterDemo the coefficents are designed with the FilterDesign<float>::designFIRLowpassWindowMethod() but I will define the coefficients myself.


#7

The easy answer is: have a look at how designFIRLowpassWindowMethod() works, and do the same thing, but with your own calculations


#8

Okay, I think I’ve got it. I needed to use

filterCoefficients.assign(numOutputChannels * numInputChannels, juce::dsp::FIR::Coefficients<float>::Ptr{ nullptr }); 
...
for (int n = 0; n < numOutputChannels; n++)
{
    for (int m = 0; m < numInputChannels; m++)
    {
        filterCoefficients.at(n * numInputChannels + m) = new juce::dsp::FIR::Coefficients<float>(filterLength);
...

Thanks for the help! :grinning:


#10
juce::dsp::FIR::Coefficients<float>::Ptr{ nullptr }

otherwise known as

{}

:slight_smile: