# IIR design: SciPy CMSIS-DSP coefficient format

How do you reconcile Scipy.signal's IIR design with CMSIS-DISP's API? Scipy.signal outputs in one of 3 forms:

• Numerator/denominator
• Pole Zero
• Second-Order-Sections.

CMSIS requires an array of length a multiple of five. Each 5 values are coefficients b0, b1, b2, a1, and a2 for a filter state: "Coefficients b0, b1 and b2 multiply the input signal x[n] and are referred to as the feedforward coefficients. Coefficients a1 and a2 multiply the output signal y[n] and are referred to as the feedback coefficients. Pay careful attention to the sign of the feedback coefficients. Some design tools use the difference equation"

Scipy's formats seem incompatible: Numerator/Denominator uses "b" and "a" terminology, but returns 2 arrays: A numerator array of lengh 6, and denominator array of len 6. SOS format also returns arrays of length 6.

This is in contrast to FIR, where there's a 1-to-1 mapping. Ie both use an array of coefficients corresponding to a convolution kernel. IIR seems more diverse by comparison.

scipy.signal.iirdesign

• CMIS uses a standard normalized second order sections. They just assume that $a_0=1$ and you don't specifically pass it into the function, so you pass in 5 coefficients instead of 6. Nov 8, 2021 at 12:08

scipy.signal returns a sos matrix when you set output='sos', which is cascaded second-order sections and has a shape of (n_sections, 6).

Each row corresponds to a second-order section, and you have [b0, b1, b2, a0, a1, a2] in order. Normalize these coefficients to make sure that a0=1, and then remove a0 from the array -- CMSIS assumes that a=1 so you only need 5 coefficients.

One thing to mention is that the sign of the denominators are different in scipy and CMSIS. The difference equation defined in CMSIS is given by

$$y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] - a_1 y[n-1] - a_2 y[n-2]$$

However it is defined in scipy/MATLAB by $$y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] + a_1 y[n-1] + a_2 y[n-2]$$

So you have to change the signs of all the denominators. And finally, cascade coefficients of all sections and you get array of length n_sections * 5:

$$[b_0^1, b_1^1, b_2^1, -a_1^1, -a_2^1, b_0^2, b_1^2, b_2^2, -a_1^2, -a_2^2,\ldots, b_0^N, b_1^N, b_2^N, -a_1^N, -a_2^N]$$ where $$N$$ is the number of biquad sections, which is defined as numStages in CMSIS.

• This was exactly what I was looking for (how to run a scipy-generated filter in CMSIS), thanks! Stuff like this should be in the CMSIS documentation Mar 18 at 9:45
• However, something might have changed, because the difference equation specified in CMSIS now is y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] (with positive a1 and a2), see keil.com/pack/doc/CMSIS/DSP/html/group__BiquadCascadeDF1.html Mar 18 at 12:48
• I think the scipy convention is -a1, -a2, so the end result is correct that you need to negate them, but for the opposite reasons as in the answer :) Mar 18 at 13:33