diff --git a/include-gpl/dsp/agc.h b/include-gpl/dsp/agc.h index 684193a98..170dc4682 100644 --- a/include-gpl/dsp/agc.h +++ b/include-gpl/dsp/agc.h @@ -80,11 +80,11 @@ private: }; -class EvenSimplerAGC +class MagSquaredAGC { public: - EvenSimplerAGC() : + MagSquaredAGC() : m_u0(1.0), m_R(1.0), m_moving_average(), @@ -92,7 +92,85 @@ public: m_count(0) {} - EvenSimplerAGC(int historySize, Real R) : + MagSquaredAGC(int historySize, Real R) : + m_u0(1.0), + m_R(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() + { + return m_u0; + } + + Real getDelayedValue() + { + if (m_count < m_historySize*m_mult) + { + return 0; + } + else + { + return 1; + } + } + + void feed(Complex& ci) + { + ci *= m_u0; + Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + m_moving_average.feed(magsq); + } + + 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_count = 0; + m_u0 = m_R / m_moving_average.average(); + } + +private: + Real m_u0; + Real m_R; // objective mag + MovingAverage<Real> 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; // squelch delay multiplicator +}; + +class MagAGC +{ +public: + + MagAGC() : + m_u0(1.0), + m_R(1.0), + m_moving_average(), + m_historySize(0), + m_count(0) + {} + + MagAGC(int historySize, Real R) : m_u0(1.0), m_R(R), m_moving_average(historySize, m_R), diff --git a/plugins/channel/nfm/nfmdemod.cpp b/plugins/channel/nfm/nfmdemod.cpp index fc36144e1..d6a4f537a 100644 --- a/plugins/channel/nfm/nfmdemod.cpp +++ b/plugins/channel/nfm/nfmdemod.cpp @@ -26,7 +26,7 @@ #include "dsp/pidcontroller.h" #include "dsp/dspengine.h" -static const Real afSqTones[2] = {1200.0, 6000.0}; // {1200.0, 8000.0}; +static const Real afSqTones[2] = {1200.0, 8000.0}; // {1200.0, 8000.0}; MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message) @@ -55,7 +55,7 @@ NFMDemod::NFMDemod() : m_audioBufferFill = 0; m_movingAverage.resize(16, 0); - m_agcLevel = 0.25; // 0.003 + m_agcLevel = 0.0625; // 0.003 //m_AGC.resize(480, m_agcLevel, 0, 0.1*m_agcLevel); m_AGC.resize(600, m_agcLevel*m_agcLevel); //, 0.3); @@ -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) * 30; // 10000 + Real demod = (h1 - h2) * 16; // 10000 (multiply by 2^16 after demod) 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) * m_AGC.getDelayedValue(); // denominator = bandpass filter number of taps + sample = demod * ((1<<16)/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 f31329cad..b7eff886b 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<Real> m_movingAverage; - EvenSimplerAGC m_AGC; + MagSquaredAGC m_AGC; Real m_agcLevel; // AGC will aim to this level Real m_agcFloor; // AGC will not go below this level