00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <sys/types.h>
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <string.h>
00045 #include <math.h>
00046 #include <errno.h>
00047 #include <stdio.h>
00048
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 58388 $")
00052
00053 #include "asterisk/frame.h"
00054 #include "asterisk/channel.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/dsp.h"
00057 #include "asterisk/ulaw.h"
00058 #include "asterisk/alaw.h"
00059
00060
00061 #define GSAMP_SIZE_NA 183
00062 #define GSAMP_SIZE_CR 188
00063 #define GSAMP_SIZE_UK 160
00064
00065 #define PROG_MODE_NA 0
00066 #define PROG_MODE_CR 1
00067 #define PROG_MODE_UK 2
00068
00069
00070 #define HZ_350 0
00071 #define HZ_440 1
00072 #define HZ_480 2
00073 #define HZ_620 3
00074 #define HZ_950 4
00075 #define HZ_1400 5
00076 #define HZ_1800 6
00077
00078
00079 #define HZ_425 0
00080
00081
00082 #define HZ_400 0
00083
00084 static struct progalias {
00085 char *name;
00086 int mode;
00087 } aliases[] = {
00088 { "us", PROG_MODE_NA },
00089 { "ca", PROG_MODE_NA },
00090 { "cr", PROG_MODE_CR },
00091 { "br", PROG_MODE_CR },
00092 { "uk", PROG_MODE_UK },
00093 };
00094
00095 static struct progress {
00096 int size;
00097 int freqs[7];
00098 } modes[] = {
00099 { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } },
00100 { GSAMP_SIZE_CR, { 425 } },
00101 { GSAMP_SIZE_UK, { 400 } },
00102 };
00103
00104 #define DEFAULT_THRESHOLD 512
00105
00106 #define BUSY_PERCENT 10
00107 #define BUSY_PAT_PERCENT 7
00108 #define BUSY_THRESHOLD 100
00109 #define BUSY_MIN 75
00110 #define BUSY_MAX 3100
00111
00112
00113 #define DSP_HISTORY 15
00114
00115
00116 #define FAX_DETECT
00117
00118 #define TONE_THRESH 10.0
00119 #define TONE_MIN_THRESH 1e8
00120 #define COUNT_THRESH 3
00121 #define UK_HANGUP_THRESH 60
00122
00123
00124 #define MAX_DTMF_DIGITS 128
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 #define DTMF_THRESHOLD 8.0e7
00139 #define FAX_THRESHOLD 8.0e7
00140 #define FAX_2ND_HARMONIC 2.0
00141 #define DTMF_NORMAL_TWIST 6.3
00142 #ifdef RADIO_RELAX
00143 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5)
00144 #else
00145 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)
00146 #endif
00147 #define DTMF_RELATIVE_PEAK_ROW 6.3
00148 #define DTMF_RELATIVE_PEAK_COL 6.3
00149 #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)
00150 #define DTMF_2ND_HARMONIC_COL 63.1
00151 #define DTMF_TO_TOTAL_ENERGY 42.0
00152
00153 #ifdef OLD_DSP_ROUTINES
00154 #define MF_THRESHOLD 8.0e7
00155 #define MF_NORMAL_TWIST 5.3
00156 #define MF_REVERSE_TWIST 4.0
00157 #define MF_RELATIVE_PEAK 5.3
00158 #define MF_2ND_HARMONIC 1.7
00159 #else
00160 #define BELL_MF_THRESHOLD 1.6e9
00161 #define BELL_MF_TWIST 4.0
00162 #define BELL_MF_RELATIVE_PEAK 12.6
00163 #endif
00164
00165 #if !defined(BUSYDETECT_MARTIN) && !defined(BUSYDETECT) && !defined(BUSYDETECT_TONEONLY) && !defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
00166 #define BUSYDETECT_MARTIN
00167 #endif
00168
00169 typedef struct {
00170 float v2;
00171 float v3;
00172 float fac;
00173 #ifndef OLD_DSP_ROUTINES
00174 int samples;
00175 #endif
00176 } goertzel_state_t;
00177
00178 typedef struct
00179 {
00180 goertzel_state_t row_out[4];
00181 goertzel_state_t col_out[4];
00182 #ifdef FAX_DETECT
00183 goertzel_state_t fax_tone;
00184 #endif
00185 #ifdef OLD_DSP_ROUTINES
00186 goertzel_state_t row_out2nd[4];
00187 goertzel_state_t col_out2nd[4];
00188 #ifdef FAX_DETECT
00189 goertzel_state_t fax_tone2nd;
00190 #endif
00191 int hit1;
00192 int hit2;
00193 int hit3;
00194 int hit4;
00195 #else
00196 int hits[3];
00197 #endif
00198 int mhit;
00199 float energy;
00200 int current_sample;
00201
00202 char digits[MAX_DTMF_DIGITS + 1];
00203
00204 int current_digits;
00205 int detected_digits;
00206 int lost_digits;
00207 int digit_hits[16];
00208 #ifdef FAX_DETECT
00209 int fax_hits;
00210 #endif
00211 } dtmf_detect_state_t;
00212
00213 typedef struct
00214 {
00215 goertzel_state_t tone_out[6];
00216 int mhit;
00217 #ifdef OLD_DSP_ROUTINES
00218 int hit1;
00219 int hit2;
00220 int hit3;
00221 int hit4;
00222 goertzel_state_t tone_out2nd[6];
00223 float energy;
00224 #else
00225 int hits[5];
00226 #endif
00227 int current_sample;
00228
00229 char digits[MAX_DTMF_DIGITS + 1];
00230
00231 int current_digits;
00232 int detected_digits;
00233 int lost_digits;
00234 #ifdef FAX_DETECT
00235 int fax_hits;
00236 #endif
00237 } mf_detect_state_t;
00238
00239 static float dtmf_row[] =
00240 {
00241 697.0, 770.0, 852.0, 941.0
00242 };
00243 static float dtmf_col[] =
00244 {
00245 1209.0, 1336.0, 1477.0, 1633.0
00246 };
00247
00248 static float mf_tones[] =
00249 {
00250 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
00251 };
00252
00253 #ifdef FAX_DETECT
00254 static float fax_freq = 1100.0;
00255 #endif
00256
00257 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
00258
00259 #ifdef OLD_DSP_ROUTINES
00260 static char mf_hit[6][6] = {
00261 { 0, '1', '2', '4', '7', 'C' },
00262 { '1', 0, '3', '5', '8', 'A' },
00263 { '2', '3', 0, '6', '9', '*' },
00264 { '4', '5', '6', 0, '0', 'B' },
00265 { '7', '8', '9', '0', 0, '#' },
00266 { 'C', 'A', '*', 'B', '#', 0 },
00267 };
00268 #else
00269 static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
00270 #endif
00271
00272 static inline void goertzel_sample(goertzel_state_t *s, short sample)
00273 {
00274 float v1;
00275 float fsamp = sample;
00276
00277 v1 = s->v2;
00278 s->v2 = s->v3;
00279 s->v3 = s->fac * s->v2 - v1 + fsamp;
00280 }
00281
00282 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
00283 {
00284 int i;
00285
00286 for (i=0;i<count;i++)
00287 goertzel_sample(s, samps[i]);
00288 }
00289
00290
00291 static inline float goertzel_result(goertzel_state_t *s)
00292 {
00293 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
00294 }
00295
00296 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
00297 {
00298 s->v2 = s->v3 = 0.0;
00299 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
00300 #ifndef OLD_DSP_ROUTINES
00301 s->samples = samples;
00302 #endif
00303 }
00304
00305 static inline void goertzel_reset(goertzel_state_t *s)
00306 {
00307 s->v2 = s->v3 = 0.0;
00308 }
00309
00310 struct ast_dsp {
00311 struct ast_frame f;
00312 int threshold;
00313 int totalsilence;
00314 int totalnoise;
00315 int features;
00316 int busymaybe;
00317 int busycount;
00318 int busy_tonelength;
00319 int busy_quietlength;
00320 int historicnoise[DSP_HISTORY];
00321 int historicsilence[DSP_HISTORY];
00322 goertzel_state_t freqs[7];
00323 int freqcount;
00324 int gsamps;
00325 int gsamp_size;
00326 int progmode;
00327 int tstate;
00328 int tcount;
00329 int digitmode;
00330 int thinkdigit;
00331 float genergy;
00332 union {
00333 dtmf_detect_state_t dtmf;
00334 mf_detect_state_t mf;
00335 } td;
00336 };
00337
00338 static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
00339 {
00340 int i;
00341
00342 #ifdef OLD_DSP_ROUTINES
00343 s->hit1 =
00344 s->mhit =
00345 s->hit3 =
00346 s->hit4 =
00347 s->hit2 = 0;
00348 #else
00349 s->hits[0] = s->hits[1] = s->hits[2] = 0;
00350 #endif
00351 for (i = 0; i < 4; i++) {
00352 goertzel_init (&s->row_out[i], dtmf_row[i], 102);
00353 goertzel_init (&s->col_out[i], dtmf_col[i], 102);
00354 #ifdef OLD_DSP_ROUTINES
00355 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
00356 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
00357 #endif
00358 s->energy = 0.0;
00359 }
00360 #ifdef FAX_DETECT
00361
00362 goertzel_init (&s->fax_tone, fax_freq, 102);
00363
00364 #ifdef OLD_DSP_ROUTINES
00365
00366 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
00367 #endif
00368 #endif
00369 s->current_sample = 0;
00370 s->detected_digits = 0;
00371 s->current_digits = 0;
00372 memset(&s->digits, 0, sizeof(s->digits));
00373 s->lost_digits = 0;
00374 s->digits[0] = '\0';
00375 }
00376
00377 static void ast_mf_detect_init (mf_detect_state_t *s)
00378 {
00379 int i;
00380 #ifdef OLD_DSP_ROUTINES
00381 s->hit1 =
00382 s->hit2 = 0;
00383 #else
00384 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00385 #endif
00386 for (i = 0; i < 6; i++) {
00387 goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00388 #ifdef OLD_DSP_ROUTINES
00389 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
00390 s->energy = 0.0;
00391 #endif
00392 }
00393 s->current_digits = 0;
00394 memset(&s->digits, 0, sizeof(s->digits));
00395 s->current_sample = 0;
00396 s->detected_digits = 0;
00397 s->lost_digits = 0;
00398 s->digits[0] = '\0';
00399 s->mhit = 0;
00400 }
00401
00402 static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples,
00403 int digitmode, int *writeback, int faxdetect)
00404 {
00405 float row_energy[4];
00406 float col_energy[4];
00407 #ifdef FAX_DETECT
00408 float fax_energy;
00409 #ifdef OLD_DSP_ROUTINES
00410 float fax_energy_2nd;
00411 #endif
00412 #endif
00413 float famp;
00414 float v1;
00415 int i;
00416 int j;
00417 int sample;
00418 int best_row;
00419 int best_col;
00420 int hit;
00421 int limit;
00422
00423 hit = 0;
00424 for (sample = 0; sample < samples; sample = limit) {
00425
00426 if ((samples - sample) >= (102 - s->current_sample))
00427 limit = sample + (102 - s->current_sample);
00428 else
00429 limit = samples;
00430 #if defined(USE_3DNOW)
00431 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00432 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00433 #ifdef OLD_DSP_ROUTINES
00434 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00435 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00436 #endif
00437
00438 #warning "Fax Support Broken"
00439 #else
00440
00441
00442 for (j=sample;j<limit;j++) {
00443 famp = amp[j];
00444 s->energy += famp*famp;
00445
00446
00447 v1 = s->row_out[0].v2;
00448 s->row_out[0].v2 = s->row_out[0].v3;
00449 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
00450 v1 = s->col_out[0].v2;
00451 s->col_out[0].v2 = s->col_out[0].v3;
00452 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
00453 v1 = s->row_out[1].v2;
00454 s->row_out[1].v2 = s->row_out[1].v3;
00455 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
00456 v1 = s->col_out[1].v2;
00457 s->col_out[1].v2 = s->col_out[1].v3;
00458 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
00459 v1 = s->row_out[2].v2;
00460 s->row_out[2].v2 = s->row_out[2].v3;
00461 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
00462 v1 = s->col_out[2].v2;
00463 s->col_out[2].v2 = s->col_out[2].v3;
00464 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
00465 v1 = s->row_out[3].v2;
00466 s->row_out[3].v2 = s->row_out[3].v3;
00467 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
00468 v1 = s->col_out[3].v2;
00469 s->col_out[3].v2 = s->col_out[3].v3;
00470 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
00471 #ifdef FAX_DETECT
00472
00473 v1 = s->fax_tone.v2;
00474 s->fax_tone.v2 = s->fax_tone.v3;
00475 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
00476 #endif
00477 #ifdef OLD_DSP_ROUTINES
00478 v1 = s->col_out2nd[0].v2;
00479 s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
00480 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
00481 v1 = s->row_out2nd[0].v2;
00482 s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
00483 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
00484 v1 = s->col_out2nd[1].v2;
00485 s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
00486 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
00487 v1 = s->row_out2nd[1].v2;
00488 s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
00489 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
00490 v1 = s->col_out2nd[2].v2;
00491 s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
00492 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
00493 v1 = s->row_out2nd[2].v2;
00494 s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
00495 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
00496 v1 = s->col_out2nd[3].v2;
00497 s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
00498 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
00499 v1 = s->row_out2nd[3].v2;
00500 s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
00501 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
00502 #ifdef FAX_DETECT
00503
00504 v1 = s->fax_tone.v2;
00505 s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
00506 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
00507 #endif
00508 #endif
00509 }
00510 #endif
00511 s->current_sample += (limit - sample);
00512 if (s->current_sample < 102) {
00513 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00514
00515
00516 for (i=sample;i<limit;i++)
00517 amp[i] = 0;
00518 *writeback = 1;
00519 }
00520 continue;
00521 }
00522 #ifdef FAX_DETECT
00523
00524 fax_energy = goertzel_result(&s->fax_tone);
00525 #endif
00526
00527
00528 row_energy[0] = goertzel_result (&s->row_out[0]);
00529 col_energy[0] = goertzel_result (&s->col_out[0]);
00530
00531 for (best_row = best_col = 0, i = 1; i < 4; i++) {
00532 row_energy[i] = goertzel_result (&s->row_out[i]);
00533 if (row_energy[i] > row_energy[best_row])
00534 best_row = i;
00535 col_energy[i] = goertzel_result (&s->col_out[i]);
00536 if (col_energy[i] > col_energy[best_col])
00537 best_col = i;
00538 }
00539 hit = 0;
00540
00541 if (row_energy[best_row] >= DTMF_THRESHOLD &&
00542 col_energy[best_col] >= DTMF_THRESHOLD &&
00543 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
00544 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
00545
00546 for (i = 0; i < 4; i++) {
00547 if ((i != best_col &&
00548 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00549 (i != best_row
00550 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00551 break;
00552 }
00553 }
00554 #ifdef OLD_DSP_ROUTINES
00555
00556 if (i >= 4 &&
00557 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
00558 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
00559 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
00560 #else
00561
00562 if (i >= 4 &&
00563 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
00564 #endif
00565
00566 hit = dtmf_positions[(best_row << 2) + best_col];
00567 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00568
00569 for (i=sample;i<limit;i++)
00570 amp[i] = 0;
00571 *writeback = 1;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 #ifdef OLD_DSP_ROUTINES
00581 if (hit == s->hit3 && s->hit3 != s->hit2) {
00582 s->mhit = hit;
00583 s->digit_hits[(best_row << 2) + best_col]++;
00584 s->detected_digits++;
00585 if (s->current_digits < MAX_DTMF_DIGITS) {
00586 s->digits[s->current_digits++] = hit;
00587 s->digits[s->current_digits] = '\0';
00588 } else {
00589 s->lost_digits++;
00590 }
00591 }
00592 #else
00593 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0]) {
00594 s->mhit = hit;
00595 s->digit_hits[(best_row << 2) + best_col]++;
00596 s->detected_digits++;
00597 if (s->current_digits < MAX_DTMF_DIGITS) {
00598 s->digits[s->current_digits++] = hit;
00599 s->digits[s->current_digits] = '\0';
00600 } else {
00601 s->lost_digits++;
00602 }
00603 }
00604 #endif
00605 }
00606 }
00607 #ifdef FAX_DETECT
00608 if (!hit && (fax_energy >= FAX_THRESHOLD) &&
00609 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
00610 (faxdetect)) {
00611 #if 0
00612 printf("Fax energy/Second Harmonic: %f\n", fax_energy);
00613 #endif
00614
00615 hit = 'f';
00616 s->fax_hits++;
00617 } else {
00618 if (s->fax_hits > 5) {
00619 hit = 'f';
00620 s->mhit = 'f';
00621 s->detected_digits++;
00622 if (s->current_digits < MAX_DTMF_DIGITS) {
00623 s->digits[s->current_digits++] = hit;
00624 s->digits[s->current_digits] = '\0';
00625 } else {
00626 s->lost_digits++;
00627 }
00628 }
00629 s->fax_hits = 0;
00630 }
00631 #endif
00632 #ifdef OLD_DSP_ROUTINES
00633 s->hit1 = s->hit2;
00634 s->hit2 = s->hit3;
00635 s->hit3 = hit;
00636 #else
00637 s->hits[0] = s->hits[1];
00638 s->hits[1] = s->hits[2];
00639 s->hits[2] = hit;
00640 #endif
00641
00642 for (i = 0; i < 4; i++) {
00643 goertzel_reset(&s->row_out[i]);
00644 goertzel_reset(&s->col_out[i]);
00645 #ifdef OLD_DSP_ROUTINES
00646 goertzel_reset(&s->row_out2nd[i]);
00647 goertzel_reset(&s->col_out2nd[i]);
00648 #endif
00649 }
00650 #ifdef FAX_DETECT
00651 goertzel_reset (&s->fax_tone);
00652 #ifdef OLD_DSP_ROUTINES
00653 goertzel_reset (&s->fax_tone2nd);
00654 #endif
00655 #endif
00656 s->energy = 0.0;
00657 s->current_sample = 0;
00658 }
00659 if ((!s->mhit) || (s->mhit != hit)) {
00660 s->mhit = 0;
00661 return(0);
00662 }
00663 return (hit);
00664 }
00665
00666
00667 #ifdef OLD_DSP_ROUTINES
00668 #define MF_GSIZE 160
00669 #else
00670 #define MF_GSIZE 120
00671 #endif
00672
00673 static int mf_detect (mf_detect_state_t *s, int16_t amp[],
00674 int samples, int digitmode, int *writeback)
00675 {
00676 #ifdef OLD_DSP_ROUTINES
00677 float tone_energy[6];
00678 int best1;
00679 int best2;
00680 float max;
00681 int sofarsogood;
00682 #else
00683 float energy[6];
00684 int best;
00685 int second_best;
00686 #endif
00687 float famp;
00688 float v1;
00689 int i;
00690 int j;
00691 int sample;
00692 int hit;
00693 int limit;
00694
00695 hit = 0;
00696 for (sample = 0; sample < samples; sample = limit) {
00697
00698 if ((samples - sample) >= (MF_GSIZE - s->current_sample))
00699 limit = sample + (MF_GSIZE - s->current_sample);
00700 else
00701 limit = samples;
00702 #if defined(USE_3DNOW)
00703 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00704 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00705 #ifdef OLD_DSP_ROUTINES
00706 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00707 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00708 #endif
00709
00710 #warning "Fax Support Broken"
00711 #else
00712
00713
00714 for (j = sample; j < limit; j++) {
00715 famp = amp[j];
00716 #ifdef OLD_DSP_ROUTINES
00717 s->energy += famp*famp;
00718 #endif
00719
00720
00721 v1 = s->tone_out[0].v2;
00722 s->tone_out[0].v2 = s->tone_out[0].v3;
00723 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
00724 v1 = s->tone_out[1].v2;
00725 s->tone_out[1].v2 = s->tone_out[1].v3;
00726 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
00727 v1 = s->tone_out[2].v2;
00728 s->tone_out[2].v2 = s->tone_out[2].v3;
00729 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
00730 v1 = s->tone_out[3].v2;
00731 s->tone_out[3].v2 = s->tone_out[3].v3;
00732 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
00733 v1 = s->tone_out[4].v2;
00734 s->tone_out[4].v2 = s->tone_out[4].v3;
00735 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
00736 v1 = s->tone_out[5].v2;
00737 s->tone_out[5].v2 = s->tone_out[5].v3;
00738 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
00739 #ifdef OLD_DSP_ROUTINES
00740 v1 = s->tone_out2nd[0].v2;
00741 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
00742 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
00743 v1 = s->tone_out2nd[1].v2;
00744 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
00745 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
00746 v1 = s->tone_out2nd[2].v2;
00747 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
00748 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
00749 v1 = s->tone_out2nd[3].v2;
00750 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
00751 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
00752 v1 = s->tone_out2nd[4].v2;
00753 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
00754 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
00755 v1 = s->tone_out2nd[3].v2;
00756 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
00757 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
00758 #endif
00759 }
00760 #endif
00761 s->current_sample += (limit - sample);
00762 if (s->current_sample < MF_GSIZE) {
00763 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00764
00765
00766 for (i=sample;i<limit;i++)
00767 amp[i] = 0;
00768 *writeback = 1;
00769 }
00770 continue;
00771 }
00772 #ifdef OLD_DSP_ROUTINES
00773
00774
00775 for (i=0;i<6;i++) {
00776 tone_energy[i] = goertzel_result(&s->tone_out[i]);
00777 }
00778
00779 best1 = 0;
00780 max = tone_energy[0];
00781 for (i=1;i<6;i++) {
00782 if (tone_energy[i] > max) {
00783 max = tone_energy[i];
00784 best1 = i;
00785 }
00786 }
00787
00788
00789 if (best1) {
00790 max = tone_energy[0];
00791 best2 = 0;
00792 } else {
00793 max = tone_energy[1];
00794 best2 = 1;
00795 }
00796
00797 for (i=0;i<6;i++) {
00798 if (i == best1) continue;
00799 if (tone_energy[i] > max) {
00800 max = tone_energy[i];
00801 best2 = i;
00802 }
00803 }
00804 hit = 0;
00805 if (best1 != best2)
00806 sofarsogood=1;
00807 else
00808 sofarsogood=0;
00809
00810 for (i=0;i<6;i++) {
00811 if (i == best1)
00812 continue;
00813 if (i == best2)
00814 continue;
00815 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
00816 sofarsogood = 0;
00817 break;
00818 }
00819 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
00820 sofarsogood = 0;
00821 break;
00822 }
00823 }
00824
00825 if (sofarsogood) {
00826
00827 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1])
00828 sofarsogood = 0;
00829 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
00830 sofarsogood = 0;
00831 }
00832 if (sofarsogood) {
00833 hit = mf_hit[best1][best2];
00834 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00835
00836 for (i=sample;i<limit;i++)
00837 amp[i] = 0;
00838 *writeback = 1;
00839 }
00840
00841 if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
00842 s->mhit = hit;
00843 s->detected_digits++;
00844 if (s->current_digits < MAX_DTMF_DIGITS - 2) {
00845 s->digits[s->current_digits++] = hit;
00846 s->digits[s->current_digits] = '\0';
00847 } else {
00848 s->lost_digits++;
00849 }
00850 }
00851 }
00852
00853 s->hit1 = s->hit2;
00854 s->hit2 = s->hit3;
00855 s->hit3 = hit;
00856
00857 for (i = 0; i < 6; i++) {
00858 goertzel_reset(&s->tone_out[i]);
00859 goertzel_reset(&s->tone_out2nd[i]);
00860 }
00861 s->energy = 0.0;
00862 s->current_sample = 0;
00863 }
00864 #else
00865
00866
00867
00868
00869
00870
00871
00872 energy[0] = goertzel_result(&s->tone_out[0]);
00873 energy[1] = goertzel_result(&s->tone_out[1]);
00874 if (energy[0] > energy[1]) {
00875 best = 0;
00876 second_best = 1;
00877 } else {
00878 best = 1;
00879 second_best = 0;
00880 }
00881
00882 for (i=2;i<6;i++) {
00883 energy[i] = goertzel_result(&s->tone_out[i]);
00884 if (energy[i] >= energy[best]) {
00885 second_best = best;
00886 best = i;
00887 } else if (energy[i] >= energy[second_best]) {
00888 second_best = i;
00889 }
00890 }
00891
00892 hit = 0;
00893 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00894 && energy[best] < energy[second_best]*BELL_MF_TWIST
00895 && energy[best]*BELL_MF_TWIST > energy[second_best]) {
00896
00897 hit = -1;
00898 for (i=0;i<6;i++) {
00899 if (i != best && i != second_best) {
00900 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00901
00902 hit = 0;
00903 break;
00904 }
00905 }
00906 }
00907 }
00908 if (hit) {
00909
00910 if (second_best < best) {
00911 i = best;
00912 best = second_best;
00913 second_best = i;
00914 }
00915 best = best*5 + second_best - 1;
00916 hit = bell_mf_positions[best];
00917
00918
00919
00920
00921
00922
00923 if (hit == s->hits[4] && hit == s->hits[3] &&
00924 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
00925 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] &&
00926 hit != s->hits[0]))) {
00927 s->detected_digits++;
00928 if (s->current_digits < MAX_DTMF_DIGITS) {
00929 s->digits[s->current_digits++] = hit;
00930 s->digits[s->current_digits] = '\0';
00931 } else {
00932 s->lost_digits++;
00933 }
00934 }
00935 } else {
00936 hit = 0;
00937 }
00938 s->hits[0] = s->hits[1];
00939 s->hits[1] = s->hits[2];
00940 s->hits[2] = s->hits[3];
00941 s->hits[3] = s->hits[4];
00942 s->hits[4] = hit;
00943
00944 for (i = 0; i < 6; i++)
00945 goertzel_reset(&s->tone_out[i]);
00946 s->current_sample = 0;
00947 }
00948 #endif
00949 if ((!s->mhit) || (s->mhit != hit)) {
00950 s->mhit = 0;
00951 return(0);
00952 }
00953 return (hit);
00954 }
00955