1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 09:48:45 -05:00

SSB demod: use delay line to squeeze squelch tail

This commit is contained in:
f4exb 2018-04-22 09:37:34 +02:00
parent 4670cbaa33
commit 7e6267f41c
5 changed files with 31 additions and 9 deletions

View File

@ -51,6 +51,7 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
m_agcNbSamples(12000), m_agcNbSamples(12000),
m_agcPowerThreshold(1e-2), m_agcPowerThreshold(1e-2),
m_agcThresholdGate(0), m_agcThresholdGate(0),
m_squelchDelayLine(2*48000),
m_audioActive(false), m_audioActive(false),
m_sampleSink(0), m_sampleSink(0),
m_audioFifo(24000), m_audioFifo(24000),
@ -207,8 +208,10 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
m_sum.imag(0.0); 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 float 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; fftfilt::cmplx& delayedSample = m_squelchDelayLine.readBack(m_agc.getStepDownDelay());
m_audioActive = delayedSample.real() != 0.0;
m_squelchDelayLine.write(sideband[i]*agcVal);
if (m_audioMute) if (m_audioMute)
{ {
@ -217,23 +220,25 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
} }
else else
{ {
fftfilt::cmplx z = delayedSample * m_agc.getStepDownValue();
if (m_audioBinaual) if (m_audioBinaual)
{ {
if (m_audioFlipChannels) if (m_audioFlipChannels)
{ {
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].imag() * m_volume * agcVal); m_audioBuffer[m_audioBufferFill].r = (qint16)(z.imag() * m_volume);
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].real() * m_volume * agcVal); m_audioBuffer[m_audioBufferFill].l = (qint16)(z.real() * m_volume);
} }
else else
{ {
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].real() * m_volume * agcVal); m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].imag() * m_volume * agcVal); m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
} }
} }
else else
{ {
Real demod = (sideband[i].real() + sideband[i].imag()) * 0.7; Real demod = (z.real() + z.imag()) * 0.7;
qint16 sample = (qint16)(demod * m_volume * agcVal); qint16 sample = (qint16)(demod * m_volume);
m_audioBuffer[m_audioBufferFill].l = sample; m_audioBuffer[m_audioBufferFill].l = sample;
m_audioBuffer[m_audioBufferFill].r = sample; m_audioBuffer[m_audioBufferFill].r = sample;
} }

View File

@ -29,6 +29,7 @@
#include "dsp/agc.h" #include "dsp/agc.h"
#include "audio/audiofifo.h" #include "audio/audiofifo.h"
#include "util/message.h" #include "util/message.h"
#include "util/doublebufferfifo.h"
#include "ssbdemodsettings.h" #include "ssbdemodsettings.h"
@ -259,6 +260,7 @@ private:
int m_agcNbSamples; //!< number of audio (48 kHz) samples for AGC averaging int m_agcNbSamples; //!< number of audio (48 kHz) samples for AGC averaging
double m_agcPowerThreshold; //!< AGC power threshold (linear) double m_agcPowerThreshold; //!< AGC power threshold (linear)
int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers int m_agcThresholdGate; //!< Gate length in number of samples befor threshold triggers
DoubleBufferFIFO<fftfilt::cmplx> m_squelchDelayLine;
bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold) bool m_audioActive; //!< True if an audio signal is produced (no AGC or AGC and above threshold)
NCOF m_nco; NCOF m_nco;

View File

@ -8,7 +8,7 @@
const PluginDescriptor SSBPlugin::m_pluginDescriptor = { const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
QString("SSB Demodulator"), QString("SSB Demodulator"),
QString("3.14.0"), QString("3.14.4"),
QString("(c) Edouard Griffiths, F4EXB"), QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"), QString("https://github.com/f4exb/sdrangel"),
true, true,

View File

@ -176,3 +176,15 @@ double MagAGC::feedAndGetValue(const Complex& ci)
return m_u0; return m_u0;
} }
} }
float MagAGC::getStepDownValue() const
{
if (m_count < m_stepDownDelay)
{
return 1.0f;
}
else
{
return StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta);
}
}

View File

@ -50,6 +50,9 @@ public:
void setStepDownDelay(int stepDownDelay) { m_stepDownDelay = stepDownDelay; } void setStepDownDelay(int stepDownDelay) { m_stepDownDelay = stepDownDelay; }
void setClamping(bool clamping) { m_clamping = clamping; } void setClamping(bool clamping) { m_clamping = clamping; }
void setClampMax(double clampMax) { m_clampMax = clampMax; } void setClampMax(double clampMax) { m_clampMax = clampMax; }
int getStepDownDelay() const { return m_stepDownDelay; }
float getStepDownValue() const;
private: private:
bool m_squared; //!< use squared magnitude (power) to compute AGC value bool m_squared; //!< use squared magnitude (power) to compute AGC value
double m_magsq; //!< current squared magnitude (power) double m_magsq; //!< current squared magnitude (power)