1 /*
2  * libteletone
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
18  *
19  *
20  * The Initial Developer of the Original Code is
21  * Stephen Underwood <steveu@coppice.org>
22  * Portions created by the Initial Developer are Copyright (C)
23  * the Initial Developer. All Rights Reserved.
24  *
25  * Contributor(s):
26  *
27  * The the original interface designed by Steve Underwood was preserved to retain
28  *the optimizations when considering DTMF tones though the names were changed in the interest
29  * of namespace.
30  *
31  * Much less efficient expansion interface was added to allow for the detection of
32  * a single arbitrary tone combination which may also exceed 2 simultaneous tones.
33  * (controlled by compile time constant TELETONE_MAX_TONES)
34  *
35  * Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
36  *
37  *
38  * libteletone_detect.c Tone Detection Code
39  *
40  *
41  *********************************************************************************
42  *
43  * Derived from tone_detect.c - General telephony tone detection, and specific
44  * detection of DTMF.
45  *
46  * Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
47  *
48  * Despite my general liking of the GPL, I place this code in the
49  * public domain for the benefit of all mankind - even the slimy
50  * ones who might try to proprietize my work and use it to my
51  * detriment.
52  *
53  *
54  * Exception:
55  * The author hereby grants the use of this source code under the
56  * following license if and only if the source code is distributed
57  * as part of the OpenZAP or FreeTDM library.	Any use or distribution of this
58  * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
59  * following license and reinact the MPL 1.1 as stated above.
60  *
61  * Copyright (c) 2007, Anthony Minessale II
62  * All rights reserved.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions
66  * are met:
67  *
68  * * Redistributions of source code must retain the above copyright
69  * notice, this list of conditions and the following disclaimer.
70  *
71  * * Redistributions in binary form must reproduce the above copyright
72  * notice, this list of conditions and the following disclaimer in the
73  * documentation and/or other materials provided with the distribution.
74  *
75  * * Neither the name of the original author; nor the names of any contributors
76  * may be used to endorse or promote products derived from this software
77  * without specific prior written permission.
78  *
79  *
80  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
81  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
82  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
83  * A PARTICULAR PURPOSE ARE DISCLAIMED.	 IN NO EVENT SHALL THE COPYRIGHT OWNER
84  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
85  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
86  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
87  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
88  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
89  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91  */
92 
93 #include <libteletone_detect.h>
94 
95 #ifndef _MSC_VER
96 #include <stdint.h>
97 #endif
98 #include <string.h>
99 #include <stdio.h>
100 #include <time.h>
101 #include <fcntl.h>
102 
103 #define LOW_ENG 10000000
104 #define ZC 2
105 static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
106 static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
107 static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
108 static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
109 
110 static float dtmf_row[] = {697.0f,	770.0f,	 852.0f,  941.0f};
111 static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f};
112 
113 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
114 
goertzel_init(teletone_goertzel_state_t * goertzel_state,teletone_detection_descriptor_t * tdesc)115 static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
116 	goertzel_state->v2 = goertzel_state->v3 = 0.0;
117 	goertzel_state->fac = tdesc->fac;
118 }
119 
teletone_goertzel_update(teletone_goertzel_state_t * goertzel_state,int16_t sample_buffer[],int samples)120 TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
121 							  int16_t sample_buffer[],
122 							  int samples)
123 {
124 	int i;
125 	float v1;
126 
127 	for (i = 0;	 i < samples;  i++) {
128 		v1 = goertzel_state->v2;
129 		goertzel_state->v2 = goertzel_state->v3;
130 		goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]);
131 	}
132 }
133 #ifdef _MSC_VER
134 #pragma warning(disable:4244)
135 #endif
136 
137 #define teletone_goertzel_result(gs) (double)(((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac))
138 
teletone_dtmf_detect_init(teletone_dtmf_detect_state_t * dtmf_detect_state,int sample_rate)139 TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
140 {
141 	int i;
142 	float theta;
143 
144 	if (!sample_rate) {
145 		sample_rate = 8000;
146 	}
147 
148 	dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
149 
150 	for (i = 0;	 i < GRID_FACTOR;  i++) {
151 		theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate));
152 		dtmf_detect_row[i].fac = (float)(2.0*cos(theta));
153 
154 		theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate));
155 		dtmf_detect_col[i].fac = (float)(2.0*cos(theta));
156 
157 		theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate));
158 		dtmf_detect_row_2nd[i].fac = (float)(2.0*cos(theta));
159 
160 		theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate));
161 		dtmf_detect_col_2nd[i].fac = (float)(2.0*cos(theta));
162 
163 		goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
164 		goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
165 		goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
166 		goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
167 
168 		dtmf_detect_state->energy = 0.0;
169 	}
170 	dtmf_detect_state->current_sample = 0;
171 	dtmf_detect_state->detected_digits = 0;
172 	dtmf_detect_state->lost_digits = 0;
173 	dtmf_detect_state->digit = 0;
174 	dtmf_detect_state->dur = 0;
175 }
176 
teletone_multi_tone_init(teletone_multi_tone_t * mt,teletone_tone_map_t * map)177 TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
178 {
179 	float theta = 0;
180 	int x = 0;
181 
182 	if (!mt->sample_rate) {
183 		mt->sample_rate = 8000;
184 	}
185 
186 	if (!mt->min_samples) {
187 		mt->min_samples = 102;
188 	}
189 
190 	mt->min_samples *= (mt->sample_rate / 8000);
191 
192 	if (!mt->positive_factor) {
193 		mt->positive_factor = 2;
194 	}
195 
196 	if(!mt->negative_factor) {
197 		mt->negative_factor = 10;
198 	}
199 
200 	if (!mt->hit_factor) {
201 		mt->hit_factor = 2;
202 	}
203 
204 	for(x = 0; x < TELETONE_MAX_TONES; x++) {
205 		if ((int) map->freqs[x] == 0) {
206 			break;
207 		}
208 		mt->tone_count++;
209 		theta = (float)(M_TWO_PI*(map->freqs[x]/(float)mt->sample_rate));
210 		mt->tdd[x].fac = (float)(2.0 * cos(theta));
211 		goertzel_init (&mt->gs[x], &mt->tdd[x]);
212 		goertzel_init (&mt->gs2[x], &mt->tdd[x]);
213 	}
214 
215 }
216 
teletone_multi_tone_detect(teletone_multi_tone_t * mt,int16_t sample_buffer[],int samples)217 TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
218 								int16_t sample_buffer[],
219 								int samples)
220 {
221 	int sample, limit = 0, j, x = 0;
222 	float v1, famp;
223 	float eng_sum = 0, eng_all[TELETONE_MAX_TONES] = {0.0};
224 	int gtest = 0, see_hit = 0;
225 
226 	for (sample = 0;  sample >= 0 && sample < samples; sample = limit) {
227 		mt->total_samples++;
228 
229 		if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
230 			limit = sample + (mt->min_samples - mt->current_sample);
231 		} else {
232 			limit = samples;
233 		}
234 		if (limit < 0 || limit > samples) {
235 			limit = samples;
236 		}
237 
238 		for (j = sample;  j < limit;  j++) {
239 			famp = sample_buffer[j];
240 
241 			mt->energy += famp*famp;
242 
243 			for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
244 				v1 = mt->gs[x].v2;
245 				mt->gs[x].v2 = mt->gs[x].v3;
246 				mt->gs[x].v3 = (float)(mt->gs[x].fac * mt->gs[x].v2 - v1 + famp);
247 
248 				v1 = mt->gs2[x].v2;
249 				mt->gs2[x].v2 = mt->gs2[x].v3;
250 				mt->gs2[x].v3 = (float)(mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp);
251 			}
252 		}
253 
254 		mt->current_sample += (limit - sample);
255 		if (mt->current_sample < mt->min_samples) {
256 			continue;
257 		}
258 
259 		eng_sum = 0;
260 		for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
261 			eng_all[x] = (float)(teletone_goertzel_result (&mt->gs[x]));
262 			eng_sum += eng_all[x];
263 		}
264 
265 		gtest = 0;
266 		for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
267 			gtest += teletone_goertzel_result (&mt->gs2[x]) < eng_all[x] ? 1 : 0;
268 		}
269 
270 		if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) {
271 			if(mt->negatives) {
272 				mt->negatives--;
273 			}
274 			mt->positives++;
275 
276 			if(mt->positives >= mt->positive_factor) {
277 				mt->hits++;
278 			}
279 			if (mt->hits >= mt->hit_factor) {
280 				see_hit++;
281 				mt->positives = mt->negatives = mt->hits = 0;
282 			}
283 		} else {
284 			mt->negatives++;
285 			if(mt->positives) {
286 				mt->positives--;
287 			}
288 			if(mt->negatives > mt->negative_factor) {
289 				mt->positives = mt->hits = 0;
290 			}
291 		}
292 
293 		/* Reinitialise the detector for the next block */
294 		for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
295 			goertzel_init (&mt->gs[x], &mt->tdd[x]);
296 			goertzel_init (&mt->gs2[x], &mt->tdd[x]);
297 		}
298 
299 		mt->energy = 0.0;
300 		mt->current_sample = 0;
301 	}
302 
303 	return see_hit;
304 }
305 
306 
teletone_dtmf_detect(teletone_dtmf_detect_state_t * dtmf_detect_state,int16_t sample_buffer[],int samples)307 TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
308 						  int16_t sample_buffer[],
309 						  int samples)
310 {
311 	float row_energy[GRID_FACTOR];
312 	float col_energy[GRID_FACTOR];
313 	float famp;
314 	float v1;
315 	int i;
316 	int j;
317 	int sample;
318 	int best_row;
319 	int best_col;
320 	char hit = 0;
321 	int limit;
322 	teletone_hit_type_t r = 0;
323 
324 	for (sample = 0;  sample < samples;	 sample = limit) {
325 		/* BLOCK_LEN is optimised to meet the DTMF specs. */
326 		if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
327 			limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
328 		} else {
329 			limit = samples;
330 		}
331 
332 		for (j = sample;  j < limit;  j++) {
333 			int x = 0;
334 			famp = sample_buffer[j];
335 
336 			dtmf_detect_state->energy += famp*famp;
337 
338 			for(x = 0; x < GRID_FACTOR; x++) {
339 				v1 = dtmf_detect_state->row_out[x].v2;
340 				dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3;
341 				dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp);
342 
343 				v1 = dtmf_detect_state->col_out[x].v2;
344 				dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3;
345 				dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp);
346 
347 				v1 = dtmf_detect_state->col_out2nd[x].v2;
348 				dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3;
349 				dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp);
350 
351 				v1 = dtmf_detect_state->row_out2nd[x].v2;
352 				dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3;
353 				dtmf_detect_state->row_out2nd[x].v3 = (float)(dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp);
354 			}
355 
356 		}
357 
358 		if (dtmf_detect_state->zc > 0) {
359 			if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
360 				if (!--dtmf_detect_state->zc) {
361 					/* Reinitialise the detector for the next block */
362 					dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
363 					for (i = 0;	 i < GRID_FACTOR;  i++) {
364 						goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
365 						goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
366 						goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
367 						goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
368 					}
369 					dtmf_detect_state->dur -= samples;
370 					return TT_HIT_END;
371 				}
372 			}
373 
374 			dtmf_detect_state->dur += samples;
375 			dtmf_detect_state->lenergy = dtmf_detect_state->energy;
376 			dtmf_detect_state->energy = 0.0;
377 			dtmf_detect_state->current_sample = 0;
378 			return TT_HIT_MIDDLE;
379 		} else if (dtmf_detect_state->digit) {
380 			return TT_HIT_END;
381 		}
382 
383 
384 		dtmf_detect_state->current_sample += (limit - sample);
385 		if (dtmf_detect_state->current_sample < BLOCK_LEN) {
386 			continue;
387 		}
388 		/* We are at the end of a DTMF detection block */
389 		/* Find the peak row and the peak column */
390 		row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
391 		col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
392 
393 		for (best_row = best_col = 0, i = 1;  i < GRID_FACTOR;	i++) {
394 			row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
395 			if (row_energy[i] > row_energy[best_row]) {
396 				best_row = i;
397 			}
398 			col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
399 			if (col_energy[i] > col_energy[best_col]) {
400 				best_col = i;
401 			}
402 		}
403 		hit = 0;
404 		/* Basic signal level test and the twist test */
405 		if (row_energy[best_row] >= DTMF_THRESHOLD &&
406 			col_energy[best_col] >= DTMF_THRESHOLD &&
407 			col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
408 			col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
409 			/* Relative peak test */
410 			for (i = 0;	 i < GRID_FACTOR;  i++) {
411 				if ((i != best_col	&&	col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
412 					(i != best_row	&&	row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
413 					break;
414 				}
415 			}
416 			/* ... and second harmonic test */
417 			if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
418 				teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
419 				teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
420 				hit = dtmf_positions[(best_row << 2) + best_col];
421 				/* Look for two successive similar results */
422 				/* The logic in the next test is:
423 				   We need two successive identical clean detects, with
424 				   something different preceeding it. This can work with
425 				   back to back differing digits. More importantly, it
426 				   can work with nasty phones that give a very wobbly start
427 				   to a digit. */
428 				if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
429 					dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
430 					dtmf_detect_state->detected_digits++;
431 					if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
432 						dtmf_detect_state->digit = hit;
433 					} else {
434 						dtmf_detect_state->lost_digits++;
435 					}
436 
437 					if (!dtmf_detect_state->zc) {
438 						dtmf_detect_state->zc = ZC;
439 						dtmf_detect_state->dur = 0;
440 						r = TT_HIT_BEGIN;
441 						break;
442 					}
443 
444 				}
445 			}
446 		}
447 
448 		dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
449 		dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
450 		dtmf_detect_state->hit3 = hit;
451 
452 		dtmf_detect_state->energy = 0.0;
453 		dtmf_detect_state->current_sample = 0;
454 
455 	}
456 
457 	return r;
458 }
459 
460 
teletone_dtmf_get(teletone_dtmf_detect_state_t * dtmf_detect_state,char * buf,unsigned int * dur)461 TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
462 {
463 	if (!dtmf_detect_state->digit) {
464 		return 0;
465 	}
466 
467 	*buf = dtmf_detect_state->digit;
468 
469 	*dur = dtmf_detect_state->dur;
470 
471 	if (!dtmf_detect_state->zc) {
472 		dtmf_detect_state->dur = 0;
473 		dtmf_detect_state->digit = 0;
474 	}
475 
476 	return 1;
477 }
478 
479 /* For Emacs:
480  * Local Variables:
481  * mode:c
482  * indent-tabs-mode:t
483  * tab-width:4
484  * c-basic-offset:4
485  * End:
486  * For VIM:
487  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
488  */
489