Implementing a DSP class that contains includes and namespaces (Vinne Falco DSPFilters)

Hi Gebre,

Jordan is right when he says you shouldn't be allocating memory inside processBlock, but there are a few other things you need to change as well.

What you've done is allocate the filter on the stack – it’s in scope within the braces in the processBlock() function and then it’s discarded just after you’ve called process on the filter itself. This is a problem because IIR filters rely on maintaining the state from previous calls. Also, there’s really no need to redesign the filter for each call to processBlock(), this can be done in your plugin constructor instead.

So what you need to do is define your filter as a member variable in the header file, set it up in the plugin constructor, and then do the processing in processBlock(). It’s also a good idea to define the filter pointer as a ScopedPointer so that JUCE tidies up after you.

The other thing to think about is the filter parameters structure. You can find out the sampleRate in prepareToPlay() – so that’s the best place to set the first argument. However if you plan on letting users vary the filter frequency or Q, then you need to update those parameters in processBlock(). Again, set up your parameters structure as a member variable (also notice that I referred to f1 and params1. If you have more than one filter, then you don’t want to lose track of which is which).

// PluginProcessor.h

private:
       ScopedPointer<Dsp::Filter> f1;
       Dsp::Params params1;

 


// PluginProcessor.cpp

// Constructor
DspFiltersDemoAudioProcessor::DspFiltersDemoAudioProcessor()
{
       // "1024" is the number of samples over which to fade parameter changes
       f1 = new Dsp::SmoothedFilterDesign <Dsp::RBJ::Design::LowPass, 2> (1024);
}

// prepareToPlay()
void DspFiltersDemoAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // Use this method as the place to do any pre-playback
    // initialisation that you need..
    params1[0] = sampleRate; // sample rate
}

// processBlock()
void DspFiltersDemoAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    // Clear excess output channels
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
       buffer.clear (i, 0, buffer.getNumSamples());

    // If these were static you could just do it once in prepareToPlay(), but you're usually going to
    // want to hook these up to parameters so the user can change them at runtime
    params1[1] = 4000; // cutoff frequency
    params1[2] = 1.25; // Q
    f1->setParams (params1);


    // Check that there are at least two channels before we process our 2 channel filter
    jassert (getNumInputChannels() >= 2);

    // Notice that buffer provides us a nice way to get the array of audio data
    f1->process (buffer.getNumSamples(), buffer.getArrayOfWritePointers());
}

Regards,
Andrew