1 //
2 // DTMF Receiver module, part of:
3 // BSD Telephony Of Mexico "Zapata" Telecom Library, version 1.10 12/9/01
4 //
5 // Part of the "Zapata" Computer Telephony Technology.
6 //
7 // See http://www.bsdtelephony.com.mx
8 //
9 // The technologies, software, hardware, designs, drawings, scheumatics, board
10 // layouts and/or artwork, concepts, methodologies (including the use of all
11 // of these, and that which is derived from the use of all of these), all other
12 // intellectual properties contained herein, and all intellectual property
13 // rights have been and shall continue to be expressly for the benefit of all
14 // mankind, and are perpetually placed in the public domain, and may be used,
15 // copied, and/or modified by anyone, in any manner, for any legal purpose,
16 // without restriction.
17 //
18 // tone_detect.c - General telephony tone detection, and specific
19 // detection of DTMF.
20 //
21 // Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
22 //
23 // Despite my general liking of the GPL, I place this code in the
24 // public domain for the benefit of all mankind - even the slimy
25 // ones who might try to proprietize my work and use it to my
26 // detriment.
27 //
28
29 #include <ucommon/ucommon.h>
30 #include <ccaudio2-config.h>
31 #include <math.h>
32 #include <ucommon/export.h>
33 #include <ccaudio2.h>
34
35 #ifdef HAVE_STDINT_H
36 #include <stdint.h>
37 #endif
38
39 #ifndef M_PI
40 #define M_PI 3.14159265358979323846
41 #endif
42
43 /* Basic DTMF specs:
44 *
45 * Minimum tone on = 40ms
46 * Minimum tone off = 50ms
47 * Maximum digit rate = 10 per second
48 * Normal twist <= 8dB accepted
49 * Reverse twist <= 4dB accepted
50 * S/N >= 15dB will detect OK
51 * Attenuation <= 26dB will detect OK
52 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
53 */
54
55 #define SAMPLE_RATE 8000.0
56
57 #define DTMF_THRESHOLD 8.0e7
58 #define FAX_THRESHOLD 8.0e7
59 #define FAX_2ND_HARMONIC 2.0 /* 4dB */
60 #define DTMF_NORMAL_TWIST 8.0 /* 8dB */
61 #define DTMF_REVERSE_TWIST 4.0 /* 4dB normal */
62 #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
63 #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
64 #define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB normal */
65 #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
66
67 namespace ucommon {
68
DTMFDetect()69 DTMFDetect::DTMFDetect()
70 {
71 int i;
72 float theta;
73 static float dtmf_row[] = { 697.0, 770.0, 852.0, 941.0 };
74 static float dtmf_col[] = { 1209.0, 1336.0, 1477.0, 1633.0 };
75 static float fax_freq = 1100.0;
76
77 state = (dtmf_detect_state_t *)malloc(sizeof(dtmf_detect_state_t));
78 memset(state, 0, sizeof(dtmf_detect_state_t));
79
80 for(i = 0; i < 4; i++)
81 {
82 theta = (float)(2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE));
83 dtmf_detect_row[i].fac = (float)(2.0 * cos(theta));
84
85 theta = (float)(2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE));
86 dtmf_detect_col[i].fac = (float)(2.0 * cos(theta));
87
88 theta = (float)(2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE));
89 dtmf_detect_row_2nd[i].fac = (float)(2.0 * cos(theta));
90
91 theta = (float)(2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE));
92 dtmf_detect_col_2nd[i].fac = (float)(2.0 * cos(theta));
93
94 goertzelInit(&state->row_out[i], &dtmf_detect_row[i]);
95 goertzelInit(&state->col_out[i], &dtmf_detect_col[i]);
96 goertzelInit(&state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
97 goertzelInit(&state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
98
99 state->energy = 0.0;
100 }
101
102 // Same for the fax detector
103 theta = (float)(2.0 * M_PI * (fax_freq / SAMPLE_RATE));
104 fax_detect.fac = (float)(2.0 * cos(theta));
105 goertzelInit(&state->fax_tone, &fax_detect);
106
107 // Same for the fax detector 2nd harmonic
108 theta = (float)(2.0 * M_PI * (fax_freq / SAMPLE_RATE));
109 fax_detect_2nd.fac = (float)(2.0 * cos(theta));
110 goertzelInit(&state->fax_tone2nd, &fax_detect_2nd);
111
112 state->current_digits = 0;
113 state->current_sample = 0;
114 state->detected_digits = 0;
115 state->lost_digits = 0;
116 state->digits[0] = '\0';
117 state->mhit = 0;
118 }
119
~DTMFDetect()120 DTMFDetect::~DTMFDetect()
121 {
122 if(state) {
123 free(state);
124 state = NULL;
125 }
126 return;
127 }
128
goertzelInit(goertzel_state_t * s,tone_detection_descriptor_t * t)129 void DTMFDetect::goertzelInit(goertzel_state_t *s, tone_detection_descriptor_t *t)
130 {
131 s->v2 = s->v3 = 0.0;
132 s->fac = t->fac;
133 }
134
goertzelUpdate(goertzel_state_t * s,Sample x[],int samples)135 void DTMFDetect::goertzelUpdate(goertzel_state_t *s,
136 Sample x[],
137 int samples)
138 {
139 int i;
140 float v1;
141
142 for (i = 0; i < samples; i++)
143 {
144 v1 = s->v2;
145 s->v2 = s->v3;
146 s->v3 = s->fac*s->v2 - v1 + x[i];
147 }
148 }
149
goertzelResult(goertzel_state_t * s)150 float DTMFDetect::goertzelResult (goertzel_state_t *s)
151 {
152 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 *s->v3 *s->fac;
153 }
154
putSamples(Linear amp,int samples)155 int DTMFDetect::putSamples(Linear amp, int samples)
156 {
157 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
158 float row_energy[4];
159 float col_energy[4];
160 float fax_energy;
161 float fax_energy_2nd;
162 float famp;
163 float v1;
164 int i;
165 int j;
166 int sample;
167 int best_row;
168 int best_col;
169 int hit;
170 int limit;
171
172 hit = 0;
173 for (sample = 0; sample < samples; sample = limit)
174 {
175 // 102 is optimised to meet the DTMF specs.
176 if ((samples - sample) >= (102 - state->current_sample))
177 limit = sample + (102 - state->current_sample);
178 else
179 limit = samples;
180
181 // The following unrolled loop takes only 35% (rough estimate) of the
182 // time of a rolled loop on the machine on which it was developed
183 for(j = sample; j < limit; j++)
184 {
185 famp = amp[j];
186 state->energy += famp*famp;
187
188 // With GCC 2.95, the following unrolled code seems to take about 35%
189 // (rough estimate) as long as a neat little 0-3 loop
190 v1 = state->row_out[0].v2;
191 state->row_out[0].v2 = state->row_out[0].v3;
192 state->row_out[0].v3 = state->row_out[0].fac*state->row_out[0].v2 - v1 + famp;
193
194 v1 = state->col_out[0].v2;
195 state->col_out[0].v2 = state->col_out[0].v3;
196 state->col_out[0].v3 = state->col_out[0].fac*state->col_out[0].v2 - v1 + famp;
197
198 v1 = state->row_out[1].v2;
199 state->row_out[1].v2 = state->row_out[1].v3;
200 state->row_out[1].v3 = state->row_out[1].fac*state->row_out[1].v2 - v1 + famp;
201
202 v1 = state->col_out[1].v2;
203 state->col_out[1].v2 = state->col_out[1].v3;
204 state->col_out[1].v3 = state->col_out[1].fac*state->col_out[1].v2 - v1 + famp;
205
206 v1 = state->row_out[2].v2;
207 state->row_out[2].v2 = state->row_out[2].v3;
208 state->row_out[2].v3 = state->row_out[2].fac*state->row_out[2].v2 - v1 + famp;
209
210 v1 = state->col_out[2].v2;
211 state->col_out[2].v2 = state->col_out[2].v3;
212 state->col_out[2].v3 = state->col_out[2].fac*state->col_out[2].v2 - v1 + famp;
213
214 v1 = state->row_out[3].v2;
215 state->row_out[3].v2 = state->row_out[3].v3;
216 state->row_out[3].v3 = state->row_out[3].fac*state->row_out[3].v2 - v1 + famp;
217
218 v1 = state->col_out[3].v2;
219 state->col_out[3].v2 = state->col_out[3].v3;
220 state->col_out[3].v3 = state->col_out[3].fac*state->col_out[3].v2 - v1 + famp;
221
222 v1 = state->col_out2nd[0].v2;
223 state->col_out2nd[0].v2 = state->col_out2nd[0].v3;
224 state->col_out2nd[0].v3 = state->col_out2nd[0].fac*state->col_out2nd[0].v2 - v1 + famp;
225
226 v1 = state->row_out2nd[0].v2;
227 state->row_out2nd[0].v2 = state->row_out2nd[0].v3;
228 state->row_out2nd[0].v3 = state->row_out2nd[0].fac*state->row_out2nd[0].v2 - v1 + famp;
229
230 v1 = state->col_out2nd[1].v2;
231 state->col_out2nd[1].v2 = state->col_out2nd[1].v3;
232 state->col_out2nd[1].v3 = state->col_out2nd[1].fac*state->col_out2nd[1].v2 - v1 + famp;
233
234 v1 = state->row_out2nd[1].v2;
235 state->row_out2nd[1].v2 = state->row_out2nd[1].v3;
236 state->row_out2nd[1].v3 = state->row_out2nd[1].fac*state->row_out2nd[1].v2 - v1 + famp;
237
238 v1 = state->col_out2nd[2].v2;
239 state->col_out2nd[2].v2 = state->col_out2nd[2].v3;
240 state->col_out2nd[2].v3 = state->col_out2nd[2].fac*state->col_out2nd[2].v2 - v1 + famp;
241
242 v1 = state->row_out2nd[2].v2;
243 state->row_out2nd[2].v2 = state->row_out2nd[2].v3;
244 state->row_out2nd[2].v3 = state->row_out2nd[2].fac*state->row_out2nd[2].v2 - v1 + famp;
245
246 v1 = state->col_out2nd[3].v2;
247 state->col_out2nd[3].v2 = state->col_out2nd[3].v3;
248 state->col_out2nd[3].v3 = state->col_out2nd[3].fac*state->col_out2nd[3].v2 - v1 + famp;
249
250 v1 = state->row_out2nd[3].v2;
251 state->row_out2nd[3].v2 = state->row_out2nd[3].v3;
252 state->row_out2nd[3].v3 = state->row_out2nd[3].fac*state->row_out2nd[3].v2 - v1 + famp;
253
254 v1 = state->fax_tone.v2;
255 state->fax_tone.v2 = state->fax_tone.v3;
256 state->fax_tone.v3 = state->fax_tone.fac*state->fax_tone.v2 - v1 + famp;
257
258 v1 = state->fax_tone.v2;
259 state->fax_tone2nd.v2 = state->fax_tone2nd.v3;
260 state->fax_tone2nd.v3 = state->fax_tone2nd.fac*state->fax_tone2nd.v2 - v1 + famp;
261 }
262 state->current_sample += (limit - sample);
263 if(state->current_sample < 102)
264 continue;
265
266 fax_energy = goertzelResult(&state->fax_tone);
267
268 // We are at the end of a DTMF detection block
269 // Find the peak row and the peak column
270 row_energy[0] = goertzelResult (&state->row_out[0]);
271 col_energy[0] = goertzelResult (&state->col_out[0]);
272
273 for(best_row = best_col = 0, i = 1; i < 4; i++)
274 {
275 row_energy[i] = goertzelResult (&state->row_out[i]);
276 if(row_energy[i] > row_energy[best_row])
277 best_row = i;
278 col_energy[i] = goertzelResult (&state->col_out[i]);
279 if(col_energy[i] > col_energy[best_col])
280 best_col = i;
281 }
282 hit = 0;
283
284 // Basic signal level test and the twist test
285 if(row_energy[best_row] >= DTMF_THRESHOLD &&
286 col_energy[best_col] >= DTMF_THRESHOLD &&
287 col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST &&
288 col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row])
289 {
290 // Relative peak test
291 for(i = 0; i < 4; i++)
292 {
293 if ((i != best_col &&
294 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
295 (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row]))
296 break;
297 }
298 // ... and second harmonic test
299 if(i >= 4 &&
300 (row_energy[best_row] + col_energy[best_col]) > 42.0*state->energy &&
301 goertzelResult (&state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
302 goertzelResult (&state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row])
303 {
304 hit = dtmf_positions[(best_row << 2) + best_col];
305 // Look for two successive similar results
306 // The logic in the next test is:
307 // We need two successive identical clean detects, with
308 // something different preceeding it. This can work with
309 // back to back differing digits. More importantly, it
310 // can work with nasty phones that give a very wobbly start
311 // to a digit.
312 if (hit == state->hit3 && state->hit3 != state->hit2) {
313 state->mhit = hit;
314 state->digit_hits[(best_row << 2) + best_col]++;
315 state->detected_digits++;
316 if (state->current_digits < 128) {
317 state->digits[state->current_digits++] = hit;
318 state->digits[state->current_digits] = '\0';
319 }
320 else {
321 state->lost_digits++;
322 }
323 }
324 }
325 }
326
327 if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > state->energy * 21.0)) {
328 fax_energy_2nd = goertzelResult(&state->fax_tone2nd);
329 if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) {
330 // XXX Probably need better checking than just this the energy
331 hit = 'f';
332 state->fax_hits++;
333 } /* Don't reset fax hits counter */
334 } else {
335 if (state->fax_hits > 5) {
336 state->mhit = 'f';
337 state->detected_digits++;
338 if (state->current_digits < 128) {
339 state->digits[state->current_digits++] = hit;
340 state->digits[state->current_digits] = '\0';
341 }
342 else
343 state->lost_digits++;
344 }
345 state->fax_hits = 0;
346 }
347 state->hit1 = state->hit2;
348 state->hit2 = state->hit3;
349 state->hit3 = hit;
350 // Reinitialise the detector for the next block
351 for (i = 0; i < 4; i++)
352 {
353 goertzelInit (&state->row_out[i], &dtmf_detect_row[i]);
354 goertzelInit (&state->col_out[i], &dtmf_detect_col[i]);
355 goertzelInit (&state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
356 goertzelInit (&state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
357 }
358 goertzelInit (&state->fax_tone, &fax_detect);
359 goertzelInit (&state->fax_tone2nd, &fax_detect_2nd);
360 state->energy = 0.0;
361 state->current_sample = 0;
362 }
363 if ((!state->mhit) || (state->mhit != hit)) {
364 state->mhit = 0;
365 return(0);
366 }
367 return (hit);
368 }
369
getResult(char * buf,int max)370 int DTMFDetect::getResult(char *buf, int max)
371 {
372 if (max > state->current_digits)
373 max = state->current_digits;
374 if (max > 0) {
375 memcpy (buf, state->digits, max);
376 memmove (state->digits, state->digits + max, state->current_digits - max);
377 state->current_digits -= max;
378 }
379 buf[max] = '\0';
380 return max;
381 }
382
383 } // namespace ucommon
384