Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gain needs to be controlled #3

Open
gauss256 opened this issue Aug 22, 2015 · 8 comments
Open

Gain needs to be controlled #3

gauss256 opened this issue Aug 22, 2015 · 8 comments
Assignees
Labels

Comments

@gauss256
Copy link

Hi, thanks for your very useful code. I found that the gain of the filter is unpredictable. I'd like the gain at the center frequency to be 1, i.e., no change between input and output. But in my code below, a gain gets applied that varies depending on the parameters chosen. How do I normalize things so that no gain gets applied?

// Design the filter
double overallGain = 1.0;
bool designedCorrectly = butterworth.bandPass(
    args.dSamplerate,               // sample rate (Hz)
    args.dLow,                      // lo cutoff (Hz)
    args.dHigh,                     // hi cutoff (Hz)
    args.nOrder,                    // filter order
    coeffs,                         // vector to hold coefficients
    overallGain);                   // gain (how to choose?)
if (!designedCorrectly) {
    throw std::runtime_error("Filter design failed");
}

// Implement the filter
int stages = (int) coeffs.size();
BiquadChain chain(stages);
chain.processBiquad(input, output, 1, (int)nItems, &coeffs[0]);
@ruohoruotsi ruohoruotsi self-assigned this Aug 22, 2015
@ruohoruotsi
Copy link
Owner

Hi, thank you for your comment. Can you please post a full test, with all your parameters that are giving you unpredictable gain? I'll try to understand the issue and advise! Cheers!

@gauss256
Copy link
Author

My test file is a frequency sweep from 0 Hz to 20 kHz, peak normalized to -3 dB.

https://www.dropbox.com/s/fpzid8sz9avzse9/sweep_0_20K.wav?dl=0

I read it in and normalize the input values to be floats within the range [-1, 1]. Because of the peak normalization, the range is actually [-0.7, 0.7].

The results are shown below. The maxOutput is the maximum absolute value of the output after the filter is applied. If there was unity gain that maximum should be 0.7. If I scale the output by maxOutput and write out the file, it looks exactly as I would expect.

    fs      f1      f2      filterOrder overallGain maxOutput
    48000   80      10000    4          1                13.7
    48000   1000    10000    4          1                18.6
    48000   80      10000    6          1                59.7
    48000   5000    10000    8          1             22369.7
    48000   1000     5000   10          1           2030042.0

@ruohoruotsi
Copy link
Owner

Okay, this looks like a bug. Let me run your examples and see if I can't fix it, or at least localize the problem. Is it only with bandpass, or have you seen gain issues with other filter types?

@ruohoruotsi ruohoruotsi added bug and removed question labels Aug 22, 2015
@gauss256
Copy link
Author

I've only tried bandpass so far.

@gauss256
Copy link
Author

I did some quick tests with loPass and hiPass, and see similar problems. The gain applied in the loPass case is large (>10^3 in the examples I tried) but is more modest for hiPass (<10^2).

@ruohoruotsi
Copy link
Owner

okay, I'm looking through my test cases and the gain calculations and there's this logic that I need to refresh on in https://github.com/ruohoruotsi/Butterworth-Filter-Design/blob/master/Butterworth.cpp.

Tonight, I'll run over your test file to reproduce the issue. My test-cases check against the filter results generated from MATLAB, so its possible there is some assumption that in practise does not work. I'll update the issue soon with my findings! Thanks for filing this!

    // correct the overall gain
    if(filter == kLoPass || filter == kBandPass){ // pre-blt is okay for S-plane
        ba[0] = preBLTgain * (preBLTgain / gain); // 2nd term is how much BLT boosts,
    }
    else if(filter == kHiPass || kBandStop){ // HF gain != DC gain
        ba[0] = 1 / ba[0];
    }

@oukradation
Copy link

Hi, great code. I am using your code in my ecg project.

However, the gain issue is still consistent after your latest commit. It behaves almost same as @gauss256 describes.

I am a beginner in c++, so don't take my word seriously but I wonder if it is overflowing issue due to different compiler, if you can't regenerate the same problem? I am using your code in Qt 5.10 with gcc 64bit.

@guo-max
Copy link

guo-max commented Nov 3, 2021

Hi, Thanks for your code. It is very useful. I had the same problem about the gain and here is my fix. I just multiply the input with ba[0] and everything looks fine.
Only tested with lowpass filter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants