SSB Modulator: implemented hard limiter on compressor to prevent overload

This commit is contained in:
f4exb 2019-05-07 02:50:05 +02:00
parent a9a149ec4b
commit a69d8a6422
3 changed files with 20 additions and 5 deletions

View File

@ -110,6 +110,7 @@ SSBMod::SSBMod(DeviceSinkAPI *deviceAPI) :
m_inAGC.setGate(m_settings.m_agcThresholdGate); m_inAGC.setGate(m_settings.m_agcThresholdGate);
m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay); m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay);
m_inAGC.setClamping(true); m_inAGC.setClamping(true);
m_inAGC.setHardLimiting(true);
applyChannelSettings(m_basebandSampleRate, m_outputSampleRate, m_inputFrequencyOffset, true); applyChannelSettings(m_basebandSampleRate, m_outputSampleRate, m_inputFrequencyOffset, true);
applySettings(m_settings, true); applySettings(m_settings, true);

View File

@ -55,7 +55,8 @@ MagAGC::MagAGC(int historySize, double R, double threshold) :
m_stepDownDelay(historySize), m_stepDownDelay(historySize),
m_clamping(false), m_clamping(false),
m_R2(R*R), m_R2(R*R),
m_clampMax(1.0) m_clampMax(1.0),
m_hardLimiting(false)
{} {}
MagAGC::~MagAGC() MagAGC::~MagAGC()
@ -95,6 +96,15 @@ void MagAGC::feed(Complex& ci)
ci *= feedAndGetValue(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) double MagAGC::feedAndGetValue(const Complex& ci)
{ {
m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); 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) if (m_stepUpCounter < m_stepLength)
{ {
m_stepUpCounter++; m_stepUpCounter++;
return m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta); return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta), m_magsq);
} }
else else
{ {
return m_u0; return hardLimiter(m_u0, m_magsq);
} }
} }
else else
@ -167,7 +177,7 @@ double MagAGC::feedAndGetValue(const Complex& ci)
if (m_stepDownCounter > 0) if (m_stepDownCounter > 0)
{ {
m_stepDownCounter--; m_stepDownCounter--;
return m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta), m_magsq);
} }
else else
{ {
@ -177,7 +187,7 @@ double MagAGC::feedAndGetValue(const Complex& ci)
} }
else else
{ {
return m_u0; return hardLimiter(m_u0, m_magsq);
} }
} }

View File

@ -53,6 +53,7 @@ public:
int getStepDownDelay() const { return m_stepDownDelay; } int getStepDownDelay() const { return m_stepDownDelay; }
float getStepDownValue() const; float getStepDownValue() const;
float getStepValue() const; float getStepValue() const;
void setHardLimiting(bool hardLimiting) { m_hardLimiting = hardLimiting; }
private: private:
bool m_squared; //!< use squared magnitude (power) to compute AGC value bool m_squared; //!< use squared magnitude (power) to compute AGC value
@ -69,6 +70,9 @@ private:
bool m_clamping; //!< clamping active bool m_clamping; //!< clamping active
double m_R2; //!< square of ordered magnitude double m_R2; //!< square of ordered magnitude
double m_clampMax; //!< maximum to clamp to as power value 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<uint32_t AvgSize> template<uint32_t AvgSize>