Based on that article and all the resources on the internet that advise the use of noise shaping for fixed-point filter implementations, I tried to make a few simulations on Matlab for the biquad I'm trying to implement.
When I implement this filter in Q31 with no noise shaping, I get the correct frequency frequency response :
Then, as expected, the Q15 implementation introduces some errors :
Note: I was expecting, as the document indicates (table 1), to smoothen things around 0 for positive feedback and around Nyquist for negative.
Here is the filtering part of my Matlab code :
acc = int32(0); % Q4.26 coeffs_Q2_13 = int16(coeffs*2^13); sYn1 = int16(0); % Q2.13 sYn2 = int16(0); % Q2.13 sXn1 = int16(0); % Q2.13 sXn2 = int16(0); % Q2.13 X = int16(in*2^15); % float to Q2_13 Y = int16(zeros(length(X), 1)); % Q2.13 Qnoise = int16(zeros(length(X), 1)); Qnoise1 = int16(0); Qnoise2 = int16(0); for i = 1:1:length(X) acc = int32(coeffs_Q2_13(1,1))*int32(X(i)); acc = acc + int32(coeffs_Q2_13(1,2))*int32(sXn1); acc = acc + int32(coeffs_Q2_13(1,3))*int32(sXn2); acc = acc - int32(coeffs_Q2_13(2,2))*int32(sYn1); acc = acc - int32(coeffs_Q2_13(2,3))*int32(sYn2); acc = acc + int32(coeffs_Q2_13(2,2))*bitand(int32(Qnoise1), 32767); acc = acc + int32(coeffs_Q2_13(2,3))*bitand(int32(Qnoise2), 32767); sXn2 = sXn1; sXn1 = X(i); sYn2 = sYn1; Y(i) = bitshift(acc, -13); Qnoise2 = Qnoise1; Qnoise(i) = int16(acc - bitshift(int32(Y(i)), 13)); %bitand(acc, int32(8191)); Qnoise1 = Qnoise(i); sYn1 = Y(i); acc = int32(0); end
My filter uses these coefficients :
- ff0 = 0.04253225858264462
- ff1 = 0.08506451716528925
- ff2 = 0.04253225858264462
- fb1 = 0.21971585162695534
- fb2 = -0.6101551140424661
I'm working at Fs = 48000 and my input vector ("in" in the code) is an impulse simulated by a 48000 samples vector with the first sample being 1 and the rest 0.
What am I doing wrong?
EDIT : I've read as a comment to a question on dsp.stackexchange (to which I can't post the link due to the sus-mentionned limitations) that quantification being a non-linear process, an impulse response is not the correct way to visualize its effects. Is that the reason? should I sweep a sinewave instead?