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.

Here is my filter's frequency response using Matlab's own filter function and plotted with the periodogram function :

enter image description here

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 :

Trying to reduce this error with 1st order ESS gives doutable results, although it seems close to working (I don't exactly know what to expect so I'm not sure) : enter image description here

Note: I was expecting, as the document indicates (table 1), to smoothen things around 0 for positive feedback and around Nyquist for negative.

Then I tried error cancellation by multiplying the quantification error by the feedback coefficients of my biquad, and then everything turned crazy : enter image description here

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);

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?


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.