Cascading allpass filters

Hi, I’m trying to implement some different allpass-based filter algorithms. I already got a first order (lp/hp) and second order (bandpass/notch) filters working well. That gave me inspiration to start experimenting with cascading ap filters. Here’s my implementation of the second order processing. I’m wondering how I could do this programatically to get a cascading filter which should produce some comb-filtering. I’m not super experienced in dsp or c++ so some of the variable names might be a bit confusing…

float AllpassFilter::processSecondOrder(int channel, float inputSample) {
    auto xn = inputSample;
    auto yn1 = a1 * xn + dn_1[channel];
    dn_1[channel] = xn - a1 * yn1;
    
    auto yn2 = a1 * yn1 + dn_2[channel];
    dn_2[channel] = yn1 - a1 * yn2;

    switch (mFilterType) {
        case Type::bandstop: return outputSample = scaling * (xn + 1.f * yn2);
        case Type::bandpass: return outputSample = scaling * (xn - 1.f * yn2);
        default: break;
    }
    return outputSample;
}

Something that achieves this as this is not good to do manually. I’m struggling to figure out how I should store the output samples of the previous stages to pass to the next stage (yn_x):

float AllpassFilter::processCascading(int channel, float inputSample) {
    auto xn = inputSample;
    
    auto yn1 = a1 * xn + dn_1[channel];
    dn_1[channel] = xn - a1 * yn1;
    
    auto yn2 = a1 * yn1 + dn_2[channel];
    dn_2[channel] = yn1 - a1 * yn2;
    
    auto yn3 = a1 * yn2 + dn_3[channel];
    dn_3[channel] = yn2 - a1 * yn3;
    
    auto yn4 = a1 * yn3 + dn_4[channel];
    dn_4[channel] = yn3 - a1 * yn4;
    
    auto yn5 = a1 * yn4 + dn_5[channel];
    dn_5[channel] = yn4 - a1 * yn5;

    switch (mFilterType) {
        case Type::experiment1: return outputSample = scaling * (xn + 1.f * yn5);
        case Type::experiment2: return outputSample = scaling * (xn - 1.f * yn5);
        default: break;
    }

    return outputSample;
}

I recently made this video about a bunch of Allpass filter code I was given. Various classes with different pros and cons, especially in regard to cascading filters. However if you watch the video beware that there were some mistakes in what class is good or bad in what way exactly. I fixed the code comments though, so when you look at the actual project on GitHub, that’s cool

1 Like