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.