First-Order Allpass Filter

Introduction

An allpass filter passes a signal with the same gain response for all frequencies. Without affecting the gain response, an allpass filter changes the frequency phase. This response can be graphed from -π to π over the audio frequency range.

The allpass filter can be used as a building block in filter construction, using phase cancellation to form standard lowpass, highpass, bandpass, and notch filters; as well as typical effects such as chorusing, flanging, and phasing.

First Order

A first order allpass is called this because it uses a one sample delay in its implementation.

y[n] = c(x[n]) + x[n-1] - c(y[n-1])

The coefficient c is calculated from the tangent of the frequency, tf, fc is the cutoff frequency, and sr is the sampling rate:

\begin{aligned}& tf = tan\bigg(\pi \frac{f_c}{sr} \bigg) \\ & c = \frac{tf-1}{tf+1} \end{aligned}

You might notice that a frequency of 0 will result in a coefficient of -1 and a frequency at half the sample rate (the Nyquist frequency) will result in an error, as tan(π/2) is ∞. Because of this, the frequency should be limited to less than half the sample rate. The coefficient approaches 1 as the frequency approaches the Nyquist frequency.

The first order allpass filter has a phase shift of 0 at 0 Hz, π at the Nyquist frequency and π/2 at the cutoff frequency. The following C code can implement this filter. Note that double floating point variables are used for feedback terms. This is because mathematical error can build up in a feedback network, and using doubles will minimize this error.

double in1 = 0; // delayed sample 
double out = 0; // keep track of the last output 

foap(float *input, float *output, long samples, float cutoff) 
{   
    double tf = tan(PI * (cutoff/SAMPLERATE)); // tangent frequency   
    double c = (tf - 1.0)/(tf + 1.0); // coefficient     
    for(int i = 0; i < samples; i++) 
    {  
        float sample = *(input+i);   
        out = (c*sample) + in1 - (c * out); 
        in1 = sample; // remember input     
        *(output+i) = out; // output   
    }
}

Leave a Reply

Your email address will not be published.