1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-10 10:33:29 -05:00

NFM demod: buffered squelch

This commit is contained in:
f4exb 2018-04-21 09:23:01 +02:00
parent 145d0cad38
commit 12f5f4e30c
7 changed files with 116 additions and 21 deletions

View File

@ -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"));

View File

@ -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<int> vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int));

View File

@ -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<float>(m_settings.m_fmDeviation));
m_audioFifo.setSize(sampleRate);
m_squelchDelayLine.resize(sampleRate/2);
m_settingsMutex.unlock();

View File

@ -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<Real, double, 32> m_movingAverage;
AFSquelch m_afSquelch;
Real m_agcLevel; // AGC will aim to this level
DoubleBufferFIFO<Real> m_squelchDelayLine;
AudioVector m_audioBuffer;
uint m_audioBufferFill;

View File

@ -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,

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_UTIL_DOUBLEBUFFERFIFO_H_
#define SDRBASE_UTIL_DOUBLEBUFFERFIFO_H_
template<typename T>
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_ */