diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index bf1eb03be..090e28826 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -110,6 +110,7 @@ SSBMod::SSBMod(DeviceSinkAPI *deviceAPI) : m_inAGC.setGate(m_settings.m_agcThresholdGate); m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay); m_inAGC.setClamping(true); + m_inAGC.setHardLimiting(true); applyChannelSettings(m_basebandSampleRate, m_outputSampleRate, m_inputFrequencyOffset, true); applySettings(m_settings, true); diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp index 93671c617..c105b3145 100644 --- a/sdrbase/dsp/agc.cpp +++ b/sdrbase/dsp/agc.cpp @@ -55,7 +55,8 @@ MagAGC::MagAGC(int historySize, double R, double threshold) : m_stepDownDelay(historySize), m_clamping(false), m_R2(R*R), - m_clampMax(1.0) + m_clampMax(1.0), + m_hardLimiting(false) {} MagAGC::~MagAGC() @@ -95,6 +96,15 @@ void MagAGC::feed(Complex& ci) ci *= feedAndGetValue(ci); } +double MagAGC::hardLimiter(double multiplier, double magsq) +{ + if ((m_hardLimiting) && (multiplier*multiplier*magsq > 1.0)) { + return 1.0 / (multiplier*sqrt(magsq)); + } else { + return multiplier; + } +} + double MagAGC::feedAndGetValue(const Complex& ci) { m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); @@ -153,11 +163,11 @@ double MagAGC::feedAndGetValue(const Complex& ci) if (m_stepUpCounter < m_stepLength) { m_stepUpCounter++; - return m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta); + return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta), m_magsq); } else { - return m_u0; + return hardLimiter(m_u0, m_magsq); } } else @@ -167,7 +177,7 @@ double MagAGC::feedAndGetValue(const Complex& ci) if (m_stepDownCounter > 0) { m_stepDownCounter--; - return m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); + return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta), m_magsq); } else { @@ -177,7 +187,7 @@ double MagAGC::feedAndGetValue(const Complex& ci) } else { - return m_u0; + return hardLimiter(m_u0, m_magsq); } } diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 196b523af..f1f1745b2 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -53,6 +53,7 @@ public: int getStepDownDelay() const { return m_stepDownDelay; } float getStepDownValue() const; float getStepValue() const; + void setHardLimiting(bool hardLimiting) { m_hardLimiting = hardLimiting; } private: bool m_squared; //!< use squared magnitude (power) to compute AGC value @@ -69,6 +70,9 @@ private: bool m_clamping; //!< clamping active double m_R2; //!< square of ordered magnitude double m_clampMax; //!< maximum to clamp to as power value + bool m_hardLimiting; //!< hard limit multiplier so that resulting sample magnitude does not exceed 1.0 + + double hardLimiter(double multiplier, double magsq); }; template