Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:47 2007

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