diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index 80ca4d644..a3320cffd 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -51,6 +51,7 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) : m_agcNbSamples(12000), m_agcPowerThreshold(1e-2), m_agcThresholdGate(0), + m_squelchDelayLine(2*48000), m_audioActive(false), m_sampleSink(0), m_audioFifo(24000), @@ -207,8 +208,10 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_sum.imag(0.0); } - double agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 10.0; // 10.0 for 3276.8, 1.0 for 327.68 - m_audioActive = agcVal != 0.0; + float agcVal = m_agcActive ? m_agc.feedAndGetValue(sideband[i]) : 10.0; // 10.0 for 3276.8, 1.0 for 327.68 + fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay()); + m_audioActive = delayedSample.real() != 0.0; + m_squelchDelayLine.write(sideband[i]*agcVal); if (m_audioMute) { @@ -217,23 +220,25 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto } else { + fftfilt::cmplx z = delayedSample * m_agc.getStepDownValue(); + if (m_audioBinaual) { if (m_audioFlipChannels) { - m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].imag() * m_volume * agcVal); - m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].real() * m_volume * agcVal); + m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume); + m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume); } else { - m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].real() * m_volume * agcVal); - m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].imag() * m_volume * agcVal); + m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume); + m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume); } } else { - Real demod = (sideband[i].real() + sideband[i].imag()) * 0.7; - qint16 sample = (qint16)(demod * m_volume * agcVal); + Real demod = (z.real() + z.imag()) * 0.7; + qint16 sample = (qint16)(demod * m_volume); m_audioBuffer[m_audioBufferFill].l = sample; m_audioBuffer[m_audioBufferFill].r = sample; } diff --git a/plugins/channelrx/demodssb/ssbdemod.h b/plugins/channelrx/demodssb/ssbdemod.h index 038d27bd1..27e721e18 100644 --- a/plugins/channelrx/demodssb/ssbdemod.h +++ b/plugins/channelrx/demodssb/ssbdemod.h @@ -29,6 +29,7 @@ #include "dsp/agc.h" #include "audio/audiofifo.h" #include "util/message.h" +#include "util/doublebufferfifo.h" #include "ssbdemodsettings.h" @@ -259,6 +260,7 @@ private: int m_agcNbSamples; //!< number of audio (48 kHz) samples for AGC averaging double m_agcPowerThreshold; //!< AGC power threshold (linear) int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers + DoubleBufferFIFO m_squelchDelayLine; bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold) NCOF m_nco; diff --git a/plugins/channelrx/demodssb/ssbplugin.cpp b/plugins/channelrx/demodssb/ssbplugin.cpp index 07bf4b1d4..af380205a 100644 --- a/plugins/channelrx/demodssb/ssbplugin.cpp +++ b/plugins/channelrx/demodssb/ssbplugin.cpp @@ -8,7 +8,7 @@ const PluginDescriptor SSBPlugin::m_pluginDescriptor = { QString("SSB Demodulator"), - QString("3.14.0"), + QString("3.14.4"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp index 94b77cd0b..82f2f59b7 100644 --- a/sdrbase/dsp/agc.cpp +++ b/sdrbase/dsp/agc.cpp @@ -176,3 +176,15 @@ double MagAGC::feedAndGetValue(const Complex& ci) return m_u0; } } + +float MagAGC::getStepDownValue() const +{ + if (m_count < m_stepDownDelay) + { + return 1.0f; + } + else + { + return StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); + } +} diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 3c0b464bd..75f3959c7 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -50,6 +50,9 @@ public: void setStepDownDelay(int stepDownDelay) { m_stepDownDelay = stepDownDelay; } void setClamping(bool clamping) { m_clamping = clamping; } void setClampMax(double clampMax) { m_clampMax = clampMax; } + int getStepDownDelay() const { return m_stepDownDelay; } + float getStepDownValue() const; + private: bool m_squared; //!< use squared magnitude (power) to compute AGC value double m_magsq; //!< current squared magnitude (power)