SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
ctcssdetector.cpp
Go to the documentation of this file.
1 /*
2  * ctcssdetector.cpp
3  *
4  * Created on: Jun 16, 2015
5  * Author: f4exb
6  */
7 #include <math.h>
8 #include "dsp/ctcssdetector.h"
9 
10 #undef M_PI
11 #define M_PI 3.14159265358979323846
12 
14  N(0),
15  sampleRate(0),
16  samplesProcessed(0),
17  maxPowerIndex(0),
18  toneDetected(false),
19  maxPower(0.0)
20 {
21  nTones = 32;
22  k = new Real[nTones];
23  coef = new Real[nTones];
24  toneSet = new Real[nTones];
25  u0 = new Real[nTones];
26  u1 = new Real[nTones];
27  power = new Real[nTones];
28 
29  // The 32 EIA standard tones
30  toneSet[0] = 67.0;
31  toneSet[1] = 71.9;
32  toneSet[2] = 74.4;
33  toneSet[3] = 77.0;
34  toneSet[4] = 79.7;
35  toneSet[5] = 82.5;
36  toneSet[6] = 85.4;
37  toneSet[7] = 88.5;
38  toneSet[8] = 91.5;
39  toneSet[9] = 94.8;
40  toneSet[10] = 97.4;
41  toneSet[11] = 100.0;
42  toneSet[12] = 103.5;
43  toneSet[13] = 107.2;
44  toneSet[14] = 110.9;
45  toneSet[15] = 114.8;
46  toneSet[16] = 118.8;
47  toneSet[17] = 123.0;
48  toneSet[18] = 127.3;
49  toneSet[19] = 131.8;
50  toneSet[20] = 136.5;
51  toneSet[21] = 141.3;
52  toneSet[22] = 146.2;
53  toneSet[23] = 151.4;
54  toneSet[24] = 156.7;
55  toneSet[25] = 162.2;
56  toneSet[26] = 167.9;
57  toneSet[27] = 173.8;
58  toneSet[28] = 179.9;
59  toneSet[29] = 186.2;
60  toneSet[30] = 192.8;
61  toneSet[31] = 203.5;
62 }
63 
64 CTCSSDetector::CTCSSDetector(int _nTones, Real *tones) :
65  N(0),
66  sampleRate(0),
68  maxPowerIndex(0),
69  toneDetected(false),
70  maxPower(0.0)
71 {
72  nTones = _nTones;
73  k = new Real[nTones];
74  coef = new Real[nTones];
75  toneSet = new Real[nTones];
76  u0 = new Real[nTones];
77  u1 = new Real[nTones];
78  power = new Real[nTones];
79 
80  for (int j = 0; j < nTones; ++j)
81  {
82  toneSet[j] = tones[j];
83  }
84 }
85 
86 
88 {
89  delete[] k;
90  delete[] coef;
91  delete[] toneSet;
92  delete[] u0;
93  delete[] u1;
94  delete[] power;
95 }
96 
97 
98 void CTCSSDetector::setCoefficients(int zN, int _samplerate )
99 {
100  N = zN; // save the basic parameters for use during analysis
101  sampleRate = _samplerate;
102 
103  // for each of the frequencies (tones) of interest calculate
104  // k and the associated filter coefficient as per the Goertzel
105  // algorithm. Note: we are using a real value (as apposed to
106  // an integer as described in some references. k is retained
107  // for later display. The tone set is specified in the
108  // constructor. Notice that the resulting coefficients are
109  // independent of N.
110  for (int j = 0; j < nTones; ++j)
111  {
112  k[j] = ((double)N * toneSet[j]) / (double)sampleRate;
113  coef[j] = 2.0 * cos((2.0 * M_PI * toneSet[j])/(double)sampleRate);
114  }
115 }
116 
117 
118 // Analyze an input signal for the presence of CTCSS tones.
120 {
121 
122  feedback(*sample); // Goertzel feedback
123  samplesProcessed += 1;
124 
125  if (samplesProcessed == N) // completed a block of N
126  {
127  feedForward(); // calculate the power at each tone
128  samplesProcessed = 0;
129  return true; // have a result
130  }
131  else
132  {
133  return false;
134  }
135 }
136 
137 
139 {
140  Real t;
141 
142  // feedback for each tone
143  for (int j = 0; j < nTones; ++j)
144  {
145  t = u0[j];
146  u0[j] = in + (coef[j] * u0[j]) - u1[j];
147  u1[j] = t;
148  }
149 }
150 
151 
153 {
154  initializePower();
155 
156  for (int j = 0; j < nTones; ++j)
157  {
158  power[j] = (u0[j] * u0[j]) + (u1[j] * u1[j]) - (coef[j] * u0[j] * u1[j]);
159  u0[j] = u1[j] = 0.0; // reset for next block.
160  }
161 
162  evaluatePower();
163 }
164 
165 
167 {
168  for (int j = 0; j < nTones; ++j)
169  {
170  power[j] = u0[j] = u1[j] = 0.0; // reset
171  }
172 
173  samplesProcessed = 0;
174  maxPower = 0.0;
175  maxPowerIndex = 0;
176  toneDetected = false;
177 }
178 
179 
181 {
182  for (int j = 0; j < nTones; ++j)
183  {
184  power[j] = 0.0; // reset
185  }
186 }
187 
188 
190 {
191  Real sumPower = 0.0;
192  Real aboveAvg = 2.0; // Arbitrary max power above average threshold
193  maxPower = 0.0;
194 
195  for (int j = 0; j < nTones; ++j)
196  {
197  sumPower += power[j];
198 
199  if (power[j] > maxPower)
200  {
201  maxPower = power[j];
202  maxPowerIndex = j;
203  }
204  }
205 
206  toneDetected = (maxPower > (sumPower/nTones) + aboveAvg);
207 }
void setCoefficients(int zN, int SampleRate)
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
virtual ~CTCSSDetector()
virtual void initializePower()
virtual void evaluatePower()
float Real
Definition: dsptypes.h:42
#define M_PI
void feedback(Real sample)
bool analyze(Real *sample)