From 00ba5115f3a0b4d792ef1e7f397cfe5c51b7214f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Tue, 3 Nov 2020 14:40:14 +0100 Subject: [PATCH] NFMDemodSink: Proper audio scaling to 16-bit --- plugins/channelrx/demodnfm/nfmdemodsink.cpp | 14 ++++----- plugins/channelrx/demodnfm/nfmdemodsink.h | 33 --------------------- sdrbase/dsp/firfilter.cpp | 13 ++++++++ sdrbase/dsp/firfilter.h | 20 +------------ sdrbase/dsp/misc.h | 3 +- 5 files changed, 22 insertions(+), 61 deletions(-) diff --git a/plugins/channelrx/demodnfm/nfmdemodsink.cpp b/plugins/channelrx/demodnfm/nfmdemodsink.cpp index 70cd50506..6dcef3b6f 100644 --- a/plugins/channelrx/demodnfm/nfmdemodsink.cpp +++ b/plugins/channelrx/demodnfm/nfmdemodsink.cpp @@ -27,6 +27,7 @@ #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "dsp/devicesamplemimo.h" +#include "dsp/misc.h" #include "device/deviceapi.h" #include "nfmdemodreport.h" @@ -58,6 +59,7 @@ NFMDemodSink::NFMDemodSink() : { m_agcLevel = 1.0; m_audioBuffer.resize(1<<16); + m_phaseDiscri.setFMScaling(1.0f); applySettings(m_settings, true); applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); @@ -174,9 +176,11 @@ void NFMDemodSink::processOneSample(Complex &ci) if (!m_settings.m_audioMute && (m_settings.m_ctcssOn && m_ctcssIndexSelected == ctcssIndex || m_ctcssIndexSelected == 0)) { Real audioSample = m_squelchDelayLine.readBack(m_squelchGate); + Q_ASSERT(audioSample >= -1.0f && audioSample <= 1.0f); audioSample = m_settings.m_highPass ? m_bandpass.filter(audioSample) : m_lowpass.filter(audioSample); - audioSample *= m_settings.m_volume * m_filterTaps; - sample = std::lrint(audioSample); + + audioSample *= m_settings.m_volume * std::numeric_limits::max(); + sample = clamp(std::rint(audioSample), std::numeric_limits::lowest(), std::numeric_limits::max()); } } @@ -258,11 +262,6 @@ void NFMDemodSink::applySettings(const NFMDemodSettings& settings, bool force) m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_audioSampleRate; } - if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) - { - m_phaseDiscri.setFMScaling((8.0f*m_audioSampleRate) / static_cast(settings.m_fmDeviation)); // integrate 4x factor - } - if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || force) { m_bandpass.create(m_filterTaps, m_audioSampleRate, 300.0, settings.m_afBandwidth); @@ -324,7 +323,6 @@ void NFMDemodSink::applyAudioSampleRate(unsigned int sampleRate) m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay } - m_phaseDiscri.setFMScaling((8.0f*sampleRate) / static_cast(m_settings.m_fmDeviation)); // integrate 4x factor m_audioFifo.setSize(sampleRate); m_squelchDelayLine.resize(sampleRate/2); m_interpolatorDistanceRemain = 0; diff --git a/plugins/channelrx/demodnfm/nfmdemodsink.h b/plugins/channelrx/demodnfm/nfmdemodsink.h index 74c8dc469..bca38c93c 100644 --- a/plugins/channelrx/demodnfm/nfmdemodsink.h +++ b/plugins/channelrx/demodnfm/nfmdemodsink.h @@ -139,39 +139,6 @@ private: void processOneSample(Complex &ci); MessageQueue *getMessageQueueToGUI() { return m_messageQueueToGUI; } - - inline float arctan2(Real y, Real x) - { - Real coeff_1 = M_PI / 4; - Real coeff_2 = 3 * coeff_1; - Real abs_y = fabs(y) + 1e-10; // kludge to prevent 0/0 condition - Real angle; - if( x>= 0) { - Real r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - Real r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - if(y < 0) { - return(-angle); - } else { - return(angle); - } - } - - inline Real angleDist(Real a, Real b) - { - Real dist = b - a; - - while(dist <= M_PI) - dist += 2 * M_PI; - while(dist >= M_PI) - dist -= 2 * M_PI; - - return dist; - } - }; #endif // INCLUDE_NFMDEMODSINK_H diff --git a/sdrbase/dsp/firfilter.cpp b/sdrbase/dsp/firfilter.cpp index ef3092583..dd287c348 100644 --- a/sdrbase/dsp/firfilter.cpp +++ b/sdrbase/dsp/firfilter.cpp @@ -52,6 +52,19 @@ void generateLowPassFilter(int nTaps, double sampleRate, double cutoff, std::vec int n = i - (nTaps - 1) / 2; taps[i] *= 0.42 + 0.5 * cos((2.0 * M_PI * n) / nTaps) + 0.08 * cos((4.0 * M_PI * n) / nTaps); } + + Real sum = 0; + size_t i; + + for (i = 0; i < taps.size() - 1; ++i) { + sum += taps[i] * 2.0; + } + + sum += taps[i]; + + for (i = 0; i < taps.size(); ++i) { + taps[i] /= sum; + } } } diff --git a/sdrbase/dsp/firfilter.h b/sdrbase/dsp/firfilter.h index d59cb3823..282e52505 100644 --- a/sdrbase/dsp/firfilter.h +++ b/sdrbase/dsp/firfilter.h @@ -20,6 +20,7 @@ #include #include "dsp/dsptypes.h" +#include "dsp/misc.h" #include "export.h" namespace FirFilterGenerators @@ -74,22 +75,6 @@ protected: } } - void normalize(Real sum_fix = 0.0) - { - Real sum = 0; - size_t i; - - for (i = 0; i < m_taps.size() - 1; ++i) { - sum += m_taps[i] * 2.0; - } - - sum += m_taps[i] + sum_fix; - - for (i = 0; i < m_taps.size(); ++i) { - m_taps[i] /= sum; - } - } - protected: std::vector m_taps; std::vector m_samples; @@ -104,7 +89,6 @@ public: { this->init(nTaps); FirFilterGenerators::generateLowPassFilter(nTaps, sampleRate, cutoff, this->m_taps); - this->normalize(); } }; @@ -129,7 +113,6 @@ struct Bandpass : public FirFilter } this->m_taps[this->m_taps.size() - 1] += 1; - this->normalize(-1.0); } }; @@ -146,6 +129,5 @@ struct Highpass : public FirFilter } this->m_taps[this->m_taps.size() - 1] += 1; - this->normalize(-1.0); } }; diff --git a/sdrbase/dsp/misc.h b/sdrbase/dsp/misc.h index f0c73f1f0..a4b41b65b 100644 --- a/sdrbase/dsp/misc.h +++ b/sdrbase/dsp/misc.h @@ -36,7 +36,8 @@ inline float cosc(float x) return (fabs(x) < 1e-10) ? 0.0 : ((1.0 - cos(M_PI * x)) / (M_PI * x)); } -inline float clamp(float x, float min, float max) +template +inline T clamp(T x, T min, T max) { return (x < min) ? min : ((x > max) ? max : x); }