Skip to content

NOTES

IIR — Infinite Impulse Response Filter

Recursive filter with feedback. Achieves sharp transitions with fewer coefficients than FIR; trade-offs include non-linear phase and potential instability.


Algorithm

Design Flow (Bilinear Transform)

\[ \text{Analog prototype} \xrightarrow{\text{prewarp}} \xrightarrow{\text{bilinear transform}} H(z) \xrightarrow{\text{Biquad decomposition}} \text{2nd-order cascade} \]

Step 1 — Select analog prototype

  • Butterworth


    Flattest passband
    Wider transition
    No passband ripple

  • Chebyshev I


    Passband ripple
    Sharper transition
    Ripple for steepness

Step 2 — Frequency Prewarping

\[ \omegaa = \frac{2}{T} \tan\left(\frac{\omegad T}{2}\right) \]

Both passband and stopband edges must be prewarped.

Step 3 — Bilinear Transform

\[ s = \frac{2}{T} \cdot \frac{1 - z^{-1}}{1 + z^{-1}} \]

Maps \(H(s)\) to digital \(H(z)\).

No aliasing

Unlike impulse invariance, bilinear transform is a one-to-one mapping → no spectral aliasing. Cost: frequency warping (compensated by prewarping).

Step 4 — Biquad Cascade

Decompose high-order \(H(z)\) into cascaded 2nd-order sections. Each biquad is independently stable and less sensitive to coefficient quantization.

Filtering Structure (DF2 Transposed)

Per biquad, per input sample:

\[ \begin{aligned} w[n] &= x[n] + b1 \cdot w[n-1] + b2 \cdot w[n-2] \\ y[n] &= a0 \cdot w[n] + a1 \cdot w[n-1] + a_2 \cdot w[n-2] \end{aligned} \]

IIR vs FIR

FIR IIR
Stability Always Verify poles
Phase Linear possible Non-linear
Order High Low (5-10× fewer)
Quantization Low sensitivity Higher (biquad mitigates)
Best for Phase-critical Low-latency, low-resource

API Reference

Design

int tiny_iir_design_lowpass(float *coeffs_b, float *coeffs_a,
                            int max_order, float cutoff_norm,
                            tiny_iir_type_t type, tiny_iir_design_t method);

Parameters: cutoff_norm in [0, 1] (1 = Nyquist)

Batch Filtering

tiny_error_t tiny_iir_filter_f32(const float *input, int len,
                                 const float *coeffs_b, const float *coeffs_a,
                                 int order, float *output);

Real-time Filtering

typedef struct { /* ... */ } tiny_iir_state_t;

tiny_error_t tiny_iir_init(tiny_iir_state_t *state,
                           const float *coeffs_b, const float *coeffs_a, int order);
tiny_error_t tiny_iir_deinit(tiny_iir_state_t *state);
float        tiny_iir_process_sample(tiny_iir_state_t *state, float input);
void         tiny_iir_reset(tiny_iir_state_t *state);

Notes

Poles outside unit circle → unstable

All IIR poles must lie within \(|z| < 1\). Verify after design with \(|\text{pole}| < 1\).

Bilinear warping

Warping is more severe at high frequencies. Correct prewarping is essential when high-frequency response matters.

Biquad cascade over direct form

High-order direct-form IIR is highly sensitive to coefficient quantization. Biquad cascades break the problem into independent 2nd-order subsystems.