Sat Nov 1 06:30:35 2008

Asterisk developer's documentation


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  */
00027 
00028 /* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
00029 /*
00030    tone_detect.c - General telephony tone detection, and specific
00031                         detection of DTMF.
00032 
00033         Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
00034 
00035         Despite my general liking of the GPL, I place this code in the
00036         public domain for the benefit of all mankind - even the slimy
00037         ones who might try to proprietize my work and use it to my
00038         detriment.
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 /* Number of goertzels for progress detect */
00061 #define GSAMP_SIZE_NA 183        /* North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
00062 #define GSAMP_SIZE_CR 188        /* Costa Rica, Brazil - Only care about 425 Hz */
00063 #define GSAMP_SIZE_UK 160        /* UK disconnect goertzel feed - shoud trigger 400hz */
00064 
00065 #define PROG_MODE_NA    0
00066 #define PROG_MODE_CR    1  
00067 #define PROG_MODE_UK    2  
00068 
00069 /* For US modes */
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 /* For CR/BR modes */
00079 #define HZ_425 0
00080 
00081 /* For UK mode */
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 } }, /* North America */
00100    { GSAMP_SIZE_CR, { 425 } },
00101    { GSAMP_SIZE_UK, { 400 } },
00102 };
00103 
00104 #define DEFAULT_THRESHOLD  512
00105 
00106 #define BUSY_PERCENT    10 /* The percentage difference between the two last silence periods */
00107 #define BUSY_PAT_PERCENT   7  /* The percentage difference between measured and actual pattern */
00108 #define BUSY_THRESHOLD     100   /* Max number of ms difference between max and min times in busy */
00109 #define BUSY_MIN     75 /* Busy must be at least 80 ms in half-cadence */
00110 #define BUSY_MAX     3100  /* Busy can't be longer than 3100 ms in half-cadence */
00111 
00112 /* Remember last 15 units */
00113 #define DSP_HISTORY     15
00114 
00115 /* Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
00116 #define FAX_DETECT
00117 
00118 #define TONE_THRESH     10.0  /* How much louder the tone should be than channel energy */
00119 #define TONE_MIN_THRESH    1e8   /* How much tone there should be at least to attempt */
00120 #define COUNT_THRESH    3  /* Need at least 50ms of stuff to count it */
00121 #define UK_HANGUP_THRESH   60 /* This is the threshold for the UK */
00122 
00123 
00124 #define  MAX_DTMF_DIGITS      128
00125 
00126 /* Basic DTMF specs:
00127  *
00128  * Minimum tone on = 40ms
00129  * Minimum tone off = 50ms
00130  * Maximum digit rate = 10 per second
00131  * Normal twist <= 8dB accepted
00132  * Reverse twist <= 4dB accepted
00133  * S/N >= 15dB will detect OK
00134  * Attenuation <= 26dB will detect OK
00135  * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
00136  */
00137 
00138 #define DTMF_THRESHOLD     8.0e7
00139 #define FAX_THRESHOLD      8.0e7
00140 #define FAX_2ND_HARMONIC   2.0     /* 4dB */
00141 #define DTMF_NORMAL_TWIST  6.3     /* 8dB */
00142 #ifdef   RADIO_RELAX
00143 #define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5)     /* 4dB normal */
00144 #else
00145 #define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)     /* 4dB normal */
00146 #endif
00147 #define DTMF_RELATIVE_PEAK_ROW   6.3     /* 8dB */
00148 #define DTMF_RELATIVE_PEAK_COL   6.3     /* 8dB */
00149 #define DTMF_2ND_HARMONIC_ROW       ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)     /* 4dB normal */
00150 #define DTMF_2ND_HARMONIC_COL 63.1    /* 18dB */
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     /* 8dB */
00156 #define MF_REVERSE_TWIST   4.0     /* was 2.5 */
00157 #define MF_RELATIVE_PEAK   5.3     /* 8dB */
00158 #define MF_2ND_HARMONIC    1.7   /* was 2.5  */
00159 #else
00160 #define BELL_MF_THRESHOLD  1.6e9
00161 #define BELL_MF_TWIST      4.0     /* 6dB */
00162 #define BELL_MF_RELATIVE_PEAK 12.6    /* 11dB */
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    /*  700 + */ {   0, '1', '2', '4', '7', 'C' },
00262    /*  900 + */ { '1',   0, '3', '5', '8', 'A' },
00263    /* 1100 + */ { '2', '3',   0, '6', '9', '*' },
00264    /* 1300 + */ { '4', '5', '6',   0, '0', 'B' },
00265    /* 1500 + */ { '7', '8', '9', '0',  0, '#' },
00266    /* 1700 + */ { '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    /* Same for the fax dector */
00362    goertzel_init (&s->fax_tone, fax_freq, 102);
00363 
00364 #ifdef OLD_DSP_ROUTINES
00365    /* Same for the fax dector 2nd harmonic */
00366    goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
00367 #endif   
00368 #endif /* FAX_DETECT */
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 /* FAX_DETECT */
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       /* 102 is optimised to meet the DTMF specs. */
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       /* XXX Need to fax detect for 3dnow too XXX */
00438       #warning "Fax Support Broken"
00439 #else
00440       /* The following unrolled loop takes only 35% (rough estimate) of the 
00441          time of a rolled loop on the machine on which it was developed */
00442       for (j=sample;j<limit;j++) {
00443          famp = amp[j];
00444          s->energy += famp*famp;
00445          /* With GCC 2.95, the following unrolled code seems to take about 35%
00446             (rough estimate) as long as a neat little 0-3 loop */
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          /* Update fax tone */
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 /* FAX_DETECT */
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          /* Update fax tone */            
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 /* FAX_DETECT */
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             /* If we had a hit last time, go ahead and clear this out since likely it
00515                will be another hit */
00516             for (i=sample;i<limit;i++) 
00517                amp[i] = 0;
00518             *writeback = 1;
00519          }
00520          continue;
00521       }
00522 #ifdef FAX_DETECT
00523       /* Detect the fax energy, too */
00524       fax_energy = goertzel_result(&s->fax_tone);
00525 #endif
00526       /* We are at the end of a DTMF detection block */
00527       /* Find the peak row and the peak column */
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       /* Basic signal level test and the twist test */
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          /* Relative peak test */
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          /* ... and second harmonic test */
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          /* ... and fraction of total energy test */
00562          if (i >= 4 &&
00563              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
00564 #endif
00565             /* Got a hit */
00566             hit = dtmf_positions[(best_row << 2) + best_col];
00567             if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00568                /* Zero out frame data if this is part DTMF */
00569                for (i=sample;i<limit;i++) 
00570                   amp[i] = 0;
00571                *writeback = 1;
00572             }
00573             /* Look for two successive similar results */
00574             /* The logic in the next test is:
00575                We need two successive identical clean detects, with
00576                something different preceeding it. This can work with
00577                back to back differing digits. More importantly, it
00578                can work with nasty phones that give a very wobbly start
00579                to a digit */
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          /* XXX Probably need better checking than just this the energy XXX */
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 /* FAX_DETECT */
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       /* Reinitialise the detector for the next block */
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 /* MF goertzel size */
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       /* 80 is optimised to meet the MF specs. */
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       /* XXX Need to fax detect for 3dnow too XXX */
00710       #warning "Fax Support Broken"
00711 #else
00712       /* The following unrolled loop takes only 35% (rough estimate) of the 
00713          time of a rolled loop on the machine on which it was developed */
00714       for (j = sample;  j < limit;  j++) {
00715          famp = amp[j];
00716 #ifdef OLD_DSP_ROUTINES
00717          s->energy += famp*famp;
00718 #endif
00719          /* With GCC 2.95, the following unrolled code seems to take about 35%
00720             (rough estimate) as long as a neat little 0-3 loop */
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             /* If we had a hit last time, go ahead and clear this out since likely it
00765                will be another hit */
00766             for (i=sample;i<limit;i++) 
00767                amp[i] = 0;
00768             *writeback = 1;
00769          }
00770          continue;
00771       }
00772 #ifdef OLD_DSP_ROUTINES    
00773       /* We're at the end of an MF detection block.  Go ahead and calculate
00774          all the energies. */
00775       for (i=0;i<6;i++) {
00776          tone_energy[i] = goertzel_result(&s->tone_out[i]);
00777       }
00778       /* Find highest */
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       /* Find 2nd highest */
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       /* Check for relative energies */
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          /* Check for 2nd harmonic */
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             /* Zero out frame data if this is part DTMF */
00836             for (i=sample;i<limit;i++) 
00837                amp[i] = 0;
00838             *writeback = 1;
00839          }
00840          /* Look for two consecutive clean hits */
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       /* Reinitialise the detector for the next block */
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       /* We're at the end of an MF detection block.  */
00866       /* Find the two highest energies. The spec says to look for
00867          two tones and two tones only. Taking this literally -ie
00868          only two tones pass the minimum threshold - doesn't work
00869          well. The sinc function mess, due to rectangular windowing
00870          ensure that! Find the two highest energies and ensure they
00871          are considerably stronger than any of the others. */
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       /*endif*/
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       /* Basic signal level and twist tests */
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          /* Relative peak test */
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                   /* The best two are not clearly the best */
00902                   hit = 0;
00903                   break;
00904                }
00905             }
00906          }
00907       }
00908       if (hit) {
00909          /* Get the values into ascending order */
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          /* Look for two successive similar results */
00918          /* The logic in the next test is:
00919             For KP we need 4 successive identical clean detects, with
00920             two blocks of something different preceeding it. For anything
00921             else we need two successive identical clean detects, with
00922             two blocks of something different preceeding it. */
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       /* Reinitialise the detector for the next block */
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