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
00942             two blocks of something different preceeding it. */
00943          if (hit == s->hits[4] && hit == s->hits[3] &&
00944             ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
00945              (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 
00946              hit != s->hits[0]))) {
00947             s->detected_digits++;
00948             if (s->current_digits < MAX_DTMF_DIGITS) {
00949                s->digits[s->current_digits++] = hit;
00950                s->digits[s->current_digits] = '\0';
00951             } else {
00952                s->lost_digits++;
00953             }
00954          }
00955       } else {
00956          hit = 0;
00957       }
00958       s->hits[0] = s->hits[1];
00959       s->hits[1] = s->hits[2];
00960       s->hits[2] = s->hits[3];
00961       s->hits[3] = s->hits[4];
00962       s->hits[4] = hit;
00963       /* Reinitialise the detector for the next block */
00964       for (i = 0;  i < 6;  i++)
00965          goertzel_reset(&s->tone_out[i]);
00966       s->current_sample = 0;
00967    }
00968 #endif   
00969    if ((!s->mhit) || (s->mhit != hit)) {
00970       s->mhit = 0;
00971       return(0);
00972    }
00973    return (hit);
00974 }
00975 
00976 static int __ast_dsp_digitdetect(struct ast_dsp *dsp, short *s, int len, int *writeback)
00977 {
00978    int res;
00979    
00980    if (dsp->digitmode & DSP_DIGITMODE_MF)
00981       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00982    else
00983       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
00984    return res;
00985 }
00986 
00987 int ast_dsp_digitdetect(struct ast_dsp *dsp, struct ast_frame *inf)
00988 {
00989    short *s;
00990    int len;
00991    int ign=0;
00992 
00993    if (inf->frametype != AST_FRAME_VOICE) {
00994       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
00995       return 0;
00996    }
00997    if (inf->subclass != AST_FORMAT_SLINEAR) {
00998       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
00999       return 0;
01000    }
01001    s = inf->data;
01002    len = inf->datalen / 2;
01003    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01004 }
01005 
01006 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
01007 {
01008    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
01009    /* Make sure absolute levels are high enough */
01010    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
01011       return 0;
01012    /* Amplify ignored stuff */
01013    i2 *= TONE_THRESH;
01014    i1 *= TONE_THRESH;
01015    e *= TONE_THRESH;
01016    /* Check first tone */
01017    if ((p1 < i1) || (p1 < i2) || (p1 < e))
01018       return 0;
01019    /* And second */
01020    if ((p2 < i1) || (p2 < i2) || (p2 < e))
01021       return 0;
01022    /* Guess it's there... */
01023    return 1;
01024 }
01025 
01026 int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
01027 {
01028    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01029       if (max > dsp->td.mf.current_digits)
01030          max = dsp->td.mf.current_digits;
01031       if (max > 0) {
01032          memcpy(buf, dsp->td.mf.digits, max);
01033          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01034          dsp->td.mf.current_digits -= max;
01035       }
01036       buf[max] = '\0';
01037       return  max;
01038    } else {
01039       if (max > dsp->td.dtmf.current_digits)
01040          max = dsp->td.dtmf.current_digits;
01041       if (max > 0) {
01042          memcpy (buf, dsp->td.dtmf.digits, max);
01043          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01044          dsp->td.dtmf.current_digits -= max;
01045       }
01046       buf[max] = '\0';
01047       return  max;
01048    }
01049 }
01050 
01051 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
01052 {
01053    int x;
01054    int y;
01055    int pass;
01056    int newstate = DSP_TONE_STATE_SILENCE;
01057    int res = 0;
01058    while (len) {
01059       /* Take the lesser of the number of samples we need and what we have */
01060       pass = len;
01061       if (pass > dsp->gsamp_size - dsp->gsamps) 
01062          pass = dsp->gsamp_size - dsp->gsamps;
01063       for (x=0;x<pass;x++) {
01064          for (y=0;y<dsp->freqcount;y++) 
01065             goertzel_sample(&dsp->freqs[y], s[x]);
01066          dsp->genergy += s[x] * s[x];
01067       }
01068       s += pass;
01069       dsp->gsamps += pass;
01070       len -= pass;
01071       if (dsp->gsamps == dsp->gsamp_size) {
01072          float hz[7];
01073          for (y=0;y<7;y++)
01074             hz[y] = goertzel_result(&dsp->freqs[y]);
01075 #if 0
01076          printf("\n350:     425:     440:     480:     620:     950:     1400:    1800:    Energy:   \n");
01077          printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 
01078             hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy);
01079 #endif
01080          switch (dsp->progmode) {
01081          case PROG_MODE_NA:
01082             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
01083                newstate = DSP_TONE_STATE_BUSY;
01084             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01085                newstate = DSP_TONE_STATE_RINGING;
01086             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01087                newstate = DSP_TONE_STATE_DIALTONE;
01088             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01089                newstate = DSP_TONE_STATE_SPECIAL1;
01090             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01091                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
01092                   newstate = DSP_TONE_STATE_SPECIAL2;
01093             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01094                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
01095                   newstate = DSP_TONE_STATE_SPECIAL3;
01096             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01097                newstate = DSP_TONE_STATE_TALKING;
01098             } else
01099                newstate = DSP_TONE_STATE_SILENCE;
01100             break;
01101          case PROG_MODE_CR:
01102             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01103                newstate = DSP_TONE_STATE_RINGING;
01104             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01105                newstate = DSP_TONE_STATE_TALKING;
01106             } else
01107                newstate = DSP_TONE_STATE_SILENCE;
01108             break;
01109          case PROG_MODE_UK:
01110             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
01111                newstate = DSP_TONE_STATE_HUNGUP;
01112             }
01113             break;
01114          default:
01115             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01116          }
01117          if (newstate == dsp->tstate) {
01118             dsp->tcount++;
01119             if (dsp->ringtimeout)
01120                dsp->ringtimeout++;
01121             switch (dsp->tstate) {
01122                case DSP_TONE_STATE_RINGING:
01123                   if ((dsp->features & DSP_PROGRESS_RINGING) &&
01124                       (dsp->tcount==THRESH_RING)) {
01125                      res = AST_CONTROL_RINGING;
01126                      dsp->ringtimeout= 1;
01127                   }
01128                   break;
01129                case DSP_TONE_STATE_BUSY:
01130                   if ((dsp->features & DSP_PROGRESS_BUSY) &&
01131                       (dsp->tcount==THRESH_BUSY)) {
01132                      res = AST_CONTROL_BUSY;
01133                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01134                   }
01135                   break;
01136                case DSP_TONE_STATE_TALKING:
01137                   if ((dsp->features & DSP_PROGRESS_TALK) &&
01138                       (dsp->tcount==THRESH_TALK)) {
01139                      res = AST_CONTROL_ANSWER;
01140                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01141                   }
01142                   break;
01143                case DSP_TONE_STATE_SPECIAL3:
01144                   if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01145                       (dsp->tcount==THRESH_CONGESTION)) {
01146                      res = AST_CONTROL_CONGESTION;
01147                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01148                   }
01149                   break;
01150                case DSP_TONE_STATE_HUNGUP:
01151                   if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01152                       (dsp->tcount==THRESH_HANGUP)) {
01153                      res = AST_CONTROL_HANGUP;
01154                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01155                   }
01156                   break;
01157             }
01158             if (dsp->ringtimeout==THRESH_RING2ANSWER) {
01159 #if 0
01160                ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n");
01161 #endif
01162                res = AST_CONTROL_ANSWER;
01163                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01164             }
01165          } else {
01166 #if 0
01167             ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01168             ast_log(LOG_NOTICE, "Start state %d\n", newstate);
01169 #endif
01170             dsp->tstate = newstate;
01171             dsp->tcount = 1;
01172          }
01173          
01174          /* Reset goertzel */                
01175          for (x=0;x<7;x++)
01176             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01177          dsp->gsamps = 0;
01178          dsp->genergy = 0.0;
01179       }
01180    }
01181 #if 0
01182    if (res)
01183       printf("Returning %d\n", res);
01184 #endif      
01185    return res;
01186 }
01187 
01188 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
01189 {
01190    if (inf->frametype != AST_FRAME_VOICE) {
01191       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01192       return 0;
01193    }
01194    if (inf->subclass != AST_FORMAT_SLINEAR) {
01195       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01196       return 0;
01197    }
01198    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01199 }
01200 
01201 static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
01202 {
01203    int accum;
01204    int x;
01205    int res = 0;
01206 
01207    if (!len)
01208       return 0;
01209    accum = 0;
01210    for (x=0;x<len; x++) 
01211       accum += abs(s[x]);
01212    accum /= len;
01213    if (accum < dsp->threshold) {
01214       /* Silent */
01215       dsp->totalsilence += len/8;
01216       if (dsp->totalnoise) {
01217          /* Move and save history */
01218          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01219          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01220 /* we don't want to check for busydetect that frequently */
01221 #if 0
01222          dsp->busymaybe = 1;
01223 #endif
01224       }
01225       dsp->totalnoise = 0;
01226       res = 1;
01227    } else {
01228       /* Not silent */
01229       dsp->totalnoise += len/8;
01230       if (dsp->totalsilence) {
01231          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01232          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01233          /* Move and save history */
01234          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01235          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01236          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01237          if (silence1 < silence2) {
01238             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01239                dsp->busymaybe = 1;
01240             else 
01241                dsp->busymaybe = 0;
01242          } else {
01243             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01244                dsp->busymaybe = 1;
01245             else 
01246                dsp->busymaybe = 0;
01247          }
01248       }
01249       dsp->totalsilence = 0;
01250    }
01251    if (totalsilence)
01252       *totalsilence = dsp->totalsilence;
01253    return res;
01254 }
01255 
01256 #ifdef BUSYDETECT_MARTIN
01257 int ast_dsp_busydetect(struct ast_dsp *dsp)
01258 {
01259    int res = 0, x;
01260 #ifndef BUSYDETECT_TONEONLY
01261    int avgsilence = 0, hitsilence = 0;
01262 #endif
01263    int avgtone = 0, hittone = 0;
01264    if (!dsp->busymaybe)
01265       return res;
01266    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01267 #ifndef BUSYDETECT_TONEONLY
01268       avgsilence += dsp->historicsilence[x];
01269 #endif
01270       avgtone += dsp->historicnoise[x];
01271    }
01272 #ifndef BUSYDETECT_TONEONLY
01273    avgsilence /= dsp->busycount;
01274 #endif
01275    avgtone /= dsp->busycount;
01276    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01277 #ifndef BUSYDETECT_TONEONLY
01278       if (avgsilence > dsp->historicsilence[x]) {
01279          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01280             hitsilence++;
01281       } else {
01282          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01283             hitsilence++;
01284       }
01285 #endif
01286       if (avgtone > dsp->historicnoise[x]) {
01287          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01288             hittone++;
01289       } else {
01290          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01291             hittone++;
01292       }
01293    }
01294 #ifndef BUSYDETECT_TONEONLY
01295    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01296        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01297        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01298 #else
01299    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01300 #endif
01301 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01302 #ifdef BUSYDETECT_TONEONLY
01303 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
01304 #endif
01305       if (avgtone > avgsilence) {
01306          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01307             res = 1;
01308       } else {
01309          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01310             res = 1;
01311       }
01312 #else
01313       res = 1;
01314 #endif
01315    }
01316    /* If we know the expected busy tone length, check we are in the range */
01317    if (res && (dsp->busy_tonelength > 0)) {
01318       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01319 #if 0
01320          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
01321                   avgtone, dsp->busy_tonelength);
01322 #endif
01323          res = 0;
01324       }
01325    }
01326 #ifndef BUSYDETECT_TONEONLY
01327    /* If we know the expected busy tone silent-period length, check we are in the range */
01328    if (res && (dsp->busy_quietlength > 0)) {
01329       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01330 #if 0
01331          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01332                   avgsilence, dsp->busy_quietlength);
01333 #endif
01334          res = 0;
01335       }
01336    }
01337 #endif
01338 #if 1
01339    if (res) {
01340       if (option_debug)
01341          ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01342    }
01343 #endif
01344    return res;
01345 }
01346 #endif
01347 
01348 #ifdef BUSYDETECT
01349 int ast_dsp_busydetect(struct ast_dsp *dsp)
01350 {
01351    int x;
01352    int res = 0;
01353    int max, min;
01354 
01355 #if 0
01356    if (dsp->busy_hits > 5);
01357    return 0;
01358 #endif
01359    if (dsp->busymaybe) {
01360 #if 0
01361       printf("Maybe busy!\n");
01362 #endif      
01363       dsp->busymaybe = 0;
01364       min = 9999;
01365       max = 0;
01366       for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01367 #if 0
01368          printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
01369 #endif         
01370          if (dsp->historicsilence[x] < min)
01371             min = dsp->historicsilence[x];
01372          if (dsp->historicnoise[x] < min)
01373             min = dsp->historicnoise[x];
01374          if (dsp->historicsilence[x] > max)
01375             max = dsp->historicsilence[x];
01376          if (dsp->historicnoise[x] > max)
01377             max = dsp->historicnoise[x];
01378       }
01379       if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
01380 #if 0
01381          printf("Busy!\n");
01382 #endif         
01383          res = 1;
01384       }
01385 #if 0
01386       printf("Min: %d, max: %d\n", min, max);
01387 #endif      
01388    }
01389    return res;
01390 }
01391 #endif
01392 
01393 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
01394 {
01395    short *s;
01396    int len;
01397    
01398    if (f->frametype != AST_FRAME_VOICE) {
01399       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01400       return 0;
01401    }
01402    if (f->subclass != AST_FORMAT_SLINEAR) {
01403       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01404       return 0;
01405    }
01406    s = f->data;
01407    len = f->datalen/2;
01408    return __ast_dsp_silence(dsp, s, len, totalsilence);
01409 }
01410 
01411 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
01412 {
01413    int silence;
01414    int res;
01415    int digit;
01416    int x;
01417    short *shortdata;
01418    unsigned char *odata;
01419    int len;
01420    int writeback = 0;
01421 
01422 #define FIX_INF(inf) do { \
01423       if (writeback) { \
01424          switch (inf->subclass) { \
01425          case AST_FORMAT_SLINEAR: \
01426             break; \
01427          case AST_FORMAT_ULAW: \
01428             for (x=0;x<len;x++) \
01429                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01430             break; \
01431          case AST_FORMAT_ALAW: \
01432             for (x=0;x<len;x++) \
01433                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01434             break; \
01435          } \
01436       } \
01437    } while(0) 
01438 
01439    if (!af)
01440       return NULL;
01441    if (af->frametype != AST_FRAME_VOICE)
01442       return af;
01443    odata = af->data;
01444    len = af->datalen;
01445    /* Make sure we have short data */
01446    switch (af->subclass) {
01447    case AST_FORMAT_SLINEAR:
01448       shortdata = af->data;
01449       len = af->datalen / 2;
01450       break;
01451    case AST_FORMAT_ULAW:
01452       shortdata = alloca(af->datalen * 2);
01453       for (x = 0;x < len; x++) 
01454          shortdata[x] = AST_MULAW(odata[x]);
01455       break;
01456    case AST_FORMAT_ALAW:
01457       shortdata = alloca(af->datalen * 2);
01458       for (x = 0; x < len; x++) 
01459          shortdata[x] = AST_ALAW(odata[x]);
01460       break;
01461    default:
01462       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01463       return af;
01464    }
01465    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01466    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01467       memset(&dsp->f, 0, sizeof(dsp->f));
01468       dsp->f.frametype = AST_FRAME_NULL;
01469       return &dsp->f;
01470    }
01471    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01472       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01473       memset(&dsp->f, 0, sizeof(dsp->f));
01474       dsp->f.frametype = AST_FRAME_CONTROL;
01475       dsp->f.subclass = AST_CONTROL_BUSY;
01476       if (option_debug)
01477          ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01478       return &dsp->f;
01479    }
01480    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01481       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01482 #if 0
01483       if (digit)
01484          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01485 #endif         
01486       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01487          if (!dsp->thinkdigit) {
01488             if (digit) {
01489                /* Looks like we might have something.  
01490                 * Request a conference mute for the moment */
01491                memset(&dsp->f, 0, sizeof(dsp->f));
01492                dsp->f.frametype = AST_FRAME_DTMF;
01493                dsp->f.subclass = 'm';
01494                dsp->thinkdigit = 'x';
01495                FIX_INF(af);
01496                if (chan)
01497                   ast_queue_frame(chan, af);
01498                ast_frfree(af);
01499                return &dsp->f;
01500             }
01501          } else {
01502             if (digit) {
01503                /* Thought we saw one last time.  Pretty sure we really have now */
01504                if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01505                   /* If we found a digit, and we're changing digits, go
01506                      ahead and send this one, but DON'T stop confmute because
01507                      we're detecting something else, too... */
01508                   memset(&dsp->f, 0, sizeof(dsp->f));
01509                   dsp->f.frametype = AST_FRAME_DTMF_END;
01510                   dsp->f.subclass = dsp->thinkdigit;
01511                   FIX_INF(af);
01512                   if (chan)
01513                      ast_queue_frame(chan, af);
01514                   ast_frfree(af);
01515                } else {
01516                   dsp->thinkdigit = digit;
01517                   memset(&dsp->f, 0, sizeof(dsp->f));
01518                   dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
01519                   dsp->f.subclass = dsp->thinkdigit;
01520                   FIX_INF(af);
01521                   if (chan)
01522                      ast_queue_frame(chan, af);
01523                   ast_frfree(af);
01524                }
01525                return &dsp->f;
01526             } else {
01527                memset(&dsp->f, 0, sizeof(dsp->f));
01528                if (dsp->thinkdigit != 'x') {
01529                   /* If we found a digit, send it now */
01530                   dsp->f.frametype = AST_FRAME_DTMF_END;
01531                   dsp->f.subclass = dsp->thinkdigit;
01532                   dsp->thinkdigit = 0;
01533                } else {
01534                   dsp->f.frametype = AST_FRAME_DTMF;
01535                   dsp->f.subclass = 'u';
01536                   dsp->thinkdigit = 0;
01537                }
01538                FIX_INF(af);
01539                if (chan)
01540                   ast_queue_frame(chan, af);
01541                ast_frfree(af);
01542                return &dsp->f;
01543             }
01544          }
01545       } else if (!digit) {
01546          /* Only check when there is *not* a hit... */
01547          if (dsp->digitmode & DSP_DIGITMODE_MF) {
01548             if (dsp->td.mf.current_digits) {
01549                memset(&dsp->f, 0, sizeof(dsp->f));
01550                dsp->f.frametype = AST_FRAME_DTMF;
01551                dsp->f.subclass = dsp->td.mf.digits[0];
01552                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01553                dsp->td.mf.current_digits--;
01554                FIX_INF(af);
01555                if (chan)
01556                   ast_queue_frame(chan, af);
01557                ast_frfree(af);
01558                return &dsp->f;
01559             }
01560          } else {
01561             if (dsp->td.dtmf.current_digits) {
01562                memset(&dsp->f, 0, sizeof(dsp->f));
01563                dsp->f.frametype = AST_FRAME_DTMF_END;
01564                dsp->f.subclass = dsp->td.dtmf.digits[0];
01565                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01566                dsp->td.dtmf.current_digits--;
01567                FIX_INF(af);
01568                if (chan)
01569                   ast_queue_frame(chan, af);
01570                ast_frfree(af);
01571                return &dsp->f;
01572             }
01573          }
01574       }
01575    }
01576    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01577       res = __ast_dsp_call_progress(dsp, shortdata, len);
01578       if (res) {
01579          switch (res) {
01580          case AST_CONTROL_ANSWER:
01581          case AST_CONTROL_BUSY:
01582          case AST_CONTROL_RINGING:
01583          case AST_CONTROL_CONGESTION:
01584          case AST_CONTROL_HANGUP:
01585             memset(&dsp->f, 0, sizeof(dsp->f));
01586             dsp->f.frametype = AST_FRAME_CONTROL;
01587             dsp->f.subclass = res;
01588             dsp->f.src = "dsp_progress";
01589             if (chan) 
01590                ast_queue_frame(chan, &dsp->f);
01591             break;
01592          default:
01593             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01594          }
01595       }
01596    }
01597    FIX_INF(af);
01598    return af;
01599 }
01600 
01601 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
01602 {
01603    int max = 0;
01604    int x;
01605    
01606    dsp->gsamp_size = modes[dsp->progmode].size;
01607    dsp->gsamps = 0;
01608    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01609       if (modes[dsp->progmode].freqs[x]) {
01610          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01611          max = x + 1;
01612       }
01613    }
01614    dsp->freqcount = max;
01615    dsp->ringtimeout= 0;
01616 }
01617 
01618 struct ast_dsp *ast_dsp_new(void)
01619 {
01620    struct ast_dsp *dsp;
01621    
01622    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01623       dsp->threshold = DEFAULT_THRESHOLD;
01624       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01625       dsp->busycount = DSP_HISTORY;
01626       /* Initialize DTMF detector */
01627       ast_dtmf_detect_init(&dsp->td.dtmf);
01628       /* Initialize initial DSP progress detect parameters */
01629       ast_dsp_prog_reset(dsp);
01630    }
01631    return dsp;
01632 }
01633 
01634 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
01635 {
01636    dsp->features = features;
01637 }
01638 
01639 void ast_dsp_free(struct ast_dsp *dsp)
01640 {
01641    free(dsp);
01642 }
01643 
01644 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
01645 {
01646    dsp->threshold = threshold;
01647 }
01648 
01649 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
01650 {
01651    if (cadences < 4)
01652       cadences = 4;
01653    if (cadences > DSP_HISTORY)
01654       cadences = DSP_HISTORY;
01655    dsp->busycount = cadences;
01656 }
01657 
01658 void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
01659 {
01660    dsp->busy_tonelength = tonelength;
01661    dsp->busy_quietlength = quietlength;
01662    if (option_debug)
01663       ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01664 }
01665 
01666 void ast_dsp_digitreset(struct ast_dsp *dsp)
01667 {
01668    int i;
01669    
01670    dsp->thinkdigit = 0;
01671    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01672       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01673       dsp->td.mf.current_digits = 0;
01674       /* Reinitialise the detector for the next block */
01675       for (i = 0;  i < 6;  i++) {
01676          goertzel_reset(&dsp->td.mf.tone_out[i]);
01677 #ifdef OLD_DSP_ROUTINES
01678          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01679 #endif         
01680       }
01681 #ifdef OLD_DSP_ROUTINES
01682       dsp->td.mf.energy = 0.0;
01683       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01684 #else
01685       dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0;
01686 #endif      
01687       dsp->td.mf.current_sample = 0;
01688    } else {
01689       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01690       dsp->td.dtmf.current_digits = 0;
01691       /* Reinitialise the detector for the next block */
01692       for (i = 0;  i < 4;  i++) {
01693          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01694          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01695 #ifdef OLD_DSP_ROUTINES
01696          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01697          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01698 #endif         
01699       }
01700 #ifdef FAX_DETECT
01701       goertzel_reset (&dsp->td.dtmf.fax_tone);
01702 #endif
01703 #ifdef OLD_DSP_ROUTINES
01704 #ifdef FAX_DETECT
01705       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01706 #endif
01707       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01708 #else
01709       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01710 #endif      
01711       dsp->td.dtmf.energy = 0.0;
01712       dsp->td.dtmf.current_sample = 0;
01713    }
01714 }
01715 
01716 void ast_dsp_reset(struct ast_dsp *dsp)
01717 {
01718    int x;
01719    
01720    dsp->totalsilence = 0;
01721    dsp->gsamps = 0;
01722    for (x=0;x<4;x++)
01723       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01724    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01725    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01726    dsp->ringtimeout= 0;
01727 }
01728 
01729 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
01730 {
01731    int new;
01732    int old;
01733    
01734    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01735    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01736    if (old != new) {
01737       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01738       if (new & DSP_DIGITMODE_MF)
01739          ast_mf_detect_init(&dsp->td.mf);
01740       else
01741          ast_dtmf_detect_init(&dsp->td.dtmf);
01742    }
01743    dsp->digitmode = digitmode;
01744    return 0;
01745 }
01746 
01747 int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
01748 {
01749    int x;
01750    
01751    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01752       if (!strcasecmp(aliases[x].name, zone)) {
01753          dsp->progmode = aliases[x].mode;
01754          ast_dsp_prog_reset(dsp);
01755          return 0;
01756       }
01757    }
01758    return -1;
01759 }
01760 
01761 int ast_dsp_get_tstate(struct ast_dsp *dsp) 
01762 {
01763    return dsp->tstate;
01764 }
01765 
01766 int ast_dsp_get_tcount(struct ast_dsp *dsp) 
01767 {
01768    return dsp->tcount;
01769 }

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen