f4exb / sdrangel

SDR Rx/Tx software for Airspy, Airspy HF+, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay and FunCube
GNU General Public License v3.0
2.91k stars 441 forks source link

Highpass and bandpass filters have large sample rate dependent gain #642

Closed srcejon closed 4 years ago

srcejon commented 4 years ago

The highpass and bandpass filters (in sdrbase/dsp/highpass.h and bandpass.h) appear to have large sample rate dependent gain in the pass band. This can be seen in the following frequency response plots for the high pass filter, based on the filter's taps, computed for:

Highpass<Real> filter;
filter.create(301, 48000, 5000);
filter.create(301, 4*48000, 5000);

highpass_freq_response

This appears to be due to the normalisation code using the value of the centre tap that has had 1 added to it on line 39 (that flips it from low pass to highpass).

It looks like this can be fixed, by simply not including this extra 1 in the normalisation:

Change: Line 49: sum += m_taps[i]; To: sum += m_taps[i] - 1;

This then gives 0dB gain in the passband, regardless of sample rate, and attenuates the stop band:

highpass_freq_response_fixed

bandpass.h needs the same fix on line 70.

f4exb commented 4 years ago

The Highpass is not used anywhere but the Bandpass in the following plugins. These plugins probably need to be checked because some hack was probably used to circumvent the issue that can now have an adverse effect:

f4exb commented 4 years ago

In the NFM Demod there is a lowpass and bandpass filter created like this:

        m_bandpass.create(301, m_audioSampleRate, 300.0, settings.m_afBandwidth);
        m_lowpass.create(301, m_audioSampleRate, settings.m_afBandwidth);

Then it is pretty obvious that it should be scaled by the number of taps:

                if (m_settings.m_highPass) {
                    sample = m_bandpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume;
                } else {
                    sample = m_lowpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume * 301.0f;
                }

Edit: in the NFM demod this is misleading because the factor 301 is compensated elsewhere in other plugins this should not be scaled in fact. In NFM demod the heuristics bandwidth dependent compensation can possibly be completely removed.

f4exb commented 4 years ago

Implemented in v4.17.0