Lesson 12 of 15

FIR Filters

FIR Filters

A Finite Impulse Response (FIR) filter is defined by its impulse response h[n]h[n] of length M+1M+1. The output is a causal convolution of the input with hh:

y[n]=k=0Mh[k]x[nk]y[n] = \sum_{k=0}^{M} h[k] \cdot x[n-k]

where x[nk]=0x[n-k] = 0 for nk<0n-k < 0. The output has the same length as xx.

Why FIR?

FIR filters are:

  • Always stable — bounded input → bounded output
  • Linear phase — symmetric hh gives constant group delay (no phase distortion)
  • Flexible — any frequency response can be approximated

Sinc Lowpass Filter

The ideal lowpass filter with cutoff fcf_c (normalized, 0<fc<0.50 < f_c < 0.5) has the impulse response:

h[n]=2fcsinc(2fc(nN/2))h[n] = 2 f_c \cdot \text{sinc}(2 f_c (n - N/2))

where sinc(x)=sin(πx)/(πx)\text{sinc}(x) = \sin(\pi x) / (\pi x) and h[N/2]=2fch[N/2] = 2f_c when x=0x=0.

For fc=0.25f_c = 0.25 (quarter-band) with N=4N=4: h=[0,0.3183,0.5,0.3183,0]h = [0, 0.3183, 0.5, 0.3183, 0]

Your Task

Implement:

  • fir_filter(x, h) — causal FIR convolution, output same length as xx
  • sinc_lowpass(fc, N) — returns N+1N+1 coefficients for ideal lowpass
import math

def fir_filter(x, h):
    result = []
    for n in range(len(x)):
        val = 0.0
        for k in range(len(h)):
            if n - k >= 0:
                val += h[k] * x[n - k]
        result.append(val)
    return result

def sinc_lowpass(fc, N):
    h = []
    center = N // 2
    for n in range(N + 1):
        x = n - center
        if x == 0:
            h.append(2 * fc)
        else:
            h.append(2 * fc * math.sin(math.pi * 2 * fc * x) / (math.pi * 2 * fc * x))
    return h
Python runtime loading...
Loading...
Click "Run" to execute your code.