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

Thread: Help with filter design

  1. #1
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192

    Help with filter design

    I'm looking to emulate a tone control in a part of an audio effect. Trying to achieve specific low frequency and high frequency attenuation.

    The spec's I'm trying to achieve are 6db/octave roll-off with a corner frequencies of 280 Hz at the low end and 4000Hz at the high end.

    I'm using the biquad with high and low shelves at the moment as an approximation, it doesn't sound quite right and I also note the comment on the design tool of trouble with corner frequencies below 400Hz.

    I'm familiar with the Audio Library but not filter design. I know you can pass them specific coefficients but not sure where to start to achieve the above spec. especially with the low corner frequency.

    I'm assuming some sort of high pass at 280Hz in serial with a low pass at 4000Hz.

    The question is : is this best approach, which objects would I use and how would I calculate the coefficients, any help appreciated.

    Cheers, Paul

  2. #2
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    323
    Representing audio filters as cascaded biquads is very common. Some google searching will provide lots of examples, and even some online web tools to convert frequency specs into the coefficients for cascaded biquads. There are biquad objects in the audio library itself, but you can also do the cascaded biquads as a single function call using the ARM dsp functions in the Keil CMSIS library.

    Be careful that different tools might use different polarities (+ or -) so pay attention to the equation from the coefficient generator and the audio object or DSP function in order to make any trivial adjustments.

    https://www.keil.com/pack/doc/CMSIS/...upFilters.html
    Last edited by Blackaddr; 04-23-2021 at 08:06 PM.

  3. #3
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,316
    also, it is useful to study exactly implementation (direct I or direct II, use of b0 etc)
    In other words, compare the CMSIS implementation with the routines (e.g. Matlab) used to create biquads

  4. #4
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    Hi, thanks for the pointers

    Quote Originally Posted by Blackaddr View Post
    There are biquad objects in the audio library itself[/URL]
    The issue with the library one is the noted issue with low corner freq (<400Hz).

    I'll have a look at the CMSIS-DSP, I'm assuming I'd need to wrap that in a new object and convert the block to floats

    Cheers, Paul
    Last edited by houtson; 04-23-2021 at 10:20 PM.

  5. #5
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    Quote Originally Posted by WMXZ View Post
    also, it is useful to study exactly implementation (direct I or direct II, use of b0 etc)
    In other words, compare the CMSIS implementation with the routines (e.g. Matlab) used to create biquads
    Thanks, came across this http://users.sussex.ac.uk/~tafj0/DSP_IIR.html which looks handy

    Cheers Paul

  6. #6
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    323
    There are float as well as integer versions of most CMSIS functions. There are also DSP functions for converting to/from float. If you've got lots of CPU to spare, that's a good approach. If you can't afford to do it all in float, there are integer functions that support up to 64-bit internal accumulators and 32-bit coefficients but read the instructions carefully to avoid input overflow. Usually it limits to you 25% max amplitude to avoid clipping.

  7. #7
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    Quick bit of feedback to say I got that working - thanks for the pointers @Blackaddr and @WMXZ.

    I'm a complete noob at filter design so I'll capture a few notes here for anyone else coming behind me.

    I used the filter calculator at https://www.earlevel.com/main/2013/1...calculator-v2/ to produce the coefficients.

    The calculator uses the formula : y[n] = a0 * x[n] + a1 * x[n-1] + a2 * x[n-2] b1 * y[n-1] b2 * y[n-2]

    The CMSIS implementation uses the formula : y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]

    So you need to change the output of the calc as:
    b0 = a0
    b1 = a1
    b2 = a2
    a0 = -1 * b0
    a1 = -1 * b1

    I created a custom object and converted the block to floats dividing through by 32768.0f (I'm sure their is a better way of doing this) before then calling the filter function - seems to work well. Plan is to incorporate into another custom object along with other stuff.

    A snippet of the code...
    Code:
    void AudioFilterBiquadFloat::update(void) {
      audio_block_t *blocka;
      float32_t blockFloat[AUDIO_BLOCK_SAMPLES];
    
      blocka = receiveWritable(0);
      if (!blocka) {
        return;
      }
      // convert block of samples to floats
      for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
        blockFloat[i] = blocka->data[i] / 32768.0f;
      }
      // process a block of samples
      arm_biquad_cascade_df1_f32(&S1, blockFloat, blockFloat, AUDIO_BLOCK_SAMPLES);
    
      // convert block back to ints
      for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
        blocka->data[i] = (float)(blockFloat[i]) * 32768.0f;
      }
      transmit(blocka);
      release(blocka);
    }
    Thanks again, Paul

  8. #8
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    1,051
    > I'm looking to emulate a tone control

    You should be able to measure the impulse response of the existing tone control and then use a teensy 4 to convolve audio with this impulse response to duplicate the original.

  9. #9
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,178
    Dividing by a constant is likely slower than multiplying by the reciprocal -
    Code:
    const float recip = 1.0f/INT16_MAX ;
    
    ...
        blockFloat[i] = blocka->data[i] * recip;
    I'm not sure if the compiler can do this automatically, there may be some subtlety of IEEE floating point
    that has different behaviour (NaNs, infinities, or whatever) between multiply and divide prohibiting
    this optimization being made implicitly.

    BTW there's no need to scale the value when converting int to float, a filter using floating point
    is completely scale agnostic - though sometimes you might want the value normalized anyway
    (ease of debugging perhaps).

  10. #10
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    The tone attenuation is on the feedback leg of an old reverb effect that I don't own so difficult to isolate.

    I have the a schematic of it so believe it is as spec'd above, cheers Paul.

  11. #11
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    Quote Originally Posted by MarkT View Post
    Dividing by a constant is likely slower than multiplying by the reciprocal
    Thanks I'll try that

    Is there and arm_ function to convert a block of int16_t to float?

    I should have said above I'm using a teensy 4, cheers Paul

  12. #12
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,178
    Quote Originally Posted by houtson View Post
    Thanks I'll try that

    Is there and arm_ function to convert a block of int16_t to float?
    actually yes I believe so - arm_q15_to_flt perhaps? Something like that.
    I should have said above I'm using a teensy 4, cheers Paul
    I was assuming so given the use of floats...

  13. #13
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    192
    thanks - void arm_q15_to_float (const q15_t * pSrc, float32_t * pDst, uint32_t blockSize )

Posting Permissions

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