Skip to content

Instantly share code, notes, and snippets.

@smoge
Created July 6, 2024 13:40
Show Gist options
  • Save smoge/9cd0e909d7e45ecab4b58da42b7c70f6 to your computer and use it in GitHub Desktop.
Save smoge/9cd0e909d7e45ecab4b58da42b7c70f6 to your computer and use it in GitHub Desktop.
Check for IIR Bad Coefficients
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
@smoge
Copy link
Author

smoge commented Jul 6, 2024

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^2

$a_0 + a_1 z^{ -1} + a_2 z^{-2} = 0$ then multiply this by $z^2$

$$ a_0 z^2 + a_1 z + a_2 = 0 $$

The isStable function ensures both poles have magnitudes less than 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment