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

Thread: Biquad stage reset

  1. #1
    Junior Member
    Join Date
    May 2021
    Posts
    8

    Biquad stage reset

    Hello everybody.
    i'm working with biqad filters, and sometimes i would like to reset a stage.
    For example, i do

    biquad.setBandpass(0,1000,1);
    biquad.setBandpass(1,2000,1);

    then i want to delete de second stage, to return to a one-stage filter.
    It's possible?
    Thank you

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,118
    Just do

    biquad.setBandpass(0,1000,1);

    again. Each stage definition will terminate the string of filter stages unless it is for a stage one more than the last one,
    so redefining the first stage will disable any subsequent stages.

  3. #3
    Junior Member
    Join Date
    May 2021
    Posts
    8
    Thank you Mark.
    So if i do
    biquad.setBandpass(0,1000,1);
    biquad.setBandpass(1,2000,1);
    biquad.setBandpass(1,3000,1);

    it's equivalent to :
    biquad.setBandpass(0,1000,1);
    biquad.setBandpass(1,3000,1);

    If i do:
    biquad.setBandpass(0,1000,1);
    biquad.setBandpass(1,2000,1);
    biquad.setBandpass(1,3000,1);
    biquad.setBandpass(0,2000,1);

    it's equivalent to:
    biquad.setBandpass(0,2000,1);

    did I understand correctly?

  4. #4
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,118
    From my reading of the code yes, but why not actually try it to be sure?

  5. #5
    Junior Member
    Join Date
    May 2021
    Posts
    8
    Sure, the next stage will be to try it out !
    Cheers

  6. #6
    Junior Member
    Join Date
    May 2021
    Posts
    8
    Hello.
    I tried to reset the filter with a new setting of the lower stage of the biquad (0) but the upper stage (1) remains set.
    So in the following code the final noise is different from the initial noise (at 400Hz)

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthNoiseWhite     noise1;         //xy=157,165
    AudioFilterBiquad        biquad1;        //xy=462,172
    AudioOutputAnalogStereo  dacs1;          //xy=693,173
    AudioConnection          patchCord1(noise1, biquad1);
    AudioConnection          patchCord2(biquad1, 0, dacs1, 0);
    AudioConnection          patchCord3(biquad1, 0, dacs1, 1);
    // GUItool: end automatically generated code
    
    
    
    void setup() {
       AudioMemory(20);
      // put your setup code here, to run once:
      noise1.amplitude(.5);
      biquad1.setBandpass(0,400,1); //Low freq noise
      delay(2000);
      biquad1.setBandpass(0,5000,1); //High freq noise OK
      delay(2000);
      biquad1.setBandpass(1,5000,1); //More High freq noise OK
      delay(2000);
      biquad1.setBandpass(0,400,1); //Low freq noise? NO
      
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }

  7. #7
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,118
    I've stared at the code again and think I've found a bug to do with this:
    Code:
    void AudioFilterBiquad::setCoefficients(uint32_t stage, const int *coefficients)
    {
    	if (stage >= 4) return;
    	int32_t *dest = definition + (stage << 3);
    	__disable_irq();
    	if (stage > 0) *(dest - 1) |= 0x80000000;   // <<<<< this sets the continuation flag in previous stage, all as expected
    	*dest++ = *coefficients++;
    	*dest++ = *coefficients++;
    	*dest++ = *coefficients++;
    	*dest++ = *coefficients++ * -1;
    	*dest++ = *coefficients++ * -1;
    	//*dest++ = 0;
    	//*dest++ = 0;  // clearing filter state causes loud pop
    	dest += 2;
    	*dest   &= 0x80000000;   // <<<<<  I assumed this should be clearing the cont flag, but to do that it needs to be  " *dest &= ~0x80000000; "
    	__enable_irq();
    }
    However I'm not quite sure if this is the intention as the low order bits of the flag word are also
    used to store the dither carry-over during filtering for that stage. Perhaps there was never an intention
    to allow resetting, but changing that line to "* dest = 0 ;" would clear the cont flag and zero out the
    dither carry (called sum in the rest of the code in filter_biquad.cpp).

    The current code allows stages to be changed independently after the fact, which could be useful.

    Perhaps the real fix is to add a method to reset the number of active stages explicitly.

  8. #8
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    187
    Hi,

    i think it's operating as intended, certainly the way I thought it operated i.e. once you have set a stage that is it set until you change it and the stage is independent of others.

    I've used one stage to say set a low shelf and another with a high shelf then vary the gains of each of them independently to provide tone control.

    If after you've set a stage you want to pass through then just open up the filter or set the coefficients directly (b0 = 1 and all the rest 0 for pass through?)

    Cheers, Paul

  9. #9
    Junior Member
    Join Date
    May 2021
    Posts
    8
    Hi,
    If after you've set a stage you want to pass through then just open up the filter or set the coefficients directly (b0 = 1 and all the rest 0 for pass through?)
    Yes! I will try this,
    cheers

Posting Permissions

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