19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
32 #define M_PI 3.14159265358979323846
36 using namespace UCOMMON_NAMESPACE;
78 #define SAMPLE_RATE 8000.0
80 #define DTMF_THRESHOLD 8.0e7
81 #define FAX_THRESHOLD 8.0e7
82 #define FAX_2ND_HARMONIC 2.0
83 #define DTMF_NORMAL_TWIST 8.0
84 #define DTMF_REVERSE_TWIST 4.0
85 #define DTMF_RELATIVE_PEAK_ROW 6.3
86 #define DTMF_RELATIVE_PEAK_COL 6.3
87 #define DTMF_2ND_HARMONIC_ROW 2.5
88 #define DTMF_2ND_HARMONIC_COL 63.1
90 DTMFDetect::DTMFDetect()
94 static float dtmf_row[] = { 697.0, 770.0, 852.0, 941.0 };
95 static float dtmf_col[] = { 1209.0, 1336.0, 1477.0, 1633.0 };
96 static float fax_freq = 1100.0;
98 state = (dtmf_detect_state_t *)malloc(
sizeof(dtmf_detect_state_t));
101 for(i = 0; i < 4; i++)
104 dtmf_detect_row[i].fac = (float)(2.0 * cos(theta));
107 dtmf_detect_col[i].fac = (float)(2.0 * cos(theta));
110 dtmf_detect_row_2nd[i].fac = (float)(2.0 * cos(theta));
113 dtmf_detect_col_2nd[i].fac = (float)(2.0 * cos(theta));
115 goertzelInit(&
state->row_out[i], &dtmf_detect_row[i]);
116 goertzelInit(&
state->col_out[i], &dtmf_detect_col[i]);
117 goertzelInit(&
state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
118 goertzelInit(&
state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
125 fax_detect.fac = (float)(2.0 * cos(theta));
126 goertzelInit(&
state->fax_tone, &fax_detect);
130 fax_detect_2nd.fac = (float)(2.0 * cos(theta));
131 goertzelInit(&
state->fax_tone2nd, &fax_detect_2nd);
133 state->current_digits = 0;
134 state->current_sample = 0;
135 state->detected_digits = 0;
136 state->lost_digits = 0;
137 state->digits[0] =
'\0';
141 DTMFDetect::~DTMFDetect()
150 void DTMFDetect::goertzelInit(goertzel_state_t *s, tone_detection_descriptor_t *t)
156 void DTMFDetect::goertzelUpdate(goertzel_state_t *s,
163 for (i = 0; i < samples; i++)
167 s->v3 = s->fac*s->v2 - v1 + x[i];
171 float DTMFDetect::goertzelResult (goertzel_state_t *s)
173 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 *s->v3 *s->fac;
176 int DTMFDetect::putSamples(linear_t amp,
int samples)
178 static char dtmf_positions[] =
"123A" "456B" "789C" "*0#D";
182 float fax_energy_2nd;
194 for (sample = 0; sample < samples; sample = limit)
197 if ((samples - sample) >= (102 -
state->current_sample))
198 limit = sample + (102 -
state->current_sample);
204 for(j = sample; j < limit; j++)
207 state->energy += famp*famp;
211 v1 =
state->row_out[0].v2;
213 state->row_out[0].v3 =
state->row_out[0].fac*
state->row_out[0].v2 - v1 + famp;
215 v1 =
state->col_out[0].v2;
217 state->col_out[0].v3 =
state->col_out[0].fac*
state->col_out[0].v2 - v1 + famp;
219 v1 =
state->row_out[1].v2;
221 state->row_out[1].v3 =
state->row_out[1].fac*
state->row_out[1].v2 - v1 + famp;
223 v1 =
state->col_out[1].v2;
225 state->col_out[1].v3 =
state->col_out[1].fac*
state->col_out[1].v2 - v1 + famp;
227 v1 =
state->row_out[2].v2;
229 state->row_out[2].v3 =
state->row_out[2].fac*
state->row_out[2].v2 - v1 + famp;
231 v1 =
state->col_out[2].v2;
233 state->col_out[2].v3 =
state->col_out[2].fac*
state->col_out[2].v2 - v1 + famp;
235 v1 =
state->row_out[3].v2;
237 state->row_out[3].v3 =
state->row_out[3].fac*
state->row_out[3].v2 - v1 + famp;
239 v1 =
state->col_out[3].v2;
241 state->col_out[3].v3 =
state->col_out[3].fac*
state->col_out[3].v2 - v1 + famp;
243 v1 =
state->col_out2nd[0].v2;
244 state->col_out2nd[0].v2 =
state->col_out2nd[0].v3;
245 state->col_out2nd[0].v3 =
state->col_out2nd[0].fac*
state->col_out2nd[0].v2 - v1 + famp;
247 v1 =
state->row_out2nd[0].v2;
248 state->row_out2nd[0].v2 =
state->row_out2nd[0].v3;
249 state->row_out2nd[0].v3 =
state->row_out2nd[0].fac*
state->row_out2nd[0].v2 - v1 + famp;
251 v1 =
state->col_out2nd[1].v2;
252 state->col_out2nd[1].v2 =
state->col_out2nd[1].v3;
253 state->col_out2nd[1].v3 =
state->col_out2nd[1].fac*
state->col_out2nd[1].v2 - v1 + famp;
255 v1 =
state->row_out2nd[1].v2;
256 state->row_out2nd[1].v2 =
state->row_out2nd[1].v3;
257 state->row_out2nd[1].v3 =
state->row_out2nd[1].fac*
state->row_out2nd[1].v2 - v1 + famp;
259 v1 =
state->col_out2nd[2].v2;
260 state->col_out2nd[2].v2 =
state->col_out2nd[2].v3;
261 state->col_out2nd[2].v3 =
state->col_out2nd[2].fac*
state->col_out2nd[2].v2 - v1 + famp;
263 v1 =
state->row_out2nd[2].v2;
264 state->row_out2nd[2].v2 =
state->row_out2nd[2].v3;
265 state->row_out2nd[2].v3 =
state->row_out2nd[2].fac*
state->row_out2nd[2].v2 - v1 + famp;
267 v1 =
state->col_out2nd[3].v2;
268 state->col_out2nd[3].v2 =
state->col_out2nd[3].v3;
269 state->col_out2nd[3].v3 =
state->col_out2nd[3].fac*
state->col_out2nd[3].v2 - v1 + famp;
271 v1 =
state->row_out2nd[3].v2;
272 state->row_out2nd[3].v2 =
state->row_out2nd[3].v3;
273 state->row_out2nd[3].v3 =
state->row_out2nd[3].fac*
state->row_out2nd[3].v2 - v1 + famp;
275 v1 =
state->fax_tone.v2;
277 state->fax_tone.v3 =
state->fax_tone.fac*
state->fax_tone.v2 - v1 + famp;
279 v1 =
state->fax_tone.v2;
280 state->fax_tone2nd.v2 =
state->fax_tone2nd.v3;
281 state->fax_tone2nd.v3 =
state->fax_tone2nd.fac*
state->fax_tone2nd.v2 - v1 + famp;
283 state->current_sample += (limit - sample);
284 if(
state->current_sample < 102)
287 fax_energy = goertzelResult(&
state->fax_tone);
291 row_energy[0] = goertzelResult (&
state->row_out[0]);
292 col_energy[0] = goertzelResult (&
state->col_out[0]);
294 for(best_row = best_col = 0, i = 1; i < 4; i++)
296 row_energy[i] = goertzelResult (&
state->row_out[i]);
297 if(row_energy[i] > row_energy[best_row])
299 col_energy[i] = goertzelResult (&
state->col_out[i]);
300 if(col_energy[i] > col_energy[best_col])
312 for(i = 0; i < 4; i++)
314 if ((i != best_col &&
321 (row_energy[best_row] + col_energy[best_col]) > 42.0*
state->energy &&
325 hit = dtmf_positions[(best_row << 2) + best_col];
335 state->digit_hits[(best_row << 2) + best_col]++;
336 state->detected_digits++;
337 if (
state->current_digits < 128) {
342 state->lost_digits++;
349 fax_energy_2nd = goertzelResult(&
state->fax_tone2nd);
356 if (
state->fax_hits > 5) {
358 state->detected_digits++;
359 if (
state->current_digits < 128) {
364 state->lost_digits++;
372 for (i = 0; i < 4; i++)
374 goertzelInit (&
state->row_out[i], &dtmf_detect_row[i]);
375 goertzelInit (&
state->col_out[i], &dtmf_detect_col[i]);
376 goertzelInit (&
state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
377 goertzelInit (&
state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
379 goertzelInit (&
state->fax_tone, &fax_detect);
380 goertzelInit (&
state->fax_tone2nd, &fax_detect_2nd);
382 state->current_sample = 0;
391 int DTMFDetect::getResult(
char *buf,
int max)
393 if (max >
state->current_digits)
394 max =
state->current_digits;
396 memcpy (buf,
state->digits, max);
397 memmove (
state->digits,
state->digits + max,
state->current_digits - max);
398 state->current_digits -= max;
#define BAYONNE_NAMESPACE
#define DTMF_REVERSE_TWIST
#define DTMF_RELATIVE_PEAK_ROW
#define DTMF_2ND_HARMONIC_COL
#define DTMF_NORMAL_TWIST
GNU Bayonne library namespace.
#define DTMF_2ND_HARMONIC_ROW
#define DTMF_RELATIVE_PEAK_COL