Search guides and the APICtrl K
  1. API reference
  2. DSP

filter_design.h

Filters steeper than one biquad.

#include <sonore/filter_design.h>
On this page

Design notes

dsp.h has the RBJ cookbook, which is every shape a SINGLE biquad can be. A 24 dB/octave lowpass is not one of those shapes, and neither is a 48 dB crossover or an anti-alias filter worth the name. Getting there means more than one section, and the only interesting question is what Q each section takes: cascading identical biquads does NOT give a Butterworth, it gives a droopy passband and a -6 dB point that has wandered off the cutoff.

What decides it: the poles of an Nth-order Butterworth sit at equal angles on a semicircle, and each conjugate pair becomes one biquad whose Q is set by where that pair sits. Order 4 is the familiar 0.54 and 1.31: two very different sections that are flat together and wrong separately.

Odd orders need a real pole as well, which is a FIRST-order section: not a biquad with something zeroed by accident, but a deliberate one-pole stage, because a 5th-order filter that quietly rounds to 4th or 6th is a filter whose slope is not what the user asked for.

Types 5

One section of a Chebyshev Type I design: where its pole pair sits.

Butterworth puts its poles on a circle; Chebyshev puts them on an ELLIPSE, squashed towards the imaginary axis by an amount the ripple decides. That squashing is the whole trade: the poles crowd nearer the passband edge, the transition gets steeper, and the passband stops being flat and starts to ripple by exactly the amount that was asked for.

frequencyScale is the part Butterworth does not have. Each section sits at a DIFFERENT frequency -- the pole's distance from the origin -- rather than all of them at the cutoff, and ignoring it gives a filter that looks plausible and has the wrong corner.

The bilinear substitution's normalised coefficients, shared by both kinds of section below. ok is false for a degenerate denominator.

One section of a Chebyshev Type II design.

Type I ripples in the PASSBAND and is flat in the stopband; Type II is the other way round, and that is usually the trade you want. An anti-alias filter's stopband is thrown away, so ripple there costs nothing, while ripple in the passband is ripple in the signal you are keeping.

It is not an all-pole design. Type I gets its steepness from where its poles sit; Type II gets it from ZEROS -- notches placed up the stopband, which is why its rejection is equiripple rather than falling away for ever, and why each section needs a numerator of its own.

The poles are the reciprocals of Type I's, which is the whole construction: inverting the frequency axis turns a rippling passband into a rippling stopband.

template <int MaxOrder = 8> class CascadedIir

A cascade of biquads, plus at most one first-order section.

MaxOrder bounds the storage, so a plugin pays for the steepest filter it might ask for and nothing more. Designing past it is REFUSED rather than clamped: a caller that asked for 12th order and silently got 8th has a crossover that leaks, and would never find out from here.

template <int MaxOrder = 8> class LinkwitzRileyN

A Linkwitz-Riley crossover of any even order.

Two Butterworths of half the order in cascade, which is the whole definition: doubling the poles is what puts both bands 6 dB down at the crossover instead of 3, and what makes them sum FLAT. A pair of plain Butterworths leaves a 3 dB bump there, which is audible on anything with energy near the corner and is the reason multiband processors use this and not the obvious thing.

effects.h has a fixed 4th-order version, which stays: it is the common case and it is smaller. This is for a caller that wants to CHOOSE: 12, 24 or 48 dB per octave is a control a multiband plugin should be able to offer.

ODD orders are refused. An odd-order Linkwitz-Riley does not exist: the construction is two identical halves, and half of an odd number is not a filter order.

Functions 8

↑↓ to move↵ to openEvery public name in the headers, and every guide