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:
parent
4670cbaa33
commit
7e6267f41c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user