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