From 12f5f4e30c270410e3ad1cd15198084d39483415 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 21 Apr 2018 09:23:01 +0200 Subject: [PATCH] NFM demod: buffered squelch --- app/main.cpp | 2 +- appsrv/main.cpp | 2 +- plugins/channelrx/demodnfm/nfmdemod.cpp | 43 +++++++----- plugins/channelrx/demodnfm/nfmdemod.h | 2 + plugins/channelrx/demodnfm/nfmplugin.cpp | 2 +- sdrbase/CMakeLists.txt | 2 +- sdrbase/util/doublebufferfifo.h | 84 ++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 21 deletions(-) create mode 100644 sdrbase/util/doublebufferfifo.h diff --git a/app/main.cpp b/app/main.cpp index 14164fd21..a843b4f10 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -35,7 +35,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo */ QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangel"); - QCoreApplication::setApplicationVersion("3.14.3"); + QCoreApplication::setApplicationVersion("3.14.4"); #if 1 qApp->setStyle(QStyleFactory::create("fusion")); diff --git a/appsrv/main.cpp b/appsrv/main.cpp index 608ede061..3c82592f2 100644 --- a/appsrv/main.cpp +++ b/appsrv/main.cpp @@ -56,7 +56,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangelSrv"); - QCoreApplication::setApplicationVersion("3.14.3"); + QCoreApplication::setApplicationVersion("3.14.4"); int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); diff --git a/plugins/channelrx/demodnfm/nfmdemod.cpp b/plugins/channelrx/demodnfm/nfmdemod.cpp index 38e0eec9d..7aa4bebbe 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.cpp +++ b/plugins/channelrx/demodnfm/nfmdemod.cpp @@ -57,7 +57,7 @@ NFMDemod::NFMDemod(DeviceSourceAPI *devieAPI) : m_sampleCount(0), m_squelchCount(0), m_squelchGate(4800), - m_squelchDecay(480), + m_squelchDecay(4800), m_squelchLevel(-990), m_squelchOpen(false), m_afSquelchOpen(false), @@ -66,6 +66,7 @@ NFMDemod::NFMDemod(DeviceSourceAPI *devieAPI) : m_magsqPeak(0.0f), m_magsqCount(0), m_afSquelch(), + m_squelchDelayLine(24000), m_audioFifo(48000), m_settingsMutex(QMutex::Recursive) { @@ -178,22 +179,29 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto if (m_settings.m_deltaSquelch) { - if (m_afSquelch.analyze(demod * m_discriCompensation)) { - m_afSquelchOpen = m_afSquelch.evaluate() ? m_squelchGate + m_squelchDecay : 0; + if (m_afSquelch.analyze(demod * m_discriCompensation)) + { + m_afSquelchOpen = m_afSquelch.evaluate(); // ? m_squelchGate + m_squelchDecay : 0; + + if (!m_afSquelchOpen) { + m_squelchDelayLine.zeroBack(m_audioSampleRate/10); // zero out evaluation period + } } if (m_afSquelchOpen) { - if (m_squelchCount < m_squelchGate + m_squelchDecay) - { + m_squelchDelayLine.write(demod * m_discriCompensation); + + if (m_squelchCount < m_squelchGate + m_squelchDecay) { m_squelchCount++; } } else { - if (m_squelchCount > 0) - { - m_squelchCount -= 10; + m_squelchDelayLine.write(0); + + if (m_squelchCount > 0) { + m_squelchCount--; } } } @@ -201,15 +209,17 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto { if ((Real) m_movingAverage < m_squelchLevel) { - if (m_squelchCount > 0) - { - m_squelchCount -= 10; + m_squelchDelayLine.write(0); + + if (m_squelchCount > 0) { + m_squelchCount--; } } else { - if (m_squelchCount < m_squelchGate + m_squelchDecay) - { + m_squelchDelayLine.write(demod * m_discriCompensation); + + if (m_squelchCount < m_squelchGate + m_squelchDecay) { m_squelchCount++; } } @@ -261,9 +271,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto } else { - demod = m_bandpass.filter(demod * m_discriCompensation); - Real squelchFactor = StepFunctions::smootherstep((Real) (m_squelchCount - m_squelchGate) / (Real) m_squelchDecay); - sample = demod * m_settings.m_volume * squelchFactor; + sample = m_bandpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume; } } else @@ -413,7 +421,7 @@ void NFMDemod::applyAudioSampleRate(int sampleRate) m_lowpass.create(301, sampleRate, 250.0); m_bandpass.create(301, sampleRate, 300.0, m_settings.m_afBandwidth); m_squelchGate = (sampleRate / 100) * m_settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate - m_squelchDecay = (sampleRate / 100); // decay is fixed at 10ms + m_squelchDecay = m_squelchGate; m_squelchCount = 0; // reset squelch open counter m_ctcssDetector.setCoefficients(sampleRate/16, sampleRate/8.0f); // 0.5s / 2 Hz resolution @@ -429,6 +437,7 @@ void NFMDemod::applyAudioSampleRate(int sampleRate) m_phaseDiscri.setFMScaling(sampleRate / static_cast(m_settings.m_fmDeviation)); m_audioFifo.setSize(sampleRate); + m_squelchDelayLine.resize(sampleRate/2); m_settingsMutex.unlock(); diff --git a/plugins/channelrx/demodnfm/nfmdemod.h b/plugins/channelrx/demodnfm/nfmdemod.h index 132b1ee25..cec6cb1aa 100644 --- a/plugins/channelrx/demodnfm/nfmdemod.h +++ b/plugins/channelrx/demodnfm/nfmdemod.h @@ -34,6 +34,7 @@ #include "audio/audiofifo.h" #include "util/message.h" #include "util/movingaverage.h" +#include "util/doublebufferfifo.h" #include "nfmdemodsettings.h" @@ -207,6 +208,7 @@ private: MovingAverageUtil m_movingAverage; AFSquelch m_afSquelch; Real m_agcLevel; // AGC will aim to this level + DoubleBufferFIFO m_squelchDelayLine; AudioVector m_audioBuffer; uint m_audioBufferFill; diff --git a/plugins/channelrx/demodnfm/nfmplugin.cpp b/plugins/channelrx/demodnfm/nfmplugin.cpp index 47feaed9f..690aa3b1c 100644 --- a/plugins/channelrx/demodnfm/nfmplugin.cpp +++ b/plugins/channelrx/demodnfm/nfmplugin.cpp @@ -9,7 +9,7 @@ const PluginDescriptor NFMPlugin::m_pluginDescriptor = { QString("NFM Demodulator"), - QString("3.14.2"), + QString("3.14.4"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index ec51b06f3..0a95fe91a 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -170,7 +170,7 @@ set(sdrbase_HEADERS util/CRC64.h util/db.h util/doublebuffer.h - #export.h + util/doublebufferfifo.h util/fixedtraits.h util/message.h util/messagequeue.h diff --git a/sdrbase/util/doublebufferfifo.h b/sdrbase/util/doublebufferfifo.h new file mode 100644 index 000000000..58c8b3929 --- /dev/null +++ b/sdrbase/util/doublebufferfifo.h @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_UTIL_DOUBLEBUFFERFIFO_H_ +#define SDRBASE_UTIL_DOUBLEBUFFERFIFO_H_ + + +template +class DoubleBufferFIFO +{ +public: + DoubleBufferFIFO(int size) : m_size(size), m_writeIndex(0), m_currentIndex(0) + { + m_data = new T[2*m_size]; + } + + ~DoubleBufferFIFO() + { + delete[] m_data; + } + + void resize(int size) + { + delete[] m_data; + m_size = size; + m_data = new T[2*m_size]; + m_writeIndex = 0; + m_currentIndex = 0; + } + + void write(const T& element) + { + m_data[m_writeIndex] = element; + m_data[m_writeIndex+m_size] = element; + m_currentIndex = m_writeIndex; + + if (m_writeIndex < m_size - 1) { + m_writeIndex++; + } else { + m_writeIndex = 0; + } + } + + T& readBack(int delay) + { + if (delay > m_size) { + delay = m_size; + } + + return m_data[m_currentIndex + m_size - delay]; + } + + void zeroBack(int delay) + { + if (delay > m_size) { + delay = m_size; + } + + for (int i = 0; i < delay; i++) { + m_data[m_currentIndex + m_size - i] = 0; + } + } + +private: + int m_size; + T *m_data; + int m_writeIndex; + int m_currentIndex; +}; + +#endif /* SDRBASE_UTIL_DOUBLEBUFFERFIFO_H_ */