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