From 9ec4e6de985c1b8cdb33bd7d686ad1e527a68e2a Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 25 Jul 2017 23:39:27 +0200 Subject: [PATCH] SSB demod: improve AGC threshold handling --- plugins/channelrx/demodssb/ssbdemod.cpp | 2 +- plugins/channelrx/demodssb/ssbdemodgui.cpp | 27 ++++++-- plugins/channelrx/demodssb/ssbdemodgui.h | 1 + plugins/channelrx/demodssb/ssbdemodgui.ui | 52 ++++++++++++++-- sdrbase/dsp/agc.cpp | 71 +++++++++++++++++++--- sdrbase/dsp/agc.h | 10 ++- sdrbase/util/smootherstep.h | 30 +++++++++ 7 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 sdrbase/util/smootherstep.h diff --git a/plugins/channelrx/demodssb/ssbdemod.cpp b/plugins/channelrx/demodssb/ssbdemod.cpp index dde581f3d..fc28113ad 100644 --- a/plugins/channelrx/demodssb/ssbdemod.cpp +++ b/plugins/channelrx/demodssb/ssbdemod.cpp @@ -302,7 +302,7 @@ bool SSBDemod::handleMessage(const Message& cmd) DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate); m_volume = cfg.getVolume(); - m_volume *= m_volume * 0.1; + m_volume *= 2.0; m_spanLog2 = cfg.getSpanLog2(); m_audioBinaual = cfg.getAudioBinaural(); diff --git a/plugins/channelrx/demodssb/ssbdemodgui.cpp b/plugins/channelrx/demodssb/ssbdemodgui.cpp index f8d775e5e..f47d5d440 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.cpp +++ b/plugins/channelrx/demodssb/ssbdemodgui.cpp @@ -129,9 +129,17 @@ bool SSBDemodGUI::deserialize(const QByteArray& data) d.readBool(11, &booltmp, false); ui->agc->setChecked(booltmp); d.readS32(12, &tmp, 7); - ui->agcTimeText->setText(QString("%1").arg((1<agcTimeLog2->setValue(tmp); + QString s = QString::number((1<agcTimeText->setText(s); d.readS32(13, &tmp, -20); - ui->agcPowerThresholdText->setText(QString("%1").arg(tmp, 0, 'f', 0)); + ui->agcPowerThreshold->setValue(tmp); + s = QString::number(tmp, 'f', 0); + ui->agcPowerThresholdText->setText(s); + d.readS32(14, &tmp, 5); + ui->agcThresholdGate->setValue(tmp); + s = QString::number(tmp*10, 'f', 0); + ui->agcThresholdGateText->setText(s); blockApplySettings(false); m_channelMarker.blockSignals(false); @@ -275,20 +283,29 @@ void SSBDemodGUI::on_volume_valueChanged(int value) applySettings(); } -void SSBDemodGUI::on_agc_stateChanged(int state) +void SSBDemodGUI::on_agc_stateChanged(int state __attribute((__unused__))) { applySettings(); } void SSBDemodGUI::on_agcTimeLog2_valueChanged(int value) { - ui->agcTimeText->setText(QString("%1").arg((1<agcTimeText->setText(s); applySettings(); } void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value) { - ui->agcPowerThresholdText->setText(QString("%1").arg(value, 0, 'f', 0)); + QString s = QString::number(value, 'f', 0); + ui->agcPowerThresholdText->setText(s); + applySettings(); +} + +void SSBDemodGUI::on_agcThresholdGate_valueChanged(int value) +{ + QString s = QString::number(value * 10, 'f', 0); + ui->agcThresholdGateText->setText(s); applySettings(); } diff --git a/plugins/channelrx/demodssb/ssbdemodgui.h b/plugins/channelrx/demodssb/ssbdemodgui.h index 56d732cd5..3c3b58fc2 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.h +++ b/plugins/channelrx/demodssb/ssbdemodgui.h @@ -51,6 +51,7 @@ private slots: void on_agc_stateChanged(int state); void on_agcTimeLog2_valueChanged(int value); void on_agcPowerThreshold_valueChanged(int value); + void on_agcThresholdGate_valueChanged(int value); void on_audioMute_toggled(bool checked); void on_spanLog2_valueChanged(int value); void onWidgetRolled(QWidget* widget, bool rollDown); diff --git a/plugins/channelrx/demodssb/ssbdemodgui.ui b/plugins/channelrx/demodssb/ssbdemodgui.ui index c65ef4a00..a4fb0ec03 100644 --- a/plugins/channelrx/demodssb/ssbdemodgui.ui +++ b/plugins/channelrx/demodssb/ssbdemodgui.ui @@ -6,7 +6,7 @@ 0 0 - 370 + 435 160 @@ -36,7 +36,7 @@ 0 0 - 360 + 421 151 @@ -479,8 +479,11 @@ AGC time constant (ms in log2 steps) + + 4 + - 10 + 11 1 @@ -494,7 +497,7 @@ - 30 + 35 0 @@ -553,6 +556,47 @@ + + + + + 24 + 24 + + + + Set threshiold gate (ms) + + + 50 + + + 1 + + + 5 + + + + + + + + 24 + 0 + + + + Threshiold gate (ms) + + + 000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp index 7f36a3a58..f87c5660f 100644 --- a/sdrbase/dsp/agc.cpp +++ b/sdrbase/dsp/agc.cpp @@ -6,6 +6,7 @@ */ #include "dsp/agc.h" +#include "util/smootherstep.h" AGC::AGC(int historySize, Real R) : @@ -46,7 +47,9 @@ MagSquaredAGC::MagSquaredAGC(int historySize, double R, double threshold) : AGC(historySize, R), m_magsq(0.0), m_threshold(threshold), - m_thresholdCount(0) + m_gate(0), + m_stepCounter(0), + m_gateCounter(0) {} MagSquaredAGC::~MagSquaredAGC() @@ -68,16 +71,39 @@ double MagSquaredAGC::feedAndGetValue(const Complex& ci) if (m_magsq > m_threshold) { - m_thresholdCount = 0; + if (m_gateCounter < m_gate) + { + m_gateCounter++; + } + else + { + m_count = 0; + } } else { - if (m_thresholdCount < m_moving_average.historySize()) { - m_thresholdCount++; + if (m_count < m_moving_average.historySize()) { + m_count++; } + + m_gateCounter = 0; } - return (m_thresholdCount < m_moving_average.historySize()) ? m_u0 : 0.0; + if (m_count < m_moving_average.historySize()) + { + if (m_stepCounter < 2400) { + m_stepCounter++; + } + + return m_u0 * StepFunctions::smootherstep(m_stepCounter/2400.0); + } + else + { + m_stepCounter = 0; + return 0.0; + } + + //return (m_count < m_moving_average.historySize()) ? m_u0 : 0.0; } //MagAGC::MagAGC() : @@ -89,7 +115,9 @@ MagAGC::MagAGC(int historySize, double R, double threshold) : AGC(historySize, R), m_magsq(0.0), m_threshold(threshold), - m_thresholdCount(0) + m_gate(0), + m_stepCounter(0), + m_gateCounter(0) {} MagAGC::~MagAGC() @@ -111,16 +139,39 @@ double MagAGC::feedAndGetValue(const Complex& ci) if (m_magsq > m_threshold) { - m_thresholdCount = 0; + if (m_gateCounter < m_gate) + { + m_gateCounter++; + } + else + { + m_count = 0; + } } else { - if (m_thresholdCount < m_moving_average.historySize()) { - m_thresholdCount++; + if (m_count < m_moving_average.historySize()) { + m_count++; } + + m_gateCounter = 0; } - return (m_thresholdCount < m_moving_average.historySize()) ? m_u0 : 0.0; + if (m_count < m_moving_average.historySize()) + { + if (m_stepCounter < 480) { + m_stepCounter++; + } + + return m_u0 * StepFunctions::smootherstep(m_stepCounter/480.0); + } + else + { + m_stepCounter = 0; + return 0.0; + } + + //return (m_count < m_moving_average.historySize()) ? m_u0 : 0.0; } //AlphaAGC::AlphaAGC() : diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 99eab76d4..61bb74c77 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -38,10 +38,13 @@ public: double feedAndGetValue(const Complex& ci); double getMagSq() const { return m_magsq; } void setThreshold(double threshold) { m_threshold = threshold; } + void setGate(int gate) { m_gate = gate; } private: double m_magsq; double m_threshold; //!< squelch on magsq average with transition from +3dB - int m_thresholdCount; + int m_gate; + int m_stepCounter; + int m_gateCounter; }; class MagAGC : public AGC @@ -53,10 +56,13 @@ public: double feedAndGetValue(const Complex& ci); Real getMagSq() const { return m_magsq; } void setThreshold(double threshold) { m_threshold = threshold; } + void setGate(int gate) { m_gate = gate; } private: double m_magsq; double m_threshold; //!< squelch on magsq average - int m_thresholdCount; + int m_gate; + int m_stepCounter; + int m_gateCounter; }; class AlphaAGC : public AGC diff --git a/sdrbase/util/smootherstep.h b/sdrbase/util/smootherstep.h new file mode 100644 index 000000000..ceaea6d6b --- /dev/null +++ b/sdrbase/util/smootherstep.h @@ -0,0 +1,30 @@ +/* + * smootherstep.h + * + * Created on: Jul 25, 2017 + * Author: f4exb + */ + +#ifndef SDRBASE_UTIL_SMOOTHERSTEP_H_ +#define SDRBASE_UTIL_SMOOTHERSTEP_H_ + +class StepFunctions +{ +public: + static float smootherstep(float x) + { + if (x == 1.0f) { + return 1.0f; + } else if (x == 0.0f) { + return 0.0f; + } + + double x3 = x * x * x; + double x4 = x * x3; + double x5 = x * x4; + + return (float) (6.0*x5 - 15.0*x4 + 10.0*x3); + } +}; + +#endif /* SDRBASE_UTIL_SMOOTHERSTEP_H_ */