![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
dsp.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * Goertzel routines are borrowed from Steve Underwood's tremendous work on the 00009 * DTMF detector. 00010 * 00011 * See http://www.asterisk.org for more information about 00012 * the Asterisk project. Please do not directly contact 00013 * any of the maintainers of this project for assistance; 00014 * the project provides a web site, mailing lists and IRC 00015 * channels for your use. 00016 * 00017 * This program is free software, distributed under the terms of 00018 * the GNU General Public License Version 2. See the LICENSE file 00019 * at the top of the source tree. 00020 */ 00021 00022 /*! \file 00023 * 00024 * \brief Convenience Signal Processing routines 00025 * 00026 * \author Mark Spencer <markster@digium.com> 00027 * \author Steve Underwood <steveu@coppice.org> 00028 */ 00029 00030 /* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */ 00031 /* 00032 tone_detect.c - General telephony tone detection, and specific 00033 detection of DTMF. 00034 00035 Copyright (C) 2001 Steve Underwood <steveu@coppice.org> 00036 00037 Despite my general liking of the GPL, I place this code in the 00038 public domain for the benefit of all mankind - even the slimy 00039 ones who might try to proprietize my work and use it to my 00040 detriment. 00041 */ 00042 00043 #include "asterisk.h" 00044 00045 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51499 $") 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 #include "asterisk/options.h" 00063 00064 /*! Number of goertzels for progress detect */ 00065 enum gsamp_size { 00066 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ 00067 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */ 00068 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */ 00069 }; 00070 00071 enum prog_mode { 00072 PROG_MODE_NA = 0, 00073 PROG_MODE_CR, 00074 PROG_MODE_UK 00075 }; 00076 00077 enum freq_index { 00078 /*! For US modes { */ 00079 HZ_350 = 0, 00080 HZ_440, 00081 HZ_480, 00082 HZ_620, 00083 HZ_950, 00084 HZ_1400, 00085 HZ_1800, /*!< } */ 00086 00087 /*! For CR/BR modes */ 00088 HZ_425 = 0, 00089 00090 /*! For UK mode */ 00091 HZ_400 = 0 00092 }; 00093 00094 static struct progalias { 00095 char *name; 00096 enum prog_mode mode; 00097 } aliases[] = { 00098 { "us", PROG_MODE_NA }, 00099 { "ca", PROG_MODE_NA }, 00100 { "cr", PROG_MODE_CR }, 00101 { "br", PROG_MODE_CR }, 00102 { "uk", PROG_MODE_UK }, 00103 }; 00104 00105 static struct progress { 00106 enum gsamp_size size; 00107 int freqs[7]; 00108 } modes[] = { 00109 { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */ 00110 { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */ 00111 { GSAMP_SIZE_UK, { 400 } }, /*!< UK */ 00112 }; 00113 00114 #define DEFAULT_THRESHOLD 512 00115 00116 enum busy_detect { 00117 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */ 00118 BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */ 00119 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */ 00120 BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */ 00121 BUSY_MAX =3100 /*!< Busy can't be longer than 3100 ms in half-cadence */ 00122 }; 00123 00124 /*! Remember last 15 units */ 00125 #define DSP_HISTORY 15 00126 00127 /*! Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */ 00128 #define FAX_DETECT 00129 00130 #define TONE_THRESH 10.0 /*!< How much louder the tone should be than channel energy */ 00131 #define TONE_MIN_THRESH 1e8 /*!< How much tone there should be at least to attempt */ 00132 00133 /*! All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms) */ 00134 enum gsamp_thresh { 00135 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */ 00136 THRESH_TALK = 2, /*!< Talk detection does not work continuously */ 00137 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */ 00138 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */ 00139 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */ 00140 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */ 00141 }; 00142 00143 #define MAX_DTMF_DIGITS 128 00144 00145 /* Basic DTMF specs: 00146 * 00147 * Minimum tone on = 40ms 00148 * Minimum tone off = 50ms 00149 * Maximum digit rate = 10 per second 00150 * Normal twist <= 8dB accepted 00151 * Reverse twist <= 4dB accepted 00152 * S/N >= 15dB will detect OK 00153 * Attenuation <= 26dB will detect OK 00154 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject 00155 */ 00156 00157 #define DTMF_THRESHOLD 8.0e7 00158 #define FAX_THRESHOLD 8.0e7 00159 #define FAX_2ND_HARMONIC 2.0 /* 4dB */ 00160 #define DTMF_NORMAL_TWIST 6.3 /* 8dB */ 00161 #ifdef RADIO_RELAX 00162 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5) /* 4dB normal */ 00163 #else 00164 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */ 00165 #endif 00166 #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ 00167 #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ 00168 #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */ 00169 #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ 00170 #define DTMF_TO_TOTAL_ENERGY 42.0 00171 00172 #ifdef OLD_DSP_ROUTINES 00173 #define MF_THRESHOLD 8.0e7 00174 #define MF_NORMAL_TWIST 5.3 /* 8dB */ 00175 #define MF_REVERSE_TWIST 4.0 /* was 2.5 */ 00176 #define MF_RELATIVE_PEAK 5.3 /* 8dB */ 00177 #define MF_2ND_HARMONIC 1.7 /* was 2.5 */ 00178 #else 00179 #define BELL_MF_THRESHOLD 1.6e9 00180 #define BELL_MF_TWIST 4.0 /* 6dB */ 00181 #define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */ 00182 #endif 00183 00184 #if !defined(BUSYDETECT_MARTIN) && !defined(BUSYDETECT) && !defined(BUSYDETECT_TONEONLY) && !defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 00185 #define BUSYDETECT_MARTIN 00186 #endif 00187 00188 typedef struct { 00189 float v2; 00190 float v3; 00191 float fac; 00192 #ifndef OLD_DSP_ROUTINES 00193 int samples; 00194 #endif 00195 } goertzel_state_t; 00196 00197 typedef struct 00198 { 00199 goertzel_state_t row_out[4]; 00200 goertzel_state_t col_out[4]; 00201 #ifdef FAX_DETECT 00202 goertzel_state_t fax_tone; 00203 #endif 00204 #ifdef OLD_DSP_ROUTINES 00205 goertzel_state_t row_out2nd[4]; 00206 goertzel_state_t col_out2nd[4]; 00207 #ifdef FAX_DETECT 00208 goertzel_state_t fax_tone2nd; 00209 #endif 00210 int hit1; 00211 int hit2; 00212 int hit3; 00213 int hit4; 00214 #else 00215 int hits[3]; 00216 #endif 00217 int mhit; 00218 float energy; 00219 int current_sample; 00220 00221 char digits[MAX_DTMF_DIGITS + 1]; 00222 00223 int current_digits; 00224 int detected_digits; 00225 int lost_digits; 00226 int digit_hits[16]; 00227 #ifdef FAX_DETECT 00228 int fax_hits; 00229 #endif 00230 } dtmf_detect_state_t; 00231 00232 typedef struct 00233 { 00234 goertzel_state_t tone_out[6]; 00235 int mhit; 00236 #ifdef OLD_DSP_ROUTINES 00237 int hit1; 00238 int hit2; 00239 int hit3; 00240 int hit4; 00241 goertzel_state_t tone_out2nd[6]; 00242 float energy; 00243 #else 00244 int hits[5]; 00245 #endif 00246 int current_sample; 00247 00248 char digits[MAX_DTMF_DIGITS + 1]; 00249 00250 int current_digits; 00251 int detected_digits; 00252 int lost_digits; 00253 #ifdef FAX_DETECT 00254 int fax_hits; 00255 #endif 00256 } mf_detect_state_t; 00257 00258 static float dtmf_row[] = 00259 { 00260 697.0, 770.0, 852.0, 941.0 00261 }; 00262 static float dtmf_col[] = 00263 { 00264 1209.0, 1336.0, 1477.0, 1633.0 00265 }; 00266 00267 static float mf_tones[] = 00268 { 00269 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0 00270 }; 00271 00272 #ifdef FAX_DETECT 00273 static float fax_freq = 1100.0; 00274 #endif 00275 00276 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; 00277 00278 #ifdef OLD_DSP_ROUTINES 00279 static char mf_hit[6][6] = { 00280 /* 700 + */ { 0, '1', '2', '4', '7', 'C' }, 00281 /* 900 + */ { '1', 0, '3', '5', '8', 'A' }, 00282 /* 1100 + */ { '2', '3', 0, '6', '9', '*' }, 00283 /* 1300 + */ { '4', '5', '6', 0, '0', 'B' }, 00284 /* 1500 + */ { '7', '8', '9', '0', 0, '#' }, 00285 /* 1700 + */ { 'C', 'A', '*', 'B', '#', 0 }, 00286 }; 00287 #else 00288 static char bell_mf_positions[] = "1247C-358A--69*---0B----#"; 00289 #endif 00290 00291 static inline void goertzel_sample(goertzel_state_t *s, short sample) 00292 { 00293 float v1; 00294 float fsamp = sample; 00295 00296 v1 = s->v2; 00297 s->v2 = s->v3; 00298 s->v3 = s->fac * s->v2 - v1 + fsamp; 00299 } 00300 00301 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count) 00302 { 00303 int i; 00304 00305 for (i=0;i<count;i++) 00306 goertzel_sample(s, samps[i]); 00307 } 00308 00309 00310 static inline float goertzel_result(goertzel_state_t *s) 00311 { 00312 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac; 00313 } 00314 00315 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples) 00316 { 00317 s->v2 = s->v3 = 0.0; 00318 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0)); 00319 #ifndef OLD_DSP_ROUTINES 00320 s->samples = samples; 00321 #endif 00322 } 00323 00324 static inline void goertzel_reset(goertzel_state_t *s) 00325 { 00326 s->v2 = s->v3 = 0.0; 00327 } 00328 00329 struct ast_dsp { 00330 struct ast_frame f; 00331 int threshold; 00332 int totalsilence; 00333 int totalnoise; 00334 int features; 00335 int ringtimeout; 00336 int busymaybe; 00337 int busycount; 00338 int busy_tonelength; 00339 int busy_quietlength; 00340 int historicnoise[DSP_HISTORY]; 00341 int historicsilence[DSP_HISTORY]; 00342 goertzel_state_t freqs[7]; 00343 int freqcount; 00344 int gsamps; 00345 enum gsamp_size gsamp_size; 00346 enum prog_mode progmode; 00347 int tstate; 00348 int tcount; 00349 int digitmode; 00350 int thinkdigit; 00351 float genergy; 00352 union { 00353 dtmf_detect_state_t dtmf; 00354 mf_detect_state_t mf; 00355 } td; 00356 }; 00357 00358 static void ast_dtmf_detect_init (dtmf_detect_state_t *s) 00359 { 00360 int i; 00361 00362 #ifdef OLD_DSP_ROUTINES 00363 s->hit1 = 00364 s->mhit = 00365 s->hit3 = 00366 s->hit4 = 00367 s->hit2 = 0; 00368 #else 00369 s->hits[0] = s->hits[1] = s->hits[2] = 0; 00370 #endif 00371 for (i = 0; i < 4; i++) { 00372 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00373 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00374 #ifdef OLD_DSP_ROUTINES 00375 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102); 00376 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102); 00377 #endif 00378 s->energy = 0.0; 00379 } 00380 #ifdef FAX_DETECT 00381 /* Same for the fax dector */ 00382 goertzel_init (&s->fax_tone, fax_freq, 102); 00383 00384 #ifdef OLD_DSP_ROUTINES 00385 /* Same for the fax dector 2nd harmonic */ 00386 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102); 00387 #endif 00388 #endif /* FAX_DETECT */ 00389 s->current_sample = 0; 00390 s->detected_digits = 0; 00391 s->current_digits = 0; 00392 memset(&s->digits, 0, sizeof(s->digits)); 00393 s->lost_digits = 0; 00394 s->digits[0] = '\0'; 00395 } 00396 00397 static void ast_mf_detect_init (mf_detect_state_t *s) 00398 { 00399 int i; 00400 #ifdef OLD_DSP_ROUTINES 00401 s->hit1 = 00402 s->hit2 = 0; 00403 #else 00404 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00405 #endif 00406 for (i = 0; i < 6; i++) { 00407 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00408 #ifdef OLD_DSP_ROUTINES 00409 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160); 00410 s->energy = 0.0; 00411 #endif 00412 } 00413 s->current_digits = 0; 00414 memset(&s->digits, 0, sizeof(s->digits)); 00415 s->current_sample = 0; 00416 s->detected_digits = 0; 00417 s->lost_digits = 0; 00418 s->digits[0] = '\0'; 00419 s->mhit = 0; 00420 } 00421 00422 static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, 00423 int digitmode, int *writeback, int faxdetect) 00424 { 00425 float row_energy[4]; 00426 float col_energy[4]; 00427 #ifdef FAX_DETECT 00428 float fax_energy; 00429 #ifdef OLD_DSP_ROUTINES 00430 float fax_energy_2nd; 00431 #endif 00432 #endif /* FAX_DETECT */ 00433 float famp; 00434 float v1; 00435 int i; 00436 int j; 00437 int sample; 00438 int best_row; 00439 int best_col; 00440 int hit; 00441 int limit; 00442 00443 hit = 0; 00444 for (sample = 0; sample < samples; sample = limit) { 00445 /* 102 is optimised to meet the DTMF specs. */ 00446 if ((samples - sample) >= (102 - s->current_sample)) 00447 limit = sample + (102 - s->current_sample); 00448 else 00449 limit = samples; 00450 #if defined(USE_3DNOW) 00451 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00452 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00453 #ifdef OLD_DSP_ROUTINES 00454 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00455 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00456 #endif 00457 /* XXX Need to fax detect for 3dnow too XXX */ 00458 #warning "Fax Support Broken" 00459 #else 00460 /* The following unrolled loop takes only 35% (rough estimate) of the 00461 time of a rolled loop on the machine on which it was developed */ 00462 for (j=sample;j<limit;j++) { 00463 famp = amp[j]; 00464 s->energy += famp*famp; 00465 /* With GCC 2.95, the following unrolled code seems to take about 35% 00466 (rough estimate) as long as a neat little 0-3 loop */ 00467 v1 = s->row_out[0].v2; 00468 s->row_out[0].v2 = s->row_out[0].v3; 00469 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; 00470 v1 = s->col_out[0].v2; 00471 s->col_out[0].v2 = s->col_out[0].v3; 00472 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; 00473 v1 = s->row_out[1].v2; 00474 s->row_out[1].v2 = s->row_out[1].v3; 00475 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; 00476 v1 = s->col_out[1].v2; 00477 s->col_out[1].v2 = s->col_out[1].v3; 00478 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; 00479 v1 = s->row_out[2].v2; 00480 s->row_out[2].v2 = s->row_out[2].v3; 00481 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; 00482 v1 = s->col_out[2].v2; 00483 s->col_out[2].v2 = s->col_out[2].v3; 00484 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; 00485 v1 = s->row_out[3].v2; 00486 s->row_out[3].v2 = s->row_out[3].v3; 00487 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; 00488 v1 = s->col_out[3].v2; 00489 s->col_out[3].v2 = s->col_out[3].v3; 00490 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; 00491 #ifdef FAX_DETECT 00492 /* Update fax tone */ 00493 v1 = s->fax_tone.v2; 00494 s->fax_tone.v2 = s->fax_tone.v3; 00495 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; 00496 #endif /* FAX_DETECT */ 00497 #ifdef OLD_DSP_ROUTINES 00498 v1 = s->col_out2nd[0].v2; 00499 s->col_out2nd[0].v2 = s->col_out2nd[0].v3; 00500 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; 00501 v1 = s->row_out2nd[0].v2; 00502 s->row_out2nd[0].v2 = s->row_out2nd[0].v3; 00503 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; 00504 v1 = s->col_out2nd[1].v2; 00505 s->col_out2nd[1].v2 = s->col_out2nd[1].v3; 00506 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; 00507 v1 = s->row_out2nd[1].v2; 00508 s->row_out2nd[1].v2 = s->row_out2nd[1].v3; 00509 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; 00510 v1 = s->col_out2nd[2].v2; 00511 s->col_out2nd[2].v2 = s->col_out2nd[2].v3; 00512 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; 00513 v1 = s->row_out2nd[2].v2; 00514 s->row_out2nd[2].v2 = s->row_out2nd[2].v3; 00515 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; 00516 v1 = s->col_out2nd[3].v2; 00517 s->col_out2nd[3].v2 = s->col_out2nd[3].v3; 00518 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; 00519 v1 = s->row_out2nd[3].v2; 00520 s->row_out2nd[3].v2 = s->row_out2nd[3].v3; 00521 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; 00522 #ifdef FAX_DETECT 00523 /* Update fax tone */ 00524 v1 = s->fax_tone.v2; 00525 s->fax_tone2nd.v2 = s->fax_tone2nd.v3; 00526 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; 00527 #endif /* FAX_DETECT */ 00528 #endif 00529 } 00530 #endif 00531 s->current_sample += (limit - sample); 00532 if (s->current_sample < 102) { 00533 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00534 /* If we had a hit last time, go ahead and clear this out since likely it 00535 will be another hit */ 00536 for (i=sample;i<limit;i++) 00537 amp[i] = 0; 00538 *writeback = 1; 00539 } 00540 continue; 00541 } 00542 #ifdef FAX_DETECT 00543 /* Detect the fax energy, too */ 00544 fax_energy = goertzel_result(&s->fax_tone); 00545 #endif 00546 /* We are at the end of a DTMF detection block */ 00547 /* Find the peak row and the peak column */ 00548 row_energy[0] = goertzel_result (&s->row_out[0]); 00549 col_energy[0] = goertzel_result (&s->col_out[0]); 00550 00551 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00552 row_energy[i] = goertzel_result (&s->row_out[i]); 00553 if (row_energy[i] > row_energy[best_row]) 00554 best_row = i; 00555 col_energy[i] = goertzel_result (&s->col_out[i]); 00556 if (col_energy[i] > col_energy[best_col]) 00557 best_col = i; 00558 } 00559 hit = 0; 00560 /* Basic signal level test and the twist test */ 00561 if (row_energy[best_row] >= DTMF_THRESHOLD && 00562 col_energy[best_col] >= DTMF_THRESHOLD && 00563 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00564 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00565 /* Relative peak test */ 00566 for (i = 0; i < 4; i++) { 00567 if ((i != best_col && 00568 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00569 (i != best_row 00570 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00571 break; 00572 } 00573 } 00574 #ifdef OLD_DSP_ROUTINES 00575 /* ... and second harmonic test */ 00576 if (i >= 4 && 00577 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy && 00578 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] 00579 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { 00580 #else 00581 /* ... and fraction of total energy test */ 00582 if (i >= 4 && 00583 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) { 00584 #endif 00585 /* Got a hit */ 00586 hit = dtmf_positions[(best_row << 2) + best_col]; 00587 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00588 /* Zero out frame data if this is part DTMF */ 00589 for (i=sample;i<limit;i++) 00590 amp[i] = 0; 00591 *writeback = 1; 00592 } 00593 /* Look for two successive similar results */ 00594 /* The logic in the next test is: 00595 We need two successive identical clean detects, with 00596 something different preceeding it. This can work with 00597 back to back differing digits. More importantly, it 00598 can work with nasty phones that give a very wobbly start 00599 to a digit */ 00600 #ifdef OLD_DSP_ROUTINES 00601 if (hit == s->hit3 && s->hit3 != s->hit2) { 00602 s->mhit = hit; 00603 s->digit_hits[(best_row << 2) + best_col]++; 00604 s->detected_digits++; 00605 if (s->current_digits < MAX_DTMF_DIGITS) { 00606 s->digits[s->current_digits++] = hit; 00607 s->digits[s->current_digits] = '\0'; 00608 } else { 00609 s->lost_digits++; 00610 } 00611 } 00612 #else 00613 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0]) { 00614 s->mhit = hit; 00615 s->digit_hits[(best_row << 2) + best_col]++; 00616 s->detected_digits++; 00617 if (s->current_digits < MAX_DTMF_DIGITS) { 00618 s->digits[s->current_digits++] = hit; 00619 s->digits[s->current_digits] = '\0'; 00620 } else { 00621 s->lost_digits++; 00622 } 00623 } 00624 #endif 00625 } 00626 } 00627 #ifdef FAX_DETECT 00628 if (!hit && (fax_energy >= FAX_THRESHOLD) && 00629 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) && 00630 (faxdetect)) { 00631 #if 0 00632 printf("Fax energy/Second Harmonic: %f\n", fax_energy); 00633 #endif 00634 /* XXX Probably need better checking than just this the energy XXX */ 00635 hit = 'f'; 00636 s->fax_hits++; 00637 } else { 00638 if (s->fax_hits > 5) { 00639 hit = 'f'; 00640 s->mhit = 'f'; 00641 s->detected_digits++; 00642 if (s->current_digits < MAX_DTMF_DIGITS) { 00643 s->digits[s->current_digits++] = hit; 00644 s->digits[s->current_digits] = '\0'; 00645 } else { 00646 s->lost_digits++; 00647 } 00648 } 00649 s->fax_hits = 0; 00650 } 00651 #endif /* FAX_DETECT */ 00652 #ifdef OLD_DSP_ROUTINES 00653 s->hit1 = s->hit2; 00654 s->hit2 = s->hit3; 00655 s->hit3 = hit; 00656 #else 00657 s->hits[0] = s->hits[1]; 00658 s->hits[1] = s->hits[2]; 00659 s->hits[2] = hit; 00660 #endif 00661 /* Reinitialise the detector for the next block */ 00662 for (i = 0; i < 4; i++) { 00663 goertzel_reset(&s->row_out[i]); 00664 goertzel_reset(&s->col_out[i]); 00665 #ifdef OLD_DSP_ROUTINES 00666 goertzel_reset(&s->row_out2nd[i]); 00667 goertzel_reset(&s->col_out2nd[i]); 00668 #endif 00669 } 00670 #ifdef FAX_DETECT 00671 goertzel_reset (&s->fax_tone); 00672 #ifdef OLD_DSP_ROUTINES 00673 goertzel_reset (&s->fax_tone2nd); 00674 #endif 00675 #endif 00676 s->energy = 0.0; 00677 s->current_sample = 0; 00678 } 00679 if ((!s->mhit) || (s->mhit != hit)) { 00680 s->mhit = 0; 00681 return(0); 00682 } 00683 return (hit); 00684 } 00685 00686 /* MF goertzel size */ 00687 #ifdef OLD_DSP_ROUTINES 00688 #define MF_GSIZE 160 00689 #else 00690 #define MF_GSIZE 120 00691 #endif 00692 00693 static int mf_detect (mf_detect_state_t *s, int16_t amp[], 00694 int samples, int digitmode, int *writeback) 00695 { 00696 #ifdef OLD_DSP_ROUTINES 00697 float tone_energy[6]; 00698 int best1; 00699 int best2; 00700 float max; 00701 int sofarsogood; 00702 #else 00703 float energy[6]; 00704 int best; 00705 int second_best; 00706 #endif 00707 float famp; 00708 float v1; 00709 int i; 00710 int j; 00711 int sample; 00712 int hit; 00713 int limit; 00714 00715 hit = 0; 00716 for (sample = 0; sample < samples; sample = limit) { 00717 /* 80 is optimised to meet the MF specs. */ 00718 if ((samples - sample) >= (MF_GSIZE - s->current_sample)) 00719 limit = sample + (MF_GSIZE - s->current_sample); 00720 else 00721 limit = samples; 00722 #if defined(USE_3DNOW) 00723 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00724 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00725 #ifdef OLD_DSP_ROUTINES 00726 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00727 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00728 #endif 00729 /* XXX Need to fax detect for 3dnow too XXX */ 00730 #warning "Fax Support Broken" 00731 #else 00732 /* The following unrolled loop takes only 35% (rough estimate) of the 00733 time of a rolled loop on the machine on which it was developed */ 00734 for (j = sample; j < limit; j++) { 00735 famp = amp[j]; 00736 #ifdef OLD_DSP_ROUTINES 00737 s->energy += famp*famp; 00738 #endif 00739 /* With GCC 2.95, the following unrolled code seems to take about 35% 00740 (rough estimate) as long as a neat little 0-3 loop */ 00741 v1 = s->tone_out[0].v2; 00742 s->tone_out[0].v2 = s->tone_out[0].v3; 00743 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp; 00744 v1 = s->tone_out[1].v2; 00745 s->tone_out[1].v2 = s->tone_out[1].v3; 00746 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp; 00747 v1 = s->tone_out[2].v2; 00748 s->tone_out[2].v2 = s->tone_out[2].v3; 00749 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp; 00750 v1 = s->tone_out[3].v2; 00751 s->tone_out[3].v2 = s->tone_out[3].v3; 00752 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp; 00753 v1 = s->tone_out[4].v2; 00754 s->tone_out[4].v2 = s->tone_out[4].v3; 00755 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp; 00756 v1 = s->tone_out[5].v2; 00757 s->tone_out[5].v2 = s->tone_out[5].v3; 00758 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp; 00759 #ifdef OLD_DSP_ROUTINES 00760 v1 = s->tone_out2nd[0].v2; 00761 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3; 00762 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp; 00763 v1 = s->tone_out2nd[1].v2; 00764 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3; 00765 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp; 00766 v1 = s->tone_out2nd[2].v2; 00767 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3; 00768 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp; 00769 v1 = s->tone_out2nd[3].v2; 00770 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3; 00771 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp; 00772 v1 = s->tone_out2nd[4].v2; 00773 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3; 00774 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp; 00775 v1 = s->tone_out2nd[3].v2; 00776 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3; 00777 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp; 00778 #endif 00779 } 00780 #endif 00781 s->current_sample += (limit - sample); 00782 if (s->current_sample < MF_GSIZE) { 00783 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00784 /* If we had a hit last time, go ahead and clear this out since likely it 00785 will be another hit */ 00786 for (i=sample;i<limit;i++) 00787 amp[i] = 0; 00788 *writeback = 1; 00789 } 00790 continue; 00791 } 00792 #ifdef OLD_DSP_ROUTINES 00793 /* We're at the end of an MF detection block. Go ahead and calculate 00794 all the energies. */ 00795 for (i=0;i<6;i++) { 00796 tone_energy[i] = goertzel_result(&s->tone_out[i]); 00797 } 00798 /* Find highest */ 00799 best1 = 0; 00800 max = tone_energy[0]; 00801 for (i=1;i<6;i++) { 00802 if (tone_energy[i] > max) { 00803 max = tone_energy[i]; 00804 best1 = i; 00805 } 00806 } 00807 00808 /* Find 2nd highest */ 00809 if (best1) { 00810 max = tone_energy[0]; 00811 best2 = 0; 00812 } else { 00813 max = tone_energy[1]; 00814 best2 = 1; 00815 } 00816 00817 for (i=0;i<6;i++) { 00818 if (i == best1) continue; 00819 if (tone_energy[i] > max) { 00820 max = tone_energy[i]; 00821 best2 = i; 00822 } 00823 } 00824 hit = 0; 00825 if (best1 != best2) 00826 sofarsogood=1; 00827 else 00828 sofarsogood=0; 00829 /* Check for relative energies */ 00830 for (i=0;i<6;i++) { 00831 if (i == best1) 00832 continue; 00833 if (i == best2) 00834 continue; 00835 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) { 00836 sofarsogood = 0; 00837 break; 00838 } 00839 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) { 00840 sofarsogood = 0; 00841 break; 00842 } 00843 } 00844 00845 if (sofarsogood) { 00846 /* Check for 2nd harmonic */ 00847 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 00848 sofarsogood = 0; 00849 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2]) 00850 sofarsogood = 0; 00851 } 00852 if (sofarsogood) { 00853 hit = mf_hit[best1][best2]; 00854 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00855 /* Zero out frame data if this is part DTMF */ 00856 for (i=sample;i<limit;i++) 00857 amp[i] = 0; 00858 *writeback = 1; 00859 } 00860 /* Look for two consecutive clean hits */ 00861 if ((hit == s->hit3) && (s->hit3 != s->hit2)) { 00862 s->mhit = hit; 00863 s->detected_digits++; 00864 if (s->current_digits < MAX_DTMF_DIGITS - 2) { 00865 s->digits[s->current_digits++] = hit; 00866 s->digits[s->current_digits] = '\0'; 00867 } else { 00868 s->lost_digits++; 00869 } 00870 } 00871 } 00872 00873 s->hit1 = s->hit2; 00874 s->hit2 = s->hit3; 00875 s->hit3 = hit; 00876 /* Reinitialise the detector for the next block */ 00877 for (i = 0; i < 6; i++) { 00878 goertzel_reset(&s->tone_out[i]); 00879 goertzel_reset(&s->tone_out2nd[i]); 00880 } 00881 s->energy = 0.0; 00882 s->current_sample = 0; 00883 } 00884 #else 00885 /* We're at the end of an MF detection block. */ 00886 /* Find the two highest energies. The spec says to look for 00887 two tones and two tones only. Taking this literally -ie 00888 only two tones pass the minimum threshold - doesn't work 00889 well. The sinc function mess, due to rectangular windowing 00890 ensure that! Find the two highest energies and ensure they 00891 are considerably stronger than any of the others. */ 00892 energy[0] = goertzel_result(&s->tone_out[0]); 00893 energy[1] = goertzel_result(&s->tone_out[1]); 00894 if (energy[0] > energy[1]) { 00895 best = 0; 00896 second_best = 1; 00897 } else { 00898 best = 1; 00899 second_best = 0; 00900 } 00901 /*endif*/ 00902 for (i=2;i<6;i++) { 00903 energy[i] = goertzel_result(&s->tone_out[i]); 00904 if (energy[i] >= energy[best]) { 00905 second_best = best; 00906 best = i; 00907 } else if (energy[i] >= energy[second_best]) { 00908 second_best = i; 00909 } 00910 } 00911 /* Basic signal level and twist tests */ 00912 hit = 0; 00913 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00914 && energy[best] < energy[second_best]*BELL_MF_TWIST 00915 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00916 /* Relative peak test */ 00917 hit = -1; 00918 for (i=0;i<6;i++) { 00919 if (i != best && i != second_best) { 00920 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00921 /* The best two are not clearly the best */ 00922 hit = 0; 00923 break; 00924 } 00925 } 00926 } 00927 } 00928 if (hit) { 00929 /* Get the values into ascending order */ 00930 if (second_best < best) { 00931 i = best; 00932 best = second_best; 00933 second_best = i; 00934 } 00935 best = best*5 + second_best - 1; 00936 hit = bell_mf_positions[best]; 00937 /* Look for two successive similar results */ 00938 /* The logic in the next test is: 00939 For KP we need 4 successive identical clean detects, with 00940 two blocks of something different preceeding it. For anything 00941 else we need two successive identical clean detects, with