103 #define LOW_ENG 10000000
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};
116 goertzel_state->
v2 = goertzel_state->
v3 = 0.0;
117 goertzel_state->
fac = tdesc->
fac;
121 int16_t sample_buffer[],
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]);
134 #pragma warning(disable:4244)
137 #define teletone_goertzel_result(gs) (double)(((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac))
148 dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
152 dtmf_detect_row[i].
fac = (float)(2.0*cos(theta));
155 dtmf_detect_col[i].
fac = (float)(2.0*cos(theta));
158 dtmf_detect_row_2nd[i].
fac = (float)(2.0*cos(theta));
161 dtmf_detect_col_2nd[i].
fac = (float)(2.0*cos(theta));
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]);
168 dtmf_detect_state->energy = 0.0;
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;
182 if (!mt->sample_rate) {
183 mt->sample_rate = 8000;
186 if (!mt->min_samples) {
187 mt->min_samples = 102;
190 mt->min_samples *= (mt->sample_rate / 8000);
192 if (!mt->positive_factor) {
193 mt->positive_factor = 2;
196 if(!mt->negative_factor) {
197 mt->negative_factor = 10;
200 if (!mt->hit_factor) {
205 if ((
int) map->freqs[x] == 0) {
209 theta = (float)(
M_TWO_PI*(map->freqs[x]/(
float)mt->sample_rate));
210 mt->tdd[x].fac = (float)(2.0 * cos(theta));
218 int16_t sample_buffer[],
221 int sample, limit = 0, j, x = 0;
224 int gtest = 0, see_hit = 0;
226 for (sample = 0; sample >= 0 && sample < samples; sample = limit) {
229 if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
230 limit = sample + (mt->min_samples - mt->current_sample);
234 if (limit < 0 || limit > samples) {
238 for (j = sample; j < limit; j++) {
239 famp = sample_buffer[j];
241 mt->energy += famp*famp;
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);
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);
254 mt->current_sample += (limit - sample);
255 if (mt->current_sample < mt->min_samples) {
262 eng_sum += eng_all[x];
270 if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) {
276 if(mt->positives >= mt->positive_factor) {
279 if (mt->hits >= mt->hit_factor) {
281 mt->positives = mt->negatives = mt->hits = 0;
288 if(mt->negatives > mt->negative_factor) {
289 mt->positives = mt->hits = 0;
300 mt->current_sample = 0;
308 int16_t sample_buffer[],
325 for (sample = 0; sample < samples; sample = limit) {
327 if ((samples - sample) >= (
BLOCK_LEN - dtmf_detect_state->current_sample)) {
328 limit = sample + (
BLOCK_LEN - dtmf_detect_state->current_sample);
333 for (j = sample; j < limit; j++) {
335 famp = sample_buffer[j];
337 dtmf_detect_state->energy += famp*famp;
340 v1 = dtmf_detect_state->row_out[x].v2;
341 dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3;
342 dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp);
344 v1 = dtmf_detect_state->col_out[x].v2;
345 dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3;
346 dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp);
348 v1 = dtmf_detect_state->col_out2nd[x].v2;
349 dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3;
350 dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp);
352 v1 = dtmf_detect_state->row_out2nd[x].v2;
353 dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3;
354 dtmf_detect_state->row_out2nd[x].v3 = (float)(dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp);
359 if (dtmf_detect_state->zc > 0) {
360 if (dtmf_detect_state->energy <
LOW_ENG && dtmf_detect_state->lenergy <
LOW_ENG) {
361 if (!--dtmf_detect_state->zc) {
363 dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
365 goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
366 goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
367 goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
368 goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
370 dtmf_detect_state->dur -= samples;
375 dtmf_detect_state->dur += samples;
376 dtmf_detect_state->lenergy = dtmf_detect_state->energy;
377 dtmf_detect_state->energy = 0.0;
378 dtmf_detect_state->current_sample = 0;
380 }
else if (dtmf_detect_state->digit) {
385 dtmf_detect_state->current_sample += (limit - sample);
386 if (dtmf_detect_state->current_sample <
BLOCK_LEN) {
394 for (best_row = best_col = 0, i = 1; i <
GRID_FACTOR; i++) {
396 if (row_energy[i] > row_energy[best_row]) {
400 if (col_energy[i] > col_energy[best_col]) {
418 if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
429 if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
430 dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
431 dtmf_detect_state->detected_digits++;
433 dtmf_detect_state->digit = hit;
435 dtmf_detect_state->lost_digits++;
438 if (!dtmf_detect_state->zc) {
439 dtmf_detect_state->zc =
ZC;
440 dtmf_detect_state->dur = 0;
449 dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
450 dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
451 dtmf_detect_state->hit3 = hit;
453 dtmf_detect_state->energy = 0.0;
454 dtmf_detect_state->current_sample = 0;
464 if (!dtmf_detect_state->digit) {
468 *buf = dtmf_detect_state->digit;
470 *dur = dtmf_detect_state->dur;
472 if (!dtmf_detect_state->zc) {
473 dtmf_detect_state->dur = 0;
474 dtmf_detect_state->digit = 0;
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]
#define TELETONE_MAX_TONES
A container for a single multi-tone detection TELETONE_MAX_TONES dictates the maximum simultaneous to...
An abstraction to store a tone mapping.
A container for a DTMF detection state.
A continer for the elements of a Goertzel Algorithm (The names are from his formula) ...
#define TELETONE_API(type)
#define DTMF_RELATIVE_PEAK_COL
void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
Initilize a multi-frequency tone detector.
#define TELETONE_MAX_DTMF_DIGITS
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]
switch_byte_t switch_byte_t * buf
teletone_hit_type_t teletone_dtmf_detect(teletone_dtmf_detect_state_t *dtmf_detect_state, int16_t sample_buffer[], int samples)
Check a sample buffer for the presence of DTMF digits.
static char dtmf_positions[]
int teletone_dtmf_get(teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
retrieve any collected digits into a string buffer
#define DTMF_RELATIVE_PEAK_ROW
#define DTMF_NORMAL_TWIST
int teletone_multi_tone_detect(teletone_multi_tone_t *mt, int16_t sample_buffer[], int samples)
Check a sample buffer for the presence of the mulit-frequency tone described by mt.
An abstraction to store the coefficient of a tone frequency.
#define teletone_goertzel_result(gs)
static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR]
static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc)
#define DTMF_2ND_HARMONIC_COL
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]
#define DTMF_2ND_HARMONIC_ROW
#define DTMF_REVERSE_TWIST
void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, int16_t sample_buffer[], int samples)
Step through the Goertzel Algorithm for each sample in a buffer.
void teletone_dtmf_detect_init(teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
Initilize a DTMF detection state object.