Osmophile

Osmophile is a lab notebook, cookbook, art project, blog, poetry collection, technical manual, and aspiring labyrinth.

Substation's Ladder Lowpass Filter

2022-01-01, Coriander V. Pines

Substation’s “LP4” filter uses a unique realtime DSP implementation of a famous (ly expensive) analog ladder lowpass filter. In particular, the implementation allows for controlled and frequency-compensated resonance and highly accurate frequency tracking. In fact, it can be used as an oscillator. The algorithm is described below.

For input signal x[n], cutoff frequency f_c[n] in Hz, and resonance r[n] \in [0, 1], update the filter state using

\begin{align*} D_0[n] &= -c\ g[n] \tanh^\star\left(\frac{x[n] + r^\star[n]\ S_3[n-1]}{c}\right) - g[n]\ S_0[n-1] \\ S_0[n] &= S_0[n-1] + D_0[n] + D_0[n -1] \\\\ D_1[n] &= g[n]\ S_0 [n] - g[n]\ S_1[n-1] \\ S_1[n] &= S_1[n-1] + D_1[n] + D_1[n -1] \\\\ D_2[n] &= g[n]\ S_1 [n] - g[n]\ S_2[n-1] \\ S_2[n] &= S_2[n-1] + D_2[n] + D_2[n -1] \\\\ D_3[n] &= -c\ g[n] \tanh^\star\left(\frac{S_3[n-1]}{c}\right) + g[n]\ S_2[n] \\ S_3[n] &= S_3[n-1] + D_3[n] + D_3[n -1] \end{align*}

where

\begin{align*} g[n] &= \frac{\pi f_c[n]}{f_s} \\ r^\star[n] &= r[n] \left(4 - \frac{f_c[n]}{7500}\right). \end{align*}

\tanh^\star(\cdot) is a piecewise rational approximation to \tanh(\cdot),

\tanh^\star(x)= \begin{cases} -1 & \text{if } x \leq -3\\ \frac{27x + x^3}{27 + 9x^2} & \text{if } x \in (-3, 3) \\ 1 & \text{if } x \geq 3 \end{cases}

and c is the filter drive; for x[n] \in [-1, 1], c = 0.8 is suggested. I have not tested modulating c, though it would probably sound okay with enough oversampling and slew limiting.

The filter update section should be oversampled by at least 6× when running at audio rates (remember to adjust f_s accordingly).

Multiple filter outputs are available:

\begin{align*} y_{LP1}[n] &= -(1 + r[n])\ S_0[n] \\ y_{LP2}[n] &= -(1 + r[n])\ S_1[n] \\ y_{LP3}[n] &= -(1 + r[n])\ S_2[n] \\ y_{LP4}[n] &= -(1 + r[n])\ S_3[n] \\ y_{BP2}[n] &= S_0[n] - S_1[n] \\ y_{BP4}[n] &= 2 S_1[n] - 4 S_2[n] + 2 S_3[n] \\ \end{align*}

Highpass outputs are possible, but of low quality.