## Guessing at the discretization, of the Sallen-Key Filter, with Q-Multiplier.

One concept that exists in modern digital signal processing is, that a simple algorithm can often be written, to perform what old-fashioned, analog filters were able to do.

But then, one place where I find lacking progress – at least, where I can find the information posted publicly – is, about how to discretize slightly more complicated analog filters. Specifically, if one wants to design 2nd-order low-pass or high-pass filters, one approach which is often recommended is, just to chain the primitive low-pass or high-pass filters. The problem with that is, the highly damped frequency-response curve that follows, which is evident, in the attenuated voltage gain, at the cutoff frequency itself.

In analog circuitry, a solution to this problem exists in the “Sallen-Key Filter“, which naturally has a gain at the corner frequency of (-6db), which would also result, if two primitive filters were simply chained. But beyond that, the analog filter can be given (positive) feedback gain, in order to increase its Q-factor.

I set out to write some pseudo-code, for how such a filter could also be converted into algorithms…


Second-Order...

LP:
for i from 1 to n
Y[i] := ( k * Y[i-1] ) + ((1 - k) * X[i]) + Feedback[i-1]
Z[i] := ( k * Z[i-1] ) + ((1 - k) * Y[i])
Feedback[i] := (Z[i] - Z[i-1]) * k * α
(output Z[i])

BP:
for i from 1 to n
Y[i] := ( k * Y[i-1] ) + ((1 - k) * X[i]) + Feedback[i-1]
Z[i] := ( k * (Z[i-1] + Y[i] - Y[i-1]) )
Feedback[i] := Z[i] * (1 - k) * α
(output Z[i])

HP:
for i from 1 to n
Y[i] := ( k * (Y[i-1] + X[i] - X[i-1]) ) + Feedback[i-1]
Z[i] := ( k * (Z[i-1] + Y[i] - Y[i-1]) )
Feedback[i] := Z[i] * (1 - k) * α
(output Z[i])

Where:

k is the constant that defines the corner frequency via ω, And
α is the constant that peaks the Q-factor.

ω = 2 * sin(π * F0 / h)
k = 1 / (1 + ω), F0 < (h / 4)

h   Is the sample-rate.
F0  Is the corner frequency.

To achieve a Q-factor (Q):
α = (2 + (sin^2(π * F0 / h) * 2) - (1 / Q))
'Damping Factor' = (ζ) = 1 / (2 * Q)

Critical Damping:
ζ = 1 / sqrt(2)
(...)
Q = 1 / sqrt(2)



(Algorithm Revised 2/08/2021, 23h40. )

(Computation of parameters Revised 2/09/2021, 2h15. )

(Updated 2/10/2021, 18h25… )

If a software-equalizer possesses GUI controls that correspond to approximate octaves, or repeated 1-2-5 sequences, it is entirely likely to be implemented as a set of bandpass filters acting in parallel. However, the simplistic bandpass filters I was contemplating, would also have required that the signal be multiplied by a factor of 4, to achieve unit gain where their low-pass and high-pass cutoff frequencies join, as I described in this posting.

(Edit 03/23/2017:

Actually, the parameters which define each digital filter, are non-trivial to compute, but nevertheless computable when the translation into the digital domain has been carried out correctly. And so a type of equalizer can be achieved, based on derived bandpass-filters, on the basis that each bandpass-filter has been tuned correctly.

If the filters cross over at their -6db point, then one octave lower or higher, one filter will reach its -3db point, while the other will reach its -12db point. So instead of -12db, this combination would yield -15db.

The fact that the signal which has wandered into one adjacent band is at -3db with respect to the center of that band, does not lead to a simple summation, because there is also a phase-shift between the frequency-components that wander across.

I suppose that the user should be aware, that in such a case, the gain of the adjacent bands has not dropped to zero, at the peak of the current band, so that perhaps the signal will simplify, if the corner-frequencies have been corrected. This way, a continuous curve will result from discrete settings.

Now, if the intention is to design a digital bandpass filter with greater than 6 db /Octave falloff curves, the simplistic approach would be just to put two of the previous stages in series – into a pipeline resulting in second-order filters.

Also, the only way then to preserve the accuracy of the input samples, is to convert them into floating-point format first, for use in processing, after which they can be exported to a practical audio-format again. )

(Edit 03/25/2017 :

The way simplistic high-pass filters work, they phase-shift the signal close to +90⁰ far down along the part of the frequency-response-curve, which represents their roll-off. And simplistic low-pass filters will phase-shift the signal close to -90⁰ under corresponding conditions.

OTOH, Either type of filter is supposed to phase-shift their signal ±45⁰, at their -3db point.

What this means is that if the output from several band-pass filters is taken in parallel – i.e. summed – then the center-frequency of one band will be along the roll-off part of the curve of each adjacent band, which combined with the -3db point from either its high-pass or its low-pass component. But then if the output of this one central band is set to zero, the output from the adjacent bands will be 90⁰ apart from each other. )

(Edit 03/29/2017 :

A further conclusion of this analysis would seem to be, that even to implement an equalizer with 1 slider /Octave properly, requires that each bandpass-filter be a second-order filter instead. That way, when the signals wander across to the center-frequency of the slider for the next octave, they will be at -6db relative to the output of that slider, and 180⁰ phase-shifted with respect to each other. Then, setting the center slider to its minimum position will cause the adjacent ones to form a working Notch Filter, and will thus allow any one band to be adjusted arbitrarily low.

And, halfway between the slider-center-frequencies, the gain of each will again be -3db, resulting in a phase-shift of ±90 with respect to the other one, and achieving flat frequency-response, when all sliders are in the same position.

The problem becomes, that if a 20-band equalizer is attempted, because the 1 /Octave example already required second-order bandpass-filters, the higher one will require 4th-order filters by same token, which would be a headache to program… )