Hello,

how does the function coeff_iirdf1_fx16 work?

I want to calculate the coefficients on my own to avoid instability.

In the documentation the vector coeffs is described as follows:

[b_0, -a_01, b_01, -a_02, b_02, ..., -a_n1, b_n1, -a_n2, b_n2, scale_factor ]

What is b_0? Is it the coefficient of the first stage and every other stages b_0 is assumed to be 1?

What is the scale_factor and how is it calculated?

I already decomposed my 4th order bandpass transferfunction into biquad stages (see attachement), but im stuck with calculating the coeff array.

Thanks in advance

Anselm

Hi Anselm,

Below some Matlab code to illustrate how the coeff_iirdf1_fr function works.

Defining your coefficients first (thus for your floating point filter operation, you could use sosfilt() from the signal processing toolbox):

% coefficients as SOS matrix (B0k, B1k, B2k, 1, A1k, A2k)

sosBandPass = [0.0553780, -0.0016135, 0.0553780, 1.0000000, -1.9649905, 0.9664257; ...

1.0000000, -1.9999372, 1.0000000, 1.0000000, -1.5649967, 0.7015197];

% convert coefficients to transfer function representation

% (this will require the signal processing toolbox)

[bcoeff, acoeff] = sos2tf(sosBandPass);

Regarding the conversion function:

% First, find the largest absolute value of any coefficient

% (either A or B coefficient)

maxAcoeff = max(abs(acoeff));

maxBcoeff = max(abs(bcoeff));

coeffMax = max(maxAcoeff, maxBcoeff);

% Next, find a suitable scaling coefficient

% (must be a power of 2, such that 2^power2 >= coeffMax)

scaleExpo = nextpow2(coeffMax);

scaleValue = 2^scaleExpo;

% To convert a floating point number to a 1.15 fractional number,

% one would compute (note that this will truncate):

% bcoeff_fr16 = int16(bcoeff * (2^15));

% Taking scaling into account, this equation will change to:

% bcoeff_fr16 = int16((bcoeff * (2^15)) / (2^scaleExpo)); % <=>

% bcoeff_fr16 = int16(bcoeff * ((2^15) / (2^scaleExpo))); % <=>

% bcoeff_fr16 = int16(bcoeff * (2^(15 - scaleExpo)));

% When using the C language, the same could be achieved using the ldexp function:

% bcoeff_fr16[k] = (short) ldexpf (bcoeff[k], 15 – scaleExpo);

n = length(bcoeff);

coeff_iirdf1(1:2:2*n) = int16(bcoeff * 2^(15 - scaleExpo));

coeff_iirdf1(2:2:2*(n-1)) = int16(-acoeff(2:end) * 2^(15 - scaleExpo));

The reason that the scale coefficient has to be a power of two is that the iirdf1 function uses an arithmetic shift to reverse any scaling applied. This scaling happens once per sample, after computing the filtered response for the given sample.

For further information, please have a look at the implementation of the equivalent fract32 function ($VDSP_INSTALL/Blackfin/lib/src/libdsp/coeff_iirdf1_fr32.c). The sources vary in the way the algorithm is implemented, however both follow the same principle as laid out above.

Andreas