Alex Benjamin
Alex Benjamin

Reputation: 11

4th Order Butterworth Filter Swift

I am currently trying to implement a 4th order butterworth, band-pass filter with cutoff 0.05 Hz to 0.15Hz.

The following is my attempt, but the result is not good in the sense that a lot of other frequencies are still getting through.

// Function to compute bandpass filter coefficients based on center frequency and quality factor.
func makeBandpassFilterWithFcAndQ(filter: inout [Double], Fs: Double, Fc: Double, Q: Double) {
    let K = tan(.pi * Fc / Fs)
    let norm = 1.0 / (1.0 + K / Q + K * K)
    filter[0] = K / Q * norm
    filter[1] = 0.0
    filter[2] = -filter[0]
    filter[3] = 2.0 * (K * K - 1.0) * norm
    filter[4] = (1.0 - K / Q + K * K) * norm
}

// Function to compute bandpass filter coefficients based on frequency range.
func makeBandpassFilterWithFreqRange(filter: inout [Double], Fs: Double, Fbtm: Double, Ftop: Double) {
    //let Fc = sqrt(Fbtm * Ftop)
    let Fc = 0.10
    let Q = Fc / (Ftop - Fbtm)
    //let Q = 0.99
    makeBandpassFilterWithFcAndQ(filter: &filter, Fs: Fs, Fc: Fc, Q: Q)
}

// Function to apply bandpass filtering to a signal
func applyBandpassFilter(signal: [Double], fs: Double, filterCoefficients: [Double]) -> [Double] {
    let numRawDoubles = vDSP_Length(signal.count)
    var rawDoubles = signal
    var filteredDoubles = [Double](repeating: 0.0, count: signal.count)

    let rawStride = vDSP_Stride(1)
    let filteredStride = vDSP_Stride(1)

    // Apply the filter using vDSP_deq22
    vDSP_deq22D(&rawDoubles, rawStride, filterCoefficients, &filteredDoubles, filteredStride, numRawDoubles - 2)

    return filteredDoubles
}

// Function to apply a 4th order Butterworth bandpass filter
func apply4thOrderButterworthBandpassFilter(signal: [Double], fs: Double, Fbtm: Double, Ftop: Double) -> [Double] {
    // First set of coefficients
    var filterCoefficients1 = [Double](repeating: 0.0, count: 5)
    makeBandpassFilterWithFreqRange(filter: &filterCoefficients1, Fs: fs, Fbtm: Fbtm, Ftop: Ftop)
    
    // Apply the first filter
    let filteredSignal1 = applyBandpassFilter(signal: signal, fs: fs, filterCoefficients: filterCoefficients1)
    
    // Second set of coefficients (same as the first for Butterworth filter)
    var filterCoefficients2 = [Double](repeating: 0.0, count: 5)
    makeBandpassFilterWithFreqRange(filter: &filterCoefficients2, Fs: fs, Fbtm: Fbtm, Ftop: Ftop)
    
    // Apply the second filter
    let filteredSignal2 = applyBandpassFilter(signal: filteredSignal1, fs: fs, filterCoefficients: filterCoefficients2)
    
    
    return filteredSignal2
}

I have tried cascading two second order filters with no luck.

Upvotes: 1

Views: 91

Answers (0)

Related Questions