1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-22 08:04:49 -05:00

CTCSS detector: fixed crash on destructor. Fixes #680

This commit is contained in:
f4exb 2020-11-01 08:23:50 +01:00
parent eeb243ea7e
commit ef1a7ef8d2
2 changed files with 126 additions and 116 deletions

View File

@ -1,68 +1,72 @@
/* //////////////////////////////////////////////////////////////////////////////////////////////////////////////
* ctcssdetector.cpp // Copyright (C) 2015-2020 Edouard Griffiths, F4EXB //
* // //
* Created on: Jun 16, 2015 // See: http://www.embedded.com/design/connectivity/4025660/Detecting-CTCSS-tones-with-Goertzel-s-algorithm //
* Author: f4exb // //
*/ // This program is free software; you can redistribute it and/or modify //
#include <math.h> // it under the terms of the GNU General Public License as published by //
#include "dsp/ctcssdetector.h" // the Free Software Foundation as version 3 of the License, or //
#include "ctcssfrequencies.h" // (at your option) any later version. //
// //
// 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/>. //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#undef M_PI #define _USE_MATH_DEFINES
#define M_PI 3.14159265358979323846 #include <cmath>
#include "dsp/ctcssdetector.h"
CTCSSDetector::CTCSSDetector() : CTCSSDetector::CTCSSDetector() :
N(0), m_N(0),
sampleRate(0), m_sampleRate(0),
samplesProcessed(0), m_samplesProcessed(0),
maxPowerIndex(0), m_maxPowerIndex(0),
toneDetected(false), m_toneDetected(false),
maxPower(0.0) m_maxPower(0.0)
{ {
nTones = CTCSSFrequencies::m_nbFreqs; m_k = new Real[CTCSSFrequencies::m_nbFreqs];
k = new Real[nTones]; m_coef = new Real[CTCSSFrequencies::m_nbFreqs];
coef = new Real[nTones]; m_u0 = new Real[CTCSSFrequencies::m_nbFreqs];
toneSet = new Real[nTones]; m_u1 = new Real[CTCSSFrequencies::m_nbFreqs];
u0 = new Real[nTones]; m_power = new Real[CTCSSFrequencies::m_nbFreqs];
u1 = new Real[nTones];
power = new Real[nTones];
toneSet = CTCSSFrequencies::m_Freqs;
} }
CTCSSDetector::CTCSSDetector(int _nTones, Real *tones) : CTCSSDetector::CTCSSDetector(int _nTones, Real *tones) :
N(0), m_N(0),
sampleRate(0), m_sampleRate(0),
samplesProcessed(0), m_samplesProcessed(0),
maxPowerIndex(0), m_maxPowerIndex(0),
toneDetected(false), m_toneDetected(false),
maxPower(0.0) m_maxPower(0.0)
{ {
nTones = CTCSSFrequencies::m_nbFreqs; m_k = new Real[CTCSSFrequencies::m_nbFreqs];
k = new Real[nTones]; m_coef = new Real[CTCSSFrequencies::m_nbFreqs];
coef = new Real[nTones]; m_u0 = new Real[CTCSSFrequencies::m_nbFreqs];
toneSet = new Real[nTones]; m_u1 = new Real[CTCSSFrequencies::m_nbFreqs];
u0 = new Real[nTones]; m_power = new Real[CTCSSFrequencies::m_nbFreqs];
u1 = new Real[nTones];
power = new Real[nTones];
toneSet = CTCSSFrequencies::m_Freqs;
} }
CTCSSDetector::~CTCSSDetector() CTCSSDetector::~CTCSSDetector()
{ {
delete[] k; delete[] m_k;
delete[] coef; delete[] m_coef;
delete[] toneSet; delete[] m_u0;
delete[] u0; delete[] m_u1;
delete[] u1; delete[] m_power;
delete[] power;
} }
void CTCSSDetector::setCoefficients(int zN, int _samplerate ) void CTCSSDetector::setCoefficients(int N, int sampleRate)
{ {
N = zN; // save the basic parameters for use during analysis m_N = N; // save the basic parameters for use during analysis
sampleRate = _samplerate; m_sampleRate = sampleRate;
// for each of the frequencies (tones) of interest calculate // for each of the frequencies (tones) of interest calculate
// k and the associated filter coefficient as per the Goertzel // k and the associated filter coefficient as per the Goertzel
@ -71,10 +75,10 @@ void CTCSSDetector::setCoefficients(int zN, int _samplerate )
// for later display. The tone set is specified in the // for later display. The tone set is specified in the
// constructor. Notice that the resulting coefficients are // constructor. Notice that the resulting coefficients are
// independent of N. // independent of N.
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
k[j] = ((double)N * toneSet[j]) / (double)sampleRate; m_k[j] = ((double) m_N * CTCSSFrequencies::m_Freqs[j]) / (double)m_sampleRate;
coef[j] = 2.0 * cos((2.0 * M_PI * toneSet[j])/(double)sampleRate); m_coef[j] = 2.0 * cos((2.0 * M_PI * CTCSSFrequencies::m_Freqs[j])/(double)m_sampleRate);
} }
} }
@ -84,12 +88,12 @@ bool CTCSSDetector::analyze(Real *sample)
{ {
feedback(*sample); // Goertzel feedback feedback(*sample); // Goertzel feedback
samplesProcessed += 1; m_samplesProcessed += 1;
if (samplesProcessed == N) // completed a block of N if (m_samplesProcessed == m_N) // completed a block of N
{ {
feedForward(); // calculate the power at each tone feedForward(); // calculate the m_power at each tone
samplesProcessed = 0; m_samplesProcessed = 0;
return true; // have a result return true; // have a result
} }
else else
@ -104,11 +108,11 @@ void CTCSSDetector::feedback(Real in)
Real t; Real t;
// feedback for each tone // feedback for each tone
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
t = u0[j]; t = m_u0[j];
u0[j] = in + (coef[j] * u0[j]) - u1[j]; m_u0[j] = in + (m_coef[j] * m_u0[j]) - m_u1[j];
u1[j] = t; m_u1[j] = t;
} }
} }
@ -117,10 +121,10 @@ void CTCSSDetector::feedForward()
{ {
initializePower(); initializePower();
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
power[j] = (u0[j] * u0[j]) + (u1[j] * u1[j]) - (coef[j] * u0[j] * u1[j]); m_power[j] = (m_u0[j] * m_u0[j]) + (m_u1[j] * m_u1[j]) - (m_coef[j] * m_u0[j] * m_u1[j]);
u0[j] = u1[j] = 0.0; // reset for next block. m_u0[j] = m_u1[j] = 0.0; // reset for next block.
} }
evaluatePower(); evaluatePower();
@ -129,23 +133,23 @@ void CTCSSDetector::feedForward()
void CTCSSDetector::reset() void CTCSSDetector::reset()
{ {
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
power[j] = u0[j] = u1[j] = 0.0; // reset m_power[j] = m_u0[j] = m_u1[j] = 0.0; // reset
} }
samplesProcessed = 0; m_samplesProcessed = 0;
maxPower = 0.0; m_maxPower = 0.0;
maxPowerIndex = 0; m_maxPowerIndex = 0;
toneDetected = false; m_toneDetected = false;
} }
void CTCSSDetector::initializePower() void CTCSSDetector::initializePower()
{ {
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
power[j] = 0.0; // reset m_power[j] = 0.0; // reset
} }
} }
@ -153,19 +157,19 @@ void CTCSSDetector::initializePower()
void CTCSSDetector::evaluatePower() void CTCSSDetector::evaluatePower()
{ {
Real sumPower = 0.0; Real sumPower = 0.0;
Real aboveAvg = 2.0; // Arbitrary max power above average threshold Real aboveAvg = 2.0; // Arbitrary max m_power above average threshold
maxPower = 0.0; m_maxPower = 0.0;
for (int j = 0; j < nTones; ++j) for (int j = 0; j < CTCSSFrequencies::m_nbFreqs; ++j)
{ {
sumPower += power[j]; sumPower += m_power[j];
if (power[j] > maxPower) if (m_power[j] > m_maxPower)
{ {
maxPower = power[j]; m_maxPower = m_power[j];
maxPowerIndex = j; m_maxPowerIndex = j;
} }
} }
toneDetected = (maxPower > (sumPower/nTones) + aboveAvg); m_toneDetected = (m_maxPower > (sumPower/CTCSSFrequencies::m_nbFreqs) + aboveAvg);
} }

View File

@ -1,16 +1,28 @@
/* //////////////////////////////////////////////////////////////////////////////////////////////////////////////
* ctcssdetector.h // Copyright (C) 2015-2020 Edouard Griffiths, F4EXB //
* // //
* Created on: Jun 16, 2015 // See: http://www.embedded.com/design/connectivity/4025660/Detecting-CTCSS-tones-with-Goertzel-s-algorithm //
* Author: f4exb // //
* See: http://www.embedded.com/design/connectivity/4025660/Detecting-CTCSS-tones-with-Goertzel-s-algorithm // 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 //
// (at your option) any later version. //
// //
// 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 INCLUDE_GPL_DSP_CTCSSDETECTOR_H_ #ifndef INCLUDE_GPL_DSP_CTCSSDETECTOR_H_
#define INCLUDE_GPL_DSP_CTCSSDETECTOR_H_ #define INCLUDE_GPL_DSP_CTCSSDETECTOR_H_
#include "dsp/dsptypes.h" #include "dsp/dsptypes.h"
#include "export.h" #include "export.h"
#include "ctcssfrequencies.h"
/** CTCSSDetector: Continuous Tone Coded Squelch System /** CTCSSDetector: Continuous Tone Coded Squelch System
* tone detector class based on the Modified Goertzel * tone detector class based on the Modified Goertzel
@ -18,49 +30,45 @@
*/ */
class SDRBASE_API CTCSSDetector { class SDRBASE_API CTCSSDetector {
public: public:
// Constructors and Destructor
CTCSSDetector(); CTCSSDetector();
// allows user defined CTCSS tone set CTCSSDetector(int _nTones, Real *tones); //!< allows user defined CTCSS tone set
CTCSSDetector(int _nTones, Real *tones);
virtual ~CTCSSDetector(); virtual ~CTCSSDetector();
// setup the basic parameters and coefficients // setup the basic parameters and coefficients
void setCoefficients( void setCoefficients(
int zN, // the algorithm "block" size int N, // the algorithm "block" size
int SampleRate); // input signal sample rate int sampleRate // input signal sample rate
);
// set the detection threshold // set the detection threshold
void setThreshold(double thold); void setThreshold(double thold);
// analyze a sample set and optionally filter // analyze a sample set and optionally filter the tone frequencies.
// the tone frequencies.
bool analyze(Real *sample); // input signal sample bool analyze(Real *sample); // input signal sample
// get the number of defined tones. // get the number of defined tones.
int getNTones() const { int getNTones() const {
return nTones; return CTCSSFrequencies::m_nbFreqs;
} }
// get the tone set // get the tone set
const Real *getToneSet() const const Real *getToneSet() const {
{ return CTCSSFrequencies::m_Freqs;
return toneSet;
} }
// get the currently detected tone, if any // get the currently detected tone, if any
bool getDetectedTone(int &maxTone) const bool getDetectedTone(int &maxTone) const
{ {
maxTone = maxPowerIndex; maxTone = m_maxPowerIndex;
return toneDetected; return m_toneDetected;
} }
// Get the max power at the detected tone. // Get the max m_power at the detected tone.
Real getMaxPower() const Real getMaxPower() const {
{ return m_maxPower;
return maxPower;
} }
void reset(); // reset the analysis algorithm void reset(); // reset the analysis algorithm
protected: protected:
// Override these to change behavior of the detector // Override these to change behavior of the detector
@ -70,19 +78,17 @@ protected:
void feedForward(); void feedForward();
private: private:
int N; int m_N;
int sampleRate; int m_sampleRate;
int nTones; int m_samplesProcessed;
int samplesProcessed; int m_maxPowerIndex;
int maxPowerIndex; bool m_toneDetected;
bool toneDetected; Real m_maxPower;
Real maxPower; Real *m_k;
Real *k; Real *m_coef;
Real *coef; Real *m_u0;
const float *toneSet; Real *m_u1;
Real *u0; Real *m_power;
Real *u1;
Real *power;
}; };