Skip to content

Commit

Permalink
SSB demod: better algorithm for AGC limitation. For #1918
Browse files Browse the repository at this point in the history
  • Loading branch information
f4exb committed Dec 11, 2023
1 parent f988007 commit 68601d6
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 14 deletions.
2 changes: 1 addition & 1 deletion plugins/channelrx/demodssb/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ This AGC is based on the calculated magnitude (square root of power of the filte

<h4>13.3: AGC clamping</h4>

When on this clamps signal at the maximum amplitude. Normally this is not needed for most signals as the AGC amplitude order is quite conservative at 10% of the maximum. You may switch it on if you notice a loud click when a transmission starts.
This limits AGC gain when signal rises up sharply avoiding peak audio overload. You may switch it on if you notice a loud click on strong signals after silences.

<h4>13.4: Noise Reduction</h4>

Expand Down
15 changes: 4 additions & 11 deletions plugins/channelrx/demodssb/ssbdemodsink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ SSBDemodSink::SSBDemodSink() :
m_magsqSum = 0.0;
m_magsqPeak = 0.0;
m_magsqCount = 0;
m_magsqCur = 0.0;
m_magsqPrev = 0.0;

SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, m_ssbFftLen);
DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen);
Expand Down Expand Up @@ -175,32 +173,27 @@ void SSBDemodSink::processOneSample(Complex &ci)
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_magsqCur = std::norm(sideband[i]*agcVal);

// Prevent overload based on squared magnitude variation
// Only if AGC is active
if (m_agcActive && m_agcClamping && (std::abs(m_magsqCur - m_magsqPrev) > m_agcTarget*m_agcTarget*5.0) & (agcVal > 100.0))
if (m_agcActive && m_agcClamping && agcVal > 100.0)
{
float target = m_agcTarget*sqrt(agcVal); // Quench AGC depending on previous value
m_agc.reset(target);
m_squelchDelayLine.write(fftfilt::cmplx{target, 0.0});
m_magsqCur = target*target;
qDebug("SSBDemodSink::processOneSample: %f", agcVal);
m_agc.reset(m_agcTarget*m_agcTarget);
m_squelchDelayLine.write(fftfilt::cmplx{0.0, 0.0});
}
else
{
m_squelchDelayLine.write(sideband[i]*agcVal);
}

m_magsqPrev = m_magsqCur;

if (m_audioMute)
{
m_audioBuffer[m_audioBufferFill].r = 0;
m_audioBuffer[m_audioBufferFill].l = 0;
}
else
{
// fftfilt::cmplx z = m_agcActive ? delayedSample * m_agc.getStepValue() : delayedSample;
fftfilt::cmplx z = (m_agcActive && m_agcClamping) ?
fftfilt::cmplx{m_lowpassI.filter(delayedSample.real()), m_lowpassQ.filter(delayedSample.imag())}
: delayedSample;
Expand Down
2 changes: 0 additions & 2 deletions plugins/channelrx/demodssb/ssbdemodsink.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ class SSBDemodSink : public ChannelSampleSink {
double m_magsqSum;
double m_magsqPeak;
int m_magsqCount;
double m_magsqCur;
double m_magsqPrev;
MagSqLevelsStore m_magSqLevelStore;
MagAGC m_agc;
bool m_agcActive;
Expand Down

0 comments on commit 68601d6

Please sign in to comment.