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