Created
July 6, 2024 13:40
-
-
Save smoge/9cd0e909d7e45ecab4b58da42b7c70f6 to your computer and use it in GitHub Desktop.
Check for IIR Bad Coefficients
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Complex (Complex((:+))) | |
data IIRParams = IIRParams | |
{ b0 :: Float | |
, b1 :: Float | |
, b2 :: Float | |
, a0 :: Float | |
, a1 :: Float | |
, a2 :: Float | |
} | |
deriving (Show) | |
-- Example of an unstable filter (IIR BAD Coefficients) | |
unstableFilter :: IIRParams | |
unstableFilter = IIRParams | |
{ b0 = 0.5 | |
, b1 = 0.5 | |
, b2 = 0.5 | |
, a0 = 1.0 | |
, a1 = -1.8 -- These coefficients | |
, a2 = 0.9 -- produce poles outside 'circle' | |
} | |
-- Calculate poles of IIR filters | |
calculatePoles :: IIRParams -> (Complex Float, Complex Float) | |
calculatePoles (IIRParams _ _ _ a0 a1 a2) = | |
let discriminant = a1 * a1 - 4 * a0 * a2 | |
twoA = 2 * a0 | |
sqrtDisc = sqrt discriminant | |
realPart = (-a1) / twoA | |
imagPart = sqrtDisc / twoA | |
root1 = realPart :+ imagPart | |
root2 = realPart :+ (-imagPart) | |
in (root1, root2) | |
-- Magnitude of complex numbers | |
magnitude :: Complex Float -> Float | |
magnitude (r :+ i) = sqrt (r * r + i * i) | |
-- Check IIR filter is stable | |
isStable :: IIRParams -> Bool | |
isStable params = | |
let (pole1, pole2) = calculatePoles params | |
in magnitude pole1 < 1 && magnitude pole2 < 1 | |
main :: IO () | |
main = do | |
let params = unstableFilter | |
print params | |
print $ calculatePoles params | |
print $ isStable params -- should be False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The theory comes from here: Audio EQ Cookbook
One needs to calculate two things:
The
calculatePoles
finds the roots of the characteristic equation; the equation that represents the poles of the filter. The characteristic equation is the filter transfer function denominators setting them equal to zero, then multiplying this by z^2The
isStable
function ensures both poles have magnitudes less than 1.