From b31e62e73c6ecf819aa4ca2167e68b1186474b65 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 7 Sep 2015 01:15:55 +0200 Subject: [PATCH] Fixed NFM strong signals handling --- include-gpl/dsp/agc.h | 80 ++++++++++++++++++++++++++------ plugins/channel/nfm/nfmdemod.cpp | 8 ++-- plugins/channel/nfm/nfmdemod.h | 2 +- sdrbase/dsp/channelizer.cpp | 2 + 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/include-gpl/dsp/agc.h b/include-gpl/dsp/agc.h index 48a463b49..684193a98 100644 --- a/include-gpl/dsp/agc.h +++ b/include-gpl/dsp/agc.h @@ -87,19 +87,25 @@ public: EvenSimplerAGC() : m_u0(1.0), m_R(1.0), - m_moving_average() + m_moving_average(), + m_historySize(0), + m_count(0) {} EvenSimplerAGC(int historySize, Real R) : m_u0(1.0), m_R(R), - m_moving_average(historySize, m_R) + m_moving_average(historySize, m_R), + m_historySize(historySize), + m_count(0) {} void resize(int historySize, Real R) { m_R = R; m_moving_average.resize(historySize, R); + m_historySize = historySize; + m_count = 0; } Real getValue() @@ -107,28 +113,49 @@ public: return m_u0; } + Real getDelayedValue() + { + if (m_count < m_historySize*m_mult) + { + return 0; + } + else + { + return m_u0; + } + } + void feed(Complex& ci) { ci *= m_u0; - Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); - m_moving_average.feed(magsq); + Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); + m_moving_average.feed(mag); } void openedSquelch() { + if (m_count < m_historySize*m_mult) + { + m_count++; + } + m_u0 = m_R / m_moving_average.average(); } void closedSquelch() { //m_moving_average.fill(m_R); // Valgrind optim - m_u0 = 1.0; + m_count = 0; + m_u0 = m_R / m_moving_average.average(); } private: Real m_u0; - Real m_R; // objective magsq + Real m_R; // objective mag MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. + int m_historySize; + int m_count; + static const int m_mult = 4; }; class AlphaAGC @@ -140,7 +167,9 @@ public: m_R(1.0), m_alpha(0.1), m_squelchOpen(true), - m_moving_average() + m_moving_average(), + m_historySize(0), + m_count(0) {} AlphaAGC(int historySize, Real R, Real alpha) : @@ -148,7 +177,9 @@ public: m_R(R), m_alpha(alpha), m_squelchOpen(true), - m_moving_average(historySize, m_R) + m_moving_average(historySize, m_R), + m_historySize(historySize), + m_count(0) {} void resize(int historySize, Real R, Real alpha) @@ -157,6 +188,8 @@ public: m_alpha = alpha; m_squelchOpen = true; m_moving_average.resize(historySize, R); + m_historySize = historySize; + m_count = 0; } Real getValue() @@ -164,25 +197,42 @@ public: return m_u0; } + Real getDelayedValue() + { + if (m_count < m_historySize) + { + return 0; + } + else + { + return m_u0; + } + } + void feed(Complex& ci) { ci *= m_u0; - Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); - if (m_squelchOpen && (magsq < m_moving_average.average())) + if (m_squelchOpen && (mag < m_moving_average.average())) { - m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - magsq)); + m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - mag)); } else { //m_squelchOpen = true; - m_moving_average.feed(magsq); + m_moving_average.feed(mag); } } void openedSquelch() { + if (m_count < m_historySize) + { + m_count++; + } + m_u0 = m_R / m_moving_average.average(); m_squelchOpen = true; } @@ -190,7 +240,9 @@ public: void closedSquelch() { //m_moving_average.fill(m_R); // Valgrind optim - m_u0 = 1.0; + m_count = 0; + //m_u0 = 1.0; + m_u0 = m_R / m_moving_average.average(); m_squelchOpen = false; } @@ -200,6 +252,8 @@ private: Real m_alpha; bool m_squelchOpen; MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. + int m_historySize; + int m_count; }; diff --git a/plugins/channel/nfm/nfmdemod.cpp b/plugins/channel/nfm/nfmdemod.cpp index 944596fc5..fc36144e1 100644 --- a/plugins/channel/nfm/nfmdemod.cpp +++ b/plugins/channel/nfm/nfmdemod.cpp @@ -55,9 +55,9 @@ NFMDemod::NFMDemod() : m_audioBufferFill = 0; m_movingAverage.resize(16, 0); - m_agcLevel = 0.003; // 0.003 + m_agcLevel = 0.25; // 0.003 //m_AGC.resize(480, m_agcLevel, 0, 0.1*m_agcLevel); - m_AGC.resize(240, m_agcLevel*m_agcLevel, 0.3); + m_AGC.resize(600, m_agcLevel*m_agcLevel); //, 0.3); m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution m_afSquelch.setCoefficients(24, 48000.0, 5, 1); // 4000 Hz span, 250us @@ -165,7 +165,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto Real qp = ci.imag() - m_m2Sample.imag(); Real h1 = m_m1Sample.real() * qp; Real h2 = m_m1Sample.imag() * ip; - Real demod = (h1 - h2) * 10000; + Real demod = (h1 - h2) * 30; // 10000 m_m2Sample = m_m1Sample; m_m1Sample = ci; @@ -218,7 +218,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto { demod = m_bandpass.filter(demod); demod *= m_running.m_volume; - sample = demod * ((1<<15)/301); // denominator = bandpass filter number of taps + sample = demod * ((1<<15)/301) * m_AGC.getDelayedValue(); // denominator = bandpass filter number of taps } m_AGC.openedSquelch(); diff --git a/plugins/channel/nfm/nfmdemod.h b/plugins/channel/nfm/nfmdemod.h index 6bd64cebf..f31329cad 100644 --- a/plugins/channel/nfm/nfmdemod.h +++ b/plugins/channel/nfm/nfmdemod.h @@ -163,7 +163,7 @@ private: Complex m_m1Sample; Complex m_m2Sample; MovingAverage m_movingAverage; - AlphaAGC m_AGC; + EvenSimplerAGC m_AGC; Real m_agcLevel; // AGC will aim to this level Real m_agcFloor; // AGC will not go below this level diff --git a/sdrbase/dsp/channelizer.cpp b/sdrbase/dsp/channelizer.cpp index 1481cd3fc..a94bad8dd 100644 --- a/sdrbase/dsp/channelizer.cpp +++ b/sdrbase/dsp/channelizer.cpp @@ -86,6 +86,8 @@ bool Channelizer::handleMessage(const Message& cmd) { qDebug() << "Channelizer::handleMessage: " << cmd.getIdentifier(); + // TODO: apply changes only if input sample rate or requested output sample rate change. Change of center frequency has no impact. + if (DSPSignalNotification::match(cmd)) { DSPSignalNotification& notif = (DSPSignalNotification&) cmd;