Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: Inner working of filter_biquad

  1. #1
    Senior Member
    Join Date
    Feb 2019
    Posts
    123

    Inner working of filter_biquad

    I am trying to figure out how the IIR filters are implemented in the audioLibrary: filter_biquad.cpp. But I really struggle at that code. Perhaps someone could give me some hints. As far as I understand the CPU can only do 32x16 multiplies-adds, so for each 32x32 product there should be two MAC instructions. I would expect these two MACs close together and with the same operands, the onee as "Bottom" the other as "Top". But the code really works in another way. What value should I specify for a1 (scaling) if I want a1=-0.5 or a1=1.0. I think the scale factor is 1073741824 but i am not sure. I would like to run the code on the filter:
    B0= 1.0
    B1= 0
    B2= 0
    A1=-1.0
    A2= 0.5
    I have coded IIR filters using an FPGA and Java, so now it comes to ARM.

    I just want to learn from the code of others!

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    For the multiply & accumulate instructions, read pages 107-108 in this document

    https://static.docs.arm.com/ddi0403/...armv7m_arm.pdf

  3. #3
    Senior Member
    Join Date
    Feb 2019
    Posts
    123
    I think I understood the MAC Instructions. The Problem is more how the MACinstructions together yield the IIR filter.
    One detailed question: You sometimes and sum with 0x3FFF. I dont understand why.

    Code:
    b0 = *state++;
    b1 = *state++;
    b2 = *state++;
    a1 = *state++;
    a2 = *state++;
    bprev = *state++;
    aprev = *state++;
    sum = *state & 0x3FFF;
    data = end - AUDIO_BLOCK_SAMPLES/2;
    do {
    	in2 = *data;
    	sum = signed_multiply_accumulate_32x16b(sum, b0, in2);      // MAC1
    	sum = signed_multiply_accumulate_32x16t(sum, b1, bprev);   // MAC2
    	sum = signed_multiply_accumulate_32x16b(sum, b2, bprev);   // MAC3
    	sum = signed_multiply_accumulate_32x16t(sum, a1, aprev);   // MAC4
    	sum = signed_multiply_accumulate_32x16b(sum, a2, aprev);   // MAC5
    	out2 = signed_saturate_rshift(sum, 16, 14);
    	sum &= 0x3FFF;
    	sum = signed_multiply_accumulate_32x16t(sum, b0, in2);     // MAC6
    	sum = signed_multiply_accumulate_32x16b(sum, b1, in2);     // MAC7
    	sum = signed_multiply_accumulate_32x16t(sum, b2, bprev);  // MAC8
    	sum = signed_multiply_accumulate_32x16b(sum, a1, out2);   // MAC9
    	sum = signed_multiply_accumulate_32x16t(sum, a2, aprev);  // MAC10
    	bprev = in2;
    	aprev = pack_16b_16b(
    	signed_saturate_rshift(sum, 16, 14), out2);
    	sum &= 0x3FFF;
    	bprev = in2;
    	*data++ = aprev;
    	} while (data < end);
    I think MAC1 and MAC6 compute b0*in2.
    But b1 is once multiplied by bprev (MAC2) and the other time by in2 (MAC7) . I don't understand that.
    Multiplication b2*bprev seems ok by MAC3 and MAC8.
    But a1 is once multiplied by aprev (MAC4) and the other time by out2 (MAC9) . I don't understand that.
    Multiplication a2*aprev seems ok by MAC5 and MAC10.

    I would be thankful for some guiding hints.

  4. #4
    Senior Member
    Join Date
    Feb 2019
    Posts
    123
    I think I have figuerd it out: The variables in2,out2,aprev,brev hold 2 int16 each and the ten MACs are used to compute two steps of the IIR filter.
    Quite tricky, but probably fast.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    Yup, this is how much of the audio library works, where pairs of 16 bit numbers are packed into 32 bit words. ARM designed their DSP extension instructions to work separately on either half of 32 bit words, so the samples can be used directly from the 32 bit registers.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    Quote Originally Posted by ossi View Post
    One detailed question: You sometimes and sum with 0x3FFF. I dont understand why.
    That part was meant to implement a "first order noise shaping" recommendation I found in this article.

    http://www.earlevel.com/main/2003/02/28/biquads/

    Looking at it again now, I'm not 100% sure the logical and really is correct. This probably creates a small DC bias, since it can't be negative. Might be totally wrong for 1/2 of the cases? Also not sure if the polarity is really right either.

    I've added a comment to the source code.

    https://github.com/PaulStoffregen/Au...67d16d10566308

  7. #7
    Junior Member
    Join Date
    Apr 2014
    Location
    Seattle, WA
    Posts
    12
    Hi Paul,

    The noise-shaping is actually correct, because the signed shift does truncation toward -inf. The quant error is guaranteed to be a positive fraction in [0,1]. If you round instead of truncate (to prevent the 0.5 ULP DC offset) then the error feedback becomes more complicated (and slow) to implement. Its not really worthwhile to fix.. dithering the output would make more sense.

  8. #8
    Senior Member
    Join Date
    Feb 2019
    Posts
    123
    @Paul: Thank you for your explanation. Have you tested (by simulation) that noise shaping with biquads is really helpful? Perhaps I will try such an simulation.

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    Quote Originally Posted by ossi View Post
    Have you tested (by simulation) that noise shaping with biquads is really helpful?
    No, I did basically no testing at all on the noise shaping, other than a couple very unscientific listening tests to check it wasn't harming the output.

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,493
    Another thread, maybe unrelated, about biquad noise stuff. Linking here, so when I someday look into this, will see both these threads.

    https://forum.pjrc.com/threads/55499...d-output-noise

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •