IIRFilter in JuceDemoPlugin


#1

As a means of learning to create a synth plugin, I’m trying to expand the JuceDemoPlugin. My first step was to add a filter.
But, since this example has a way handling single and double floating point precision. The problem arises when trying to implement the IIRFilter class. I get the following compiler bugs:

error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a parameter of type ‘float *’ with an lvalue of type 'float’
error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a parameter of type ‘float *’ with an lvalue of type 'float’
error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a parameter of type ‘float *’ with an lvalue of type 'double’
error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a parameter of type ‘float *’ with an lvalue of type ‘double’

It seems to me that the IIRFilter class can’t handle Float type templates… (and I don’t yet exactly know how they work).

This is the code I’ve added:

PluginProcessor.h

template <typename FloatType>
void applyFilter (AudioBuffer<FloatType>&);

PluginProcessor.cpp

template <typename FloatType>
void JuceDemoPluginAudioProcessor::applyFilter (AudioBuffer<FloatType>& buffer)
{
    
    IIRCoefficients ic = IIRCoefficients::makeLowPass(m_sampleRate, 500);
    lowPassFilterLeft.setCoefficients(ic);
    lowPassFilterRight.setCoefficients(ic);
    
    const int numSamples = buffer.getNumSamples();
    
    for (int channel = 0; channel < getTotalNumOutputChannels(); ++channel)
    {
        FloatType* const channelData = buffer.getWritePointer ( channel );
    
        lowPassFilterLeft.processSamples ( channelData[0], numSamples );
        lowPassFilterRight.processSamples( channelData[1], numSamples );
    }
    
}

template <typename FloatType>
void JuceDemoPluginAudioProcessor::process (AudioBuffer<FloatType>& buffer,
                                            MidiBuffer& midiMessages,
                                            AudioBuffer<FloatType>& delayBuffer)
{
    const int numSamples = buffer.getNumSamples();

    // Now pass any incoming midi messages to our keyboard state object, and let it
    // add messages to the buffer if the user is clicking on the on-screen keys
    keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);

    // and now get our synth to process these midi events and generate its output.
    synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
    
    applyFilter (buffer); //FILTER OUTPUT

    // Apply our delay effect to the new output..
    applyDelay (buffer, delayBuffer);

    // In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getTotalNumInputChannels(); i < getTotalNumOutputChannels(); ++i)
        buffer.clear (i, 0, numSamples);

    applyGain (buffer, delayBuffer); // apply our gain-change to the outgoing data..
    
    
    // Now ask the host for the current time so we can store it to be displayed later...
    updateCurrentTimeInfoFromHost();
}

Is there a way around this error without having to adjust the IIRFilter class? Any help in the right direction would be greatly appreciated!


#2

No, you have a simple C++ problem. You are calling a function that takes a pointer to a float with directly a float. That obviously can’t work.
Provide what is required, not what you think the method should take.


#3

Well, I believe that’s what my code does. When actually providing a float I get following error:

error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a variable of type ‘const float’ with an rvalue of type 'float *'
error: C:\JUCE\examples\audio plugin demo\Source\PluginProcessor.cpp: cannot initialize a variable of type ‘const double’ with an rvalue of type ‘double *’

const FloatType channelData = buffer.getWritePointer ( channel );
    
lowPassFilterLeft.processSamples ( channelData[0], numSamples );
lowPassFilterRight.processSamples( channelData[1], numSamples );

#4

Your compiler disagrees :wink:

in your template FloatType get’s replaced with float. But getWritePointer(channel) returns a float*
That’s what Matthieu said.

The next problem you will have is, that processSamples uses a float* and not a const float*, so get rid of the const as well.

It should work, if you change that line to

FloatType* channelData = buffer.getWritePointer ( channel );


#5

That makes sense. Now I’ll have to figure out how to change my template haha. I assumed that simply adding a * to a templated variable would make it a pointer…


#6

You probably need to read a C++ book before doing anything else…


#7

Yep. Any recommendations?


#8

https://www.amazon.com/C-Programming-Language-4th/dp/0321563840/


#9

Thanks!