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