diff --git a/plugins/channelrx/demodssb/ssbdemodsink.cpp b/plugins/channelrx/demodssb/ssbdemodsink.cpp index 43d9e0d73..ffb462960 100644 --- a/plugins/channelrx/demodssb/ssbdemodsink.cpp +++ b/plugins/channelrx/demodssb/ssbdemodsink.cpp @@ -69,10 +69,12 @@ SSBDemodSink::SSBDemodSink() : m_demodBufferFill = 0; m_usb = true; - m_magsq = 0.0f; - m_magsqSum = 0.0f; - m_magsqPeak = 0.0f; + m_magsq = 0.0; + m_magsqSum = 0.0; + m_magsqPeak = 0.0; m_magsqCount = 0; + m_magsqCur = 0.0; + m_magsqPrev = 0.0; m_agc.setClampMax(SDR_RX_SCALED/100.0); m_agc.setClamping(m_agcClamping); @@ -170,10 +172,24 @@ void SSBDemodSink::processOneSample(Complex &ci) m_sum.imag(0.0); } - float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 0.1; + float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 1.0; fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay()); m_audioActive = delayedSample.real() != 0.0; - m_squelchDelayLine.write(sideband[i]*agcVal); + m_magsqCur = std::norm(sideband[i]*agcVal); + + // Prevent overload if squared magnitude variation is 90% full scale (0.9*.0.9 = 0.81) + // Only if AGC is active + if (m_agcActive && (m_magsqCur - m_magsqPrev > m_agcTarget*m_agcTarget*8.1)) + { + m_agc.reset(m_agcTarget*100.0); // Quench AGC at -20dB the target + m_squelchDelayLine.write(sideband[i]); + } + else + { + m_squelchDelayLine.write(sideband[i]*agcVal); + } + + m_magsqPrev = m_magsqCur; if (m_audioMute) { diff --git a/plugins/channelrx/demodssb/ssbdemodsink.h b/plugins/channelrx/demodssb/ssbdemodsink.h index 92f3e9e1c..5c98e3d8c 100644 --- a/plugins/channelrx/demodssb/ssbdemodsink.h +++ b/plugins/channelrx/demodssb/ssbdemodsink.h @@ -101,6 +101,8 @@ private: double m_magsqSum; double m_magsqPeak; int m_magsqCount; + double m_magsqCur; + double m_magsqPrev; MagSqLevelsStore m_magSqLevelStore; MagAGC m_agc; bool m_agcActive; diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 006d7ba40..38b544a3e 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -32,6 +32,7 @@ public: void setOrder(double R) { m_R = R; } Real getValue(); Real getAverage(); + void reset(double R) { m_moving_average.fill(R); } virtual void feed(Complex& ci) = 0; protected: