This source file includes following definitions.
- goertzel_init
- TELETONE_API
- TELETONE_API
- TELETONE_API
- TELETONE_API
- TELETONE_API
- TELETONE_API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 #include <libteletone_detect.h>
61
62 #ifndef _MSC_VER
63 #include <stdint.h>
64 #endif
65 #include <string.h>
66 #include <stdio.h>
67 #include <time.h>
68 #include <fcntl.h>
69
70
71 static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
72 static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
73 static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
74 static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
75
76 static float dtmf_row[] = {697.0f, 770.0f, 852.0f, 941.0f};
77 static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f};
78
79 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
80
81 static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
82 goertzel_state->v2 = goertzel_state->v3 = 0.0;
83 goertzel_state->fac = tdesc->fac;
84 }
85
86 TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
87 int16_t sample_buffer[],
88 int samples)
89 {
90 int i;
91 float v1;
92
93 for (i = 0; i < samples; i++) {
94 v1 = goertzel_state->v2;
95 goertzel_state->v2 = goertzel_state->v3;
96 goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]);
97 }
98 }
99 #ifdef _MSC_VER
100 #pragma warning(disable:4244)
101 #endif
102
103 #define teletone_goertzel_result(gs) (double)(((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac))
104
105 TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
106 {
107 int i;
108 float theta;
109
110 dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
111
112 for (i = 0; i < GRID_FACTOR; i++) {
113 theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate));
114 dtmf_detect_row[i].fac = (float)(2.0*cos(theta));
115
116 theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate));
117 dtmf_detect_col[i].fac = (float)(2.0*cos(theta));
118
119 theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate));
120 dtmf_detect_row_2nd[i].fac = (float)(2.0*cos(theta));
121
122 theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate));
123 dtmf_detect_col_2nd[i].fac = (float)(2.0*cos(theta));
124
125 goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
126 goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
127 goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
128 goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
129
130 dtmf_detect_state->energy = 0.0;
131 }
132 dtmf_detect_state->current_sample = 0;
133 dtmf_detect_state->detected_digits = 0;
134 dtmf_detect_state->lost_digits = 0;
135 dtmf_detect_state->digits[0] = '\0';
136 dtmf_detect_state->mhit = 0;
137 }
138
139 TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
140 {
141 float theta = 0;
142 int x = 0;
143
144 if (!mt->sample_rate) {
145 mt->sample_rate = 8000;
146 }
147
148 if (!mt->min_samples) {
149 mt->min_samples = 102;
150 }
151
152 mt->min_samples *= (mt->sample_rate / 8000);
153
154 if (!mt->positive_factor) {
155 mt->positive_factor = 2;
156 }
157
158 if(!mt->negative_factor) {
159 mt->negative_factor = 10;
160 }
161
162 if (!mt->hit_factor) {
163 mt->hit_factor = 2;
164 }
165
166 for(x = 0; x < TELETONE_MAX_TONES; x++) {
167 if ((int) map->freqs[x] == 0) {
168 break;
169 }
170 mt->tone_count++;
171 theta = (float)(M_TWO_PI*(map->freqs[x]/(float)mt->sample_rate));
172 mt->tdd[x].fac = (float)(2.0 * cos(theta));
173 goertzel_init (&mt->gs[x], &mt->tdd[x]);
174 goertzel_init (&mt->gs2[x], &mt->tdd[x]);
175 }
176
177 }
178
179 TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
180 int16_t sample_buffer[],
181 int samples)
182 {
183 int sample, limit = 0, j, x = 0;
184 float v1, famp;
185 float eng_sum = 0, eng_all[TELETONE_MAX_TONES] = {0.0};
186 int gtest = 0, see_hit = 0;
187
188 for (sample = 0; sample >= 0 && sample < samples; sample = limit) {
189 mt->total_samples++;
190
191 if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
192 limit = sample + (mt->min_samples - mt->current_sample);
193 } else {
194 limit = samples;
195 }
196 if (limit < 0 || limit > samples) {
197 limit = samples;
198 }
199
200 for (j = sample; j < limit; j++) {
201 famp = sample_buffer[j];
202
203 mt->energy += famp*famp;
204
205 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
206 v1 = mt->gs[x].v2;
207 mt->gs[x].v2 = mt->gs[x].v3;
208 mt->gs[x].v3 = (float)(mt->gs[x].fac * mt->gs[x].v2 - v1 + famp);
209
210 v1 = mt->gs2[x].v2;
211 mt->gs2[x].v2 = mt->gs2[x].v3;
212 mt->gs2[x].v3 = (float)(mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp);
213 }
214 }
215
216 mt->current_sample += (limit - sample);
217 if (mt->current_sample < mt->min_samples) {
218 continue;
219 }
220
221 eng_sum = 0;
222 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
223 eng_all[x] = (float)(teletone_goertzel_result (&mt->gs[x]));
224 eng_sum += eng_all[x];
225 }
226
227 gtest = 0;
228 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
229 gtest += teletone_goertzel_result (&mt->gs2[x]) < eng_all[x] ? 1 : 0;
230 }
231
232 if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) {
233 if(mt->negatives) {
234 mt->negatives--;
235 }
236 mt->positives++;
237
238 if(mt->positives >= mt->positive_factor) {
239 mt->hits++;
240 }
241 if (mt->hits >= mt->hit_factor) {
242 see_hit++;
243 mt->positives = mt->negatives = mt->hits = 0;
244 }
245 } else {
246 mt->negatives++;
247 if(mt->positives) {
248 mt->positives--;
249 }
250 if(mt->negatives > mt->negative_factor) {
251 mt->positives = mt->hits = 0;
252 }
253 }
254
255
256 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
257 goertzel_init (&mt->gs[x], &mt->tdd[x]);
258 goertzel_init (&mt->gs2[x], &mt->tdd[x]);
259 }
260
261 mt->energy = 0.0;
262 mt->current_sample = 0;
263 }
264
265 return see_hit;
266 }
267
268
269 TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
270 int16_t sample_buffer[],
271 int samples)
272 {
273 float row_energy[GRID_FACTOR];
274 float col_energy[GRID_FACTOR];
275 float famp;
276 float v1;
277 int i;
278 int j;
279 int sample;
280 int best_row;
281 int best_col;
282 char hit;
283 int limit;
284
285 hit = 0;
286 for (sample = 0; sample < samples; sample = limit) {
287
288 if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
289 limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
290 } else {
291 limit = samples;
292 }
293
294 for (j = sample; j < limit; j++) {
295 int x = 0;
296 famp = sample_buffer[j];
297
298 dtmf_detect_state->energy += famp*famp;
299
300 for(x = 0; x < GRID_FACTOR; x++) {
301 v1 = dtmf_detect_state->row_out[x].v2;
302 dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3;
303 dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp);
304
305 v1 = dtmf_detect_state->col_out[x].v2;
306 dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3;
307 dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp);
308
309 v1 = dtmf_detect_state->col_out2nd[x].v2;
310 dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3;
311 dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp);
312
313 v1 = dtmf_detect_state->row_out2nd[x].v2;
314 dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3;
315 dtmf_detect_state->row_out2nd[x].v3 = (float)(dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp);
316 }
317
318 }
319
320 dtmf_detect_state->current_sample += (limit - sample);
321 if (dtmf_detect_state->current_sample < BLOCK_LEN) {
322 continue;
323 }
324
325
326 row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
327 col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
328
329 for (best_row = best_col = 0, i = 1; i < GRID_FACTOR; i++) {
330 row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
331 if (row_energy[i] > row_energy[best_row]) {
332 best_row = i;
333 }
334 col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
335 if (col_energy[i] > col_energy[best_col]) {
336 best_col = i;
337 }
338 }
339 hit = 0;
340
341 if (row_energy[best_row] >= DTMF_THRESHOLD &&
342 col_energy[best_col] >= DTMF_THRESHOLD &&
343 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
344 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
345
346 for (i = 0; i < GRID_FACTOR; i++) {
347 if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
348 (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
349 break;
350 }
351 }
352
353 if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
354 teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
355 teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
356 hit = dtmf_positions[(best_row << 2) + best_col];
357
358
359
360
361
362
363
364 if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
365 dtmf_detect_state->mhit = hit;
366 dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
367 dtmf_detect_state->detected_digits++;
368 if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
369 dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
370 dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
371 }
372 else
373 {
374 dtmf_detect_state->lost_digits++;
375 }
376 }
377 }
378 }
379 dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
380 dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
381 dtmf_detect_state->hit3 = hit;
382
383 for (i = 0; i < GRID_FACTOR; i++) {
384 goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
385 goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
386 goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
387 goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
388 }
389 dtmf_detect_state->energy = 0.0;
390 dtmf_detect_state->current_sample = 0;
391 }
392 if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
393 dtmf_detect_state->mhit = 0;
394 return(0);
395 }
396 return (hit);
397 }
398
399
400 TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
401 char *buf,
402 int max)
403 {
404 teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
405
406 if (max > dtmf_detect_state->current_digits) {
407 max = dtmf_detect_state->current_digits;
408 }
409 if (max > 0) {
410 memcpy (buf, dtmf_detect_state->digits, max);
411 memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
412 dtmf_detect_state->current_digits -= max;
413 }
414 buf[max] = '\0';
415 return max;
416 }
417
418
419
420
421
422
423
424
425
426
427