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

Thread: AudioFilterStateVariable unwanted noise

  1. #1
    Junior Member
    Join Date
    Oct 2020
    Posts
    14

    AudioFilterStateVariable unwanted noise

    I'm getting a raspy noise from the AudioFilterStateVariable under certain conditions.
    (I'm using a Teensy 4.1 with TEENSY4_AUDIO adapter board).

    when the combination of the freq control input, frequency(freq) and resonance(.707) push the filter parameters out of wack the filter outputs a awful, unwanted noise.

    I've created an example design to demonstrate the problem. I believe that the problem occurs when the filter cutoff frequency is pushed close to or above Nyquist, particularly when the resonance is low (like .707).

    It would be great if the filter could internally limit the F after the calculation F = Fcenter*2^(signal*octaves).

    Or perhaps, someone has a work around?

    The attached file has the example design is attached (filter_noise.ino).

    filter_noise.ino

  2. #2
    Junior Member
    Join Date
    Oct 2020
    Posts
    14
    Apparently, there is a limit to the F after the calculation F = Fcenter*2^(signal*octaves).
    in

    void AudioFilterStateVariable::update_variable(const int16_t *in,
    const int16_t *ctl, int16_t *lp, int16_t *bp, int16_t *hp)

    ...
    if (fmult > 5378279) fmult = 5378279;
    fmult = fmult << 8;

    ...
    though I'm not sure what the magic number 5378279 and why fmult gets shifted left by 8 here.

    Anyway, this doesn't explain why the filter makes that really loud, raspy white noise sound as described in the post above.

    anyone know why it does that?

  3. #3
    Junior Member
    Join Date
    Oct 2020
    Posts
    14
    Ok, so after analyzing filter_variable.cpp, I fixed the problem with the noise.

    I made a couple of changes to filter_variable.cpp
    First, I uncommented line 42 to define IMPROVE_HIGH_FREQUENCY_ACCURACY
    next I changed line 133 from:
    if (fmult > 5378279) fmult = 5378279;
    to:
    if (fmult > 4205728) fmult = 4205728;

    then after fmult << 8, fmult (normalized) is limited to slightly more than 1.0
    This limits the adjusted filter cutoff ( Fcenter*2^(signal*octaves) ) to 14,744 Hz


    this magic number of 4205728, should probably be tied to resonance value ('damp' in filter_variable.cpp), then the filter's adjusted cutoff could go higher with higher resonance values.

    I'm not sure if there are other ramifications regarding this hack, but it seems to work well for my purposes.

  4. #4
    Senior Member
    Join Date
    Apr 2019
    Posts
    172
    Thanks very much for this. It's solved a problem where resonance values below 1.1 were causing noise for me.

  5. #5
    Junior Member
    Join Date
    Oct 2020
    Posts
    14
    I've made a couple more hacks to this so it works better for my purposes:
    1. I changed void AudioFilterStateVariable::update_variable to use 4x oversampling instead of just 2x;

    old 2x code snippet:
    (starting around line 147 in filter_variable.cpp)
    Code:
    		// now do the state variable filter as normal, using fmult
    		input = (*in++) << 12;
    		lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = ((input + inputprev)>>1) - lowpass - MULT(damp, bandpass);
    		inputprev = input;
    		bandpass = bandpass + MULT(fmult, highpass);
    		lowpasstmp = lowpass;
    		bandpasstmp = bandpass;
    		highpasstmp = highpass;
    		lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = input - lowpass - MULT(damp, bandpass);
    		bandpass = bandpass + MULT(fmult, highpass);
    		lowpasstmp = signed_saturate_rshift(lowpass+lowpasstmp, 16, 13);
    		bandpasstmp = signed_saturate_rshift(bandpass+bandpasstmp, 16, 13);
    		highpasstmp = signed_saturate_rshift(highpass+highpasstmp, 16, 13);
    		*lp++ = lowpasstmp;
    		*bp++ = bandpasstmp;
    		*hp++ = highpasstmp;
    new 4x code snippet:
    Code:
    		// now do the state variable filter as normal, using fmult
    		input = (*in++) << 12;
    
    		lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = ((input + 3*inputprev)>>2) - lowpass - MULT(damp, bandpass);
    		bandpass = bandpass + MULT(fmult, highpass);
    		
    		lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = ((input + inputprev)>>1) - lowpass - MULT(damp, bandpass);
    		bandpass = bandpass + MULT(fmult, highpass);
            
    		lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = ((3*input + inputprev)>>2) - lowpass - MULT(damp, bandpass);
    		bandpass = bandpass + MULT(fmult, highpass);
            
                    lowpass = lowpass + MULT(fmult, bandpass);
    		highpass = input - lowpass - MULT(damp, bandpass);
    		bandpass = bandpass + MULT(fmult, highpass);
    
    		lowpasstmp = signed_saturate_rshift(lowpass, 16, 12);  // just decimate, no need to avg outputs
    		bandpasstmp = signed_saturate_rshift(bandpass, 16, 12);
    		highpasstmp = signed_saturate_rshift(highpass, 16, 12);
    		inputprev = input;
    		*lp++ = lowpasstmp;
    		*bp++ = bandpasstmp;
    		*hp++ = highpasstmp;
    2. then I changed line 100:
    //fcenter = setting_fcenter;
    fcenter = setting_fcenter/2;

    3. then I changed around line 133 a little more to:
    if (fmult > 4194303) fmult = 4194303;

    4. then I changed line 55 of filter_variable.h

    //if (q < 0.7f) q = 0.7f;
    if (q < 0.5f) q = 0.5f;

    Now with these changes the filter is stable with Fc up to 29.4kHz, even with a q as low as 0.5.

    the down sampling is just decimated by taking one of the 4 sample instead of averaging like it was before,
    but this seems to work fine.

    Anyway, I just wanted to share what i did with this in case it helps someone.
    Last edited by tigger; 09-20-2021 at 04:47 AM.

  6. #6
    Junior Member
    Join Date
    Oct 2020
    Posts
    14
    actually, I had to change fmult max to:
    if (fmult > 2965372) fmult = 2965372; // fmult <= 0.7, to allow q to go down to 0.5 instead of 0.7

    This means with 4x oversampling Fc max is about 20kHz.

Posting Permissions

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