Mon Sep 18 09:13:15 2006

Asterisk developer's documentation


dsp.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
00009  * DTMF detector.
00010  *
00011  * See http://www.asterisk.org for more information about
00012  * the Asterisk project. Please do not directly contact
00013  * any of the maintainers of this project for assistance;
00014  * the project provides a web site, mailing lists and IRC
00015  * channels for your use.
00016  *
00017  * This program is free software, distributed under the terms of
00018  * the GNU General Public License Version 2. See the LICENSE file
00019  * at the top of the source tree.
00020  */
00021 
00022 /*! \file
00023  *
00024  * \brief Convenience Signal Processing routines
00025  * 
00026  */
00027 
00028 /* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
00029 /*
00030    tone_detect.c - General telephony tone detection, and specific
00031                         detection of DTMF.
00032 
00033         Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
00034 
00035         Despite my general liking of the GPL, I place this code in the
00036         public domain for the benefit of all mankind - even the slimy
00037         ones who might try to proprietize my work and use it to my
00038         detriment.
00039 */
00040 
00041 #include <sys/types.h>
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <string.h>
00045 #include <math.h>
00046 #include <errno.h>
00047 #include <stdio.h>
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 36697 $")
00052 
00053 #include "asterisk/frame.h"
00054 #include "asterisk/channel.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/dsp.h"
00057 #include "asterisk/ulaw.h"
00058 #include "asterisk/alaw.h"
00059 
00060 /* Number of goertzels for progress detect */
00061 #define GSAMP_SIZE_NA 183        /* North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
00062 #define GSAMP_SIZE_CR 188        /* Costa Rica, Brazil - Only care about 425 Hz */
00063 #define GSAMP_SIZE_UK 160        /* UK disconnect goertzel feed - shoud trigger 400hz */
00064 
00065 #define PROG_MODE_NA    0
00066 #define PROG_MODE_CR    1  
00067 #define PROG_MODE_UK    2  
00068 
00069 /* For US modes */
00070 #define HZ_350  0
00071 #define HZ_440  1
00072 #define HZ_480  2
00073 #define HZ_620  3
00074 #define HZ_950  4
00075 #define HZ_1400 5
00076 #define HZ_1800 6
00077 
00078 /* For CR/BR modes */
00079 #define HZ_425 0
00080 
00081 /* For UK mode */
00082 #define HZ_400 0
00083 
00084 static struct progalias {
00085    char *name;
00086    int mode;
00087 } aliases[] = {
00088    { "us", PROG_MODE_NA },
00089    { "ca", PROG_MODE_NA },
00090    { "cr", PROG_MODE_CR },
00091    { "br", PROG_MODE_CR },
00092    { "uk", PROG_MODE_UK },
00093 };
00094 
00095 static struct progress {
00096    int size;
00097    int freqs[7];
00098 } modes[] = {
00099    { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /* North America */
00100    { GSAMP_SIZE_CR, { 425 } },
00101    { GSAMP_SIZE_UK, { 400 } },
00102 };
00103 
00104 #define DEFAULT_THRESHOLD  512
00105 
00106 #define BUSY_PERCENT    10 /* The percentage difference between the two last silence periods */
00107 #define BUSY_PAT_PERCENT   7  /* The percentage difference between measured and actual pattern */
00108 #define BUSY_THRESHOLD     100   /* Max number of ms difference between max and min times in busy */
00109 #define BUSY_MIN     75 /* Busy must be at least 80 ms in half-cadence */
00110 #define BUSY_MAX     3100  /* Busy can't be longer than 3100 ms in half-cadence */
00111 
00112 /* Remember last 15 units */
00113 #define DSP_HISTORY     15
00114 
00115 /* Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
00116 #define FAX_DETECT
00117 
00118 #define TONE_THRESH     10.0  /* How much louder the tone should be than channel energy */
00119 #define TONE_MIN_THRESH    1e8   /* How much tone there should be at least to attempt */
00120 #define COUNT_THRESH    3  /* Need at least 50ms of stuff to count it */
00121 #define UK_HANGUP_THRESH   60 /* This is the threshold for the UK */
00122 
00123 
00124 #define  MAX_DTMF_DIGITS      128
00125 
00126 /* Basic DTMF specs:
00127  *
00128  * Minimum tone on = 40ms
00129  * Minimum tone off = 50ms
00130  * Maximum digit rate = 10 per second
00131  * Normal twist <= 8dB accepted
00132  * Reverse twist <= 4dB accepted
00133  * S/N >= 15dB will detect OK
00134  * Attenuation <= 26dB will detect OK
00135  * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
00136  */
00137 
00138 #define DTMF_THRESHOLD     8.0e7
00139 #define FAX_THRESHOLD      8.0e7
00140 #define FAX_2ND_HARMONIC   2.0     /* 4dB */
00141 #define DTMF_NORMAL_TWIST  6.3     /* 8dB */
00142 #ifdef   RADIO_RELAX
00143 #define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5)     /* 4dB normal */
00144 #else
00145 #define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)     /* 4dB normal */
00146 #endif
00147 #define DTMF_RELATIVE_PEAK_ROW   6.3     /* 8dB */
00148 #define DTMF_RELATIVE_PEAK_COL   6.3     /* 8dB */
00149 #define DTMF_2ND_HARMONIC_ROW       ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)     /* 4dB normal */
00150 #define DTMF_2ND_HARMONIC_COL 63.1    /* 18dB */
00151 #define DTMF_TO_TOTAL_ENERGY  42.0
00152 
00153 #ifdef OLD_DSP_ROUTINES
00154 #define MF_THRESHOLD    8.0e7
00155 #define MF_NORMAL_TWIST    5.3     /* 8dB */
00156 #define MF_REVERSE_TWIST   4.0     /* was 2.5 */
00157 #define MF_RELATIVE_PEAK   5.3     /* 8dB */
00158 #define MF_2ND_HARMONIC    1.7   /* was 2.5  */
00159 #else
00160 #define BELL_MF_THRESHOLD  1.6e9
00161 #define BELL_MF_TWIST      4.0     /* 6dB */
00162 #define BELL_MF_RELATIVE_PEAK 12.6    /* 11dB */
00163 #endif
00164 
00165 #if !defined(BUSYDETECT_MARTIN) && !defined(BUSYDETECT) && !defined(BUSYDETECT_TONEONLY) && !defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
00166 #define BUSYDETECT_MARTIN
00167 #endif
00168 
00169 typedef struct {
00170    float v2;
00171    float v3;
00172    float fac;
00173 #ifndef OLD_DSP_ROUTINES
00174    int samples;
00175 #endif   
00176 } goertzel_state_t;
00177 
00178 typedef struct
00179 {
00180    goertzel_state_t row_out[4];
00181    goertzel_state_t col_out[4];
00182 #ifdef FAX_DETECT
00183    goertzel_state_t fax_tone;
00184 #endif
00185 #ifdef OLD_DSP_ROUTINES
00186    goertzel_state_t row_out2nd[4];
00187    goertzel_state_t col_out2nd[4];
00188 #ifdef FAX_DETECT
00189    goertzel_state_t fax_tone2nd;    
00190 #endif
00191    int hit1;
00192    int hit2;
00193    int hit3;
00194    int hit4;
00195 #else
00196    int hits[3];
00197 #endif   
00198    int mhit;
00199    float energy;
00200    int current_sample;
00201 
00202    char digits[MAX_DTMF_DIGITS + 1];
00203    
00204    int current_digits;
00205    int detected_digits;
00206    int lost_digits;
00207    int digit_hits[16];
00208 #ifdef FAX_DETECT
00209    int fax_hits;
00210 #endif
00211 } dtmf_detect_state_t;
00212 
00213 typedef struct
00214 {
00215    goertzel_state_t tone_out[6];
00216    int mhit;
00217 #ifdef OLD_DSP_ROUTINES
00218    int hit1;
00219    int hit2;
00220    int hit3;
00221    int hit4;
00222    goertzel_state_t tone_out2nd[6];
00223    float energy;
00224 #else
00225    int hits[5];
00226 #endif
00227    int current_sample;
00228    
00229    char digits[MAX_DTMF_DIGITS + 1];
00230 
00231    int current_digits;
00232    int detected_digits;
00233    int lost_digits;
00234 #ifdef FAX_DETECT
00235    int fax_hits;
00236 #endif
00237 } mf_detect_state_t;
00238 
00239 static float dtmf_row[] =
00240 {
00241    697.0,  770.0,  852.0,  941.0
00242 };
00243 static float dtmf_col[] =
00244 {
00245    1209.0, 1336.0, 1477.0, 1633.0
00246 };
00247 
00248 static float mf_tones[] =
00249 {
00250    700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
00251 };
00252 
00253 #ifdef FAX_DETECT
00254 static float fax_freq = 1100.0;
00255 #endif
00256 
00257 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
00258 
00259 #ifdef OLD_DSP_ROUTINES
00260 static char mf_hit[6][6] = {
00261    /*  700 + */ {   0, '1', '2', '4', '7', 'C' },
00262    /*  900 + */ { '1',   0, '3', '5', '8', 'A' },
00263    /* 1100 + */ { '2', '3',   0, '6', '9', '*' },
00264    /* 1300 + */ { '4', '5', '6',   0, '0', 'B' },
00265    /* 1500 + */ { '7', '8', '9', '0',  0, '#' },
00266    /* 1700 + */ { 'C', 'A', '*', 'B', '#',  0  },
00267 };
00268 #else
00269 static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
00270 #endif
00271 
00272 static inline void goertzel_sample(goertzel_state_t *s, short sample)
00273 {
00274    float v1;
00275    float fsamp  = sample;
00276    
00277    v1 = s->v2;
00278    s->v2 = s->v3;
00279    s->v3 = s->fac * s->v2 - v1 + fsamp;
00280 }
00281 
00282 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
00283 {
00284    int i;
00285    
00286    for (i=0;i<count;i++) 
00287       goertzel_sample(s, samps[i]);
00288 }
00289 
00290 
00291 static inline float goertzel_result(goertzel_state_t *s)
00292 {
00293    return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
00294 }
00295 
00296 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
00297 {
00298    s->v2 = s->v3 = 0.0;
00299    s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
00300 #ifndef OLD_DSP_ROUTINES
00301    s->samples = samples;
00302 #endif
00303 }
00304 
00305 static inline void goertzel_reset(goertzel_state_t *s)
00306 {
00307    s->v2 = s->v3 = 0.0;
00308 }
00309 
00310 struct ast_dsp {
00311    struct ast_frame f;
00312    int threshold;
00313    int totalsilence;
00314    int totalnoise;
00315    int features;
00316    int busymaybe;
00317    int busycount;
00318    int busy_tonelength;
00319    int busy_quietlength;
00320    int historicnoise[DSP_HISTORY];
00321    int historicsilence[DSP_HISTORY];
00322    goertzel_state_t freqs[7];
00323    int freqcount;
00324    int gsamps;
00325    int gsamp_size;
00326    int progmode;
00327    int tstate;
00328    int tcount;
00329    int digitmode;
00330    int thinkdigit;
00331    float genergy;
00332    union {
00333       dtmf_detect_state_t dtmf;
00334       mf_detect_state_t mf;
00335    } td;
00336 };
00337 
00338 static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
00339 {
00340    int i;
00341 
00342 #ifdef OLD_DSP_ROUTINES
00343    s->hit1 = 
00344    s->mhit = 
00345    s->hit3 =
00346    s->hit4 = 
00347    s->hit2 = 0;
00348 #else
00349    s->hits[0] = s->hits[1] = s->hits[2] = 0;
00350 #endif
00351    for (i = 0;  i < 4;  i++) {
00352       goertzel_init (&s->row_out[i], dtmf_row[i], 102);
00353       goertzel_init (&s->col_out[i], dtmf_col[i], 102);
00354 #ifdef OLD_DSP_ROUTINES
00355       goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
00356       goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
00357 #endif   
00358       s->energy = 0.0;
00359    }
00360 #ifdef FAX_DETECT
00361    /* Same for the fax dector */
00362    goertzel_init (&s->fax_tone, fax_freq, 102);
00363 
00364 #ifdef OLD_DSP_ROUTINES
00365    /* Same for the fax dector 2nd harmonic */
00366    goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
00367 #endif   
00368 #endif /* FAX_DETECT */
00369    s->current_sample = 0;
00370    s->detected_digits = 0;
00371    s->current_digits = 0;
00372    memset(&s->digits, 0, sizeof(s->digits));
00373    s->lost_digits = 0;
00374    s->digits[0] = '\0';
00375 }
00376 
00377 static void ast_mf_detect_init (mf_detect_state_t *s)
00378 {
00379    int i;
00380 #ifdef OLD_DSP_ROUTINES
00381    s->hit1 = 
00382    s->hit2 = 0;
00383 #else 
00384    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00385 #endif
00386    for (i = 0;  i < 6;  i++) {
00387       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00388 #ifdef OLD_DSP_ROUTINES
00389       goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
00390       s->energy = 0.0;
00391 #endif
00392    }
00393    s->current_digits = 0;
00394    memset(&s->digits, 0, sizeof(s->digits));
00395    s->current_sample = 0;
00396    s->detected_digits = 0;
00397    s->lost_digits = 0;
00398    s->digits[0] = '\0';
00399    s->mhit = 0;
00400 }
00401 
00402 static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, 
00403        int digitmode, int *writeback, int faxdetect)
00404 {
00405    float row_energy[4];
00406    float col_energy[4];
00407 #ifdef FAX_DETECT
00408    float fax_energy;
00409 #ifdef OLD_DSP_ROUTINES
00410    float fax_energy_2nd;
00411 #endif   
00412 #endif /* FAX_DETECT */
00413    float famp;
00414    float v1;
00415    int i;
00416    int j;
00417    int sample;
00418    int best_row;
00419    int best_col;
00420    int hit;
00421    int limit;
00422 
00423    hit = 0;
00424    for (sample = 0;  sample < samples;  sample = limit) {
00425       /* 102 is optimised to meet the DTMF specs. */
00426       if ((samples - sample) >= (102 - s->current_sample))
00427          limit = sample + (102 - s->current_sample);
00428       else
00429          limit = samples;
00430 #if defined(USE_3DNOW)
00431       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00432       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00433 #ifdef OLD_DSP_ROUTINES
00434       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00435       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00436 #endif      
00437       /* XXX Need to fax detect for 3dnow too XXX */
00438       #warning "Fax Support Broken"
00439 #else
00440       /* The following unrolled loop takes only 35% (rough estimate) of the 
00441          time of a rolled loop on the machine on which it was developed */
00442       for (j=sample;j<limit;j++) {
00443          famp = amp[j];
00444          s->energy += famp*famp;
00445          /* With GCC 2.95, the following unrolled code seems to take about 35%
00446             (rough estimate) as long as a neat little 0-3 loop */
00447          v1 = s->row_out[0].v2;
00448          s->row_out[0].v2 = s->row_out[0].v3;
00449          s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
00450          v1 = s->col_out[0].v2;
00451          s->col_out[0].v2 = s->col_out[0].v3;
00452          s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
00453          v1 = s->row_out[1].v2;
00454          s->row_out[1].v2 = s->row_out[1].v3;
00455          s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
00456          v1 = s->col_out[1].v2;
00457          s->col_out[1].v2 = s->col_out[1].v3;
00458          s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
00459          v1 = s->row_out[2].v2;
00460          s->row_out[2].v2 = s->row_out[2].v3;
00461          s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
00462          v1 = s->col_out[2].v2;
00463          s->col_out[2].v2 = s->col_out[2].v3;
00464          s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
00465          v1 = s->row_out[3].v2;
00466          s->row_out[3].v2 = s->row_out[3].v3;
00467          s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
00468          v1 = s->col_out[3].v2;
00469          s->col_out[3].v2 = s->col_out[3].v3;
00470          s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
00471 #ifdef FAX_DETECT
00472          /* Update fax tone */
00473          v1 = s->fax_tone.v2;
00474          s->fax_tone.v2 = s->fax_tone.v3;
00475          s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
00476 #endif /* FAX_DETECT */
00477 #ifdef OLD_DSP_ROUTINES
00478          v1 = s->col_out2nd[0].v2;
00479          s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
00480          s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
00481          v1 = s->row_out2nd[0].v2;
00482          s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
00483          s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
00484          v1 = s->col_out2nd[1].v2;
00485          s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
00486          s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
00487          v1 = s->row_out2nd[1].v2;
00488          s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
00489          s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
00490          v1 = s->col_out2nd[2].v2;
00491          s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
00492          s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
00493          v1 = s->row_out2nd[2].v2;
00494          s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
00495          s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
00496          v1 = s->col_out2nd[3].v2;
00497          s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
00498          s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
00499          v1 = s->row_out2nd[3].v2;
00500          s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
00501          s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
00502 #ifdef FAX_DETECT
00503          /* Update fax tone */            
00504          v1 = s->fax_tone.v2;
00505          s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
00506          s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
00507 #endif /* FAX_DETECT */
00508 #endif
00509       }
00510 #endif
00511       s->current_sample += (limit - sample);
00512       if (s->current_sample < 102) {
00513          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00514             /* If we had a hit last time, go ahead and clear this out since likely it
00515                will be another hit */
00516             for (i=sample;i<limit;i++) 
00517                amp[i] = 0;
00518             *writeback = 1;
00519          }
00520          continue;
00521       }
00522 #ifdef FAX_DETECT
00523       /* Detect the fax energy, too */
00524       fax_energy = goertzel_result(&s->fax_tone);
00525 #endif
00526       /* We are at the end of a DTMF detection block */
00527       /* Find the peak row and the peak column */
00528       row_energy[0] = goertzel_result (&s->row_out[0]);
00529       col_energy[0] = goertzel_result (&s->col_out[0]);
00530 
00531       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00532          row_energy[i] = goertzel_result (&s->row_out[i]);
00533          if (row_energy[i] > row_energy[best_row])
00534             best_row = i;
00535          col_energy[i] = goertzel_result (&s->col_out[i]);
00536          if (col_energy[i] > col_energy[best_col])
00537             best_col = i;
00538       }
00539       hit = 0;
00540       /* Basic signal level test and the twist test */
00541       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00542           col_energy[best_col] >= DTMF_THRESHOLD &&
00543           col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
00544           col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
00545          /* Relative peak test */
00546          for (i = 0;  i < 4;  i++) {
00547             if ((i != best_col &&
00548                 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00549                 (i != best_row 
00550                  && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00551                break;
00552             }
00553          }
00554 #ifdef OLD_DSP_ROUTINES
00555          /* ... and second harmonic test */
00556          if (i >= 4 && 
00557              (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
00558                       goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
00559              && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
00560 #else
00561          /* ... and fraction of total energy test */
00562          if (i >= 4 &&
00563              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
00564 #endif
00565             /* Got a hit */
00566             hit = dtmf_positions[(best_row << 2) + best_col];
00567             if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00568                /* Zero out frame data if this is part DTMF */
00569                for (i=sample;i<limit;i++) 
00570                   amp[i] = 0;
00571                *writeback = 1;
00572             }
00573             /* Look for two successive similar results */
00574             /* The logic in the next test is:
00575                We need two successive identical clean detects, with
00576                something different preceeding it. This can work with
00577                back to back differing digits. More importantly, it
00578                can work with nasty phones that give a very wobbly start
00579                to a digit */
00580 #ifdef OLD_DSP_ROUTINES
00581             if (hit == s->hit3  &&  s->hit3 != s->hit2) {
00582                s->mhit = hit;
00583                s->digit_hits[(best_row << 2) + best_col]++;
00584                s->detected_digits++;
00585                if (s->current_digits < MAX_DTMF_DIGITS) {
00586                   s->digits[s->current_digits++] = hit;
00587                   s->digits[s->current_digits] = '\0';
00588                } else {
00589                   s->lost_digits++;
00590                }
00591             }
00592 #else          
00593             if (hit == s->hits[2]  &&  hit != s->hits[1]  &&  hit != s->hits[0]) {
00594                s->mhit = hit;
00595                s->digit_hits[(best_row << 2) + best_col]++;
00596                s->detected_digits++;
00597                if (s->current_digits < MAX_DTMF_DIGITS) {
00598                   s->digits[s->current_digits++] = hit;
00599                   s->digits[s->current_digits] = '\0';
00600                } else {
00601                   s->lost_digits++;
00602                }
00603             }
00604 #endif
00605          }
00606       } 
00607 #ifdef FAX_DETECT
00608       if (!hit && (fax_energy >= FAX_THRESHOLD) && 
00609          (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
00610          (faxdetect)) {
00611 #if 0
00612          printf("Fax energy/Second Harmonic: %f\n", fax_energy);
00613 #endif               
00614          /* XXX Probably need better checking than just this the energy XXX */
00615          hit = 'f';
00616          s->fax_hits++;
00617       } else {
00618          if (s->fax_hits > 5) {
00619             hit = 'f';
00620             s->mhit = 'f';
00621             s->detected_digits++;
00622             if (s->current_digits < MAX_DTMF_DIGITS) {
00623                s->digits[s->current_digits++] = hit;
00624                s->digits[s->current_digits] = '\0';
00625             } else {
00626                s->lost_digits++;
00627             }
00628          }
00629          s->fax_hits = 0;
00630       }
00631 #endif /* FAX_DETECT */
00632 #ifdef OLD_DSP_ROUTINES
00633       s->hit1 = s->hit2;
00634       s->hit2 = s->hit3;
00635       s->hit3 = hit;
00636 #else
00637       s->hits[0] = s->hits[1];
00638       s->hits[1] = s->hits[2];
00639       s->hits[2] = hit;
00640 #endif      
00641       /* Reinitialise the detector for the next block */
00642       for (i = 0;  i < 4;  i++) {
00643          goertzel_reset(&s->row_out[i]);
00644          goertzel_reset(&s->col_out[i]);
00645 #ifdef OLD_DSP_ROUTINES
00646          goertzel_reset(&s->row_out2nd[i]);
00647          goertzel_reset(&s->col_out2nd[i]);
00648 #endif         
00649       }
00650 #ifdef FAX_DETECT
00651       goertzel_reset (&s->fax_tone);
00652 #ifdef OLD_DSP_ROUTINES
00653       goertzel_reset (&s->fax_tone2nd);
00654 #endif         
00655 #endif
00656       s->energy = 0.0;
00657       s->current_sample = 0;
00658    }
00659    if ((!s->mhit) || (s->mhit != hit)) {
00660       s->mhit = 0;
00661       return(0);
00662    }
00663    return (hit);
00664 }
00665 
00666 /* MF goertzel size */
00667 #ifdef OLD_DSP_ROUTINES
00668 #define  MF_GSIZE 160
00669 #else
00670 #define MF_GSIZE 120
00671 #endif
00672 
00673 static int mf_detect (mf_detect_state_t *s, int16_t amp[],
00674                  int samples, int digitmode, int *writeback)
00675 {
00676 #ifdef OLD_DSP_ROUTINES
00677    float tone_energy[6];
00678    int best1;
00679    int best2;
00680    float max;
00681    int sofarsogood;
00682 #else
00683    float energy[6];
00684    int best;
00685    int second_best;
00686 #endif
00687    float famp;
00688    float v1;
00689    int i;
00690    int j;
00691    int sample;
00692    int hit;
00693    int limit;
00694 
00695    hit = 0;
00696    for (sample = 0;  sample < samples;  sample = limit) {
00697       /* 80 is optimised to meet the MF specs. */
00698       if ((samples - sample) >= (MF_GSIZE - s->current_sample))
00699          limit = sample + (MF_GSIZE - s->current_sample);
00700       else
00701          limit = samples;
00702 #if defined(USE_3DNOW)
00703       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00704       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00705 #ifdef OLD_DSP_ROUTINES
00706       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00707       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00708 #endif
00709       /* XXX Need to fax detect for 3dnow too XXX */
00710       #warning "Fax Support Broken"
00711 #else
00712       /* The following unrolled loop takes only 35% (rough estimate) of the 
00713          time of a rolled loop on the machine on which it was developed */
00714       for (j = sample;  j < limit;  j++) {
00715          famp = amp[j];
00716 #ifdef OLD_DSP_ROUTINES
00717          s->energy += famp*famp;
00718 #endif
00719          /* With GCC 2.95, the following unrolled code seems to take about 35%
00720             (rough estimate) as long as a neat little 0-3 loop */
00721          v1 = s->tone_out[0].v2;
00722          s->tone_out[0].v2 = s->tone_out[0].v3;
00723          s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
00724          v1 = s->tone_out[1].v2;
00725          s->tone_out[1].v2 = s->tone_out[1].v3;
00726          s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
00727          v1 = s->tone_out[2].v2;
00728          s->tone_out[2].v2 = s->tone_out[2].v3;
00729          s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
00730          v1 = s->tone_out[3].v2;
00731          s->tone_out[3].v2 = s->tone_out[3].v3;
00732          s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
00733          v1 = s->tone_out[4].v2;
00734          s->tone_out[4].v2 = s->tone_out[4].v3;
00735          s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
00736          v1 = s->tone_out[5].v2;
00737          s->tone_out[5].v2 = s->tone_out[5].v3;
00738          s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
00739 #ifdef OLD_DSP_ROUTINES
00740          v1 = s->tone_out2nd[0].v2;
00741          s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
00742          s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
00743          v1 = s->tone_out2nd[1].v2;
00744          s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
00745          s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
00746          v1 = s->tone_out2nd[2].v2;
00747          s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
00748          s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
00749          v1 = s->tone_out2nd[3].v2;
00750          s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
00751          s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
00752          v1 = s->tone_out2nd[4].v2;
00753          s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
00754          s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
00755          v1 = s->tone_out2nd[3].v2;
00756          s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
00757          s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
00758 #endif
00759       }
00760 #endif
00761       s->current_sample += (limit - sample);
00762       if (s->current_sample < MF_GSIZE) {
00763          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00764             /* If we had a hit last time, go ahead and clear this out since likely it
00765                will be another hit */
00766             for (i=sample;i<limit;i++) 
00767                amp[i] = 0;
00768             *writeback = 1;
00769          }
00770          continue;
00771       }
00772 #ifdef OLD_DSP_ROUTINES    
00773       /* We're at the end of an MF detection block.  Go ahead and calculate
00774          all the energies. */
00775       for (i=0;i<6;i++) {
00776          tone_energy[i] = goertzel_result(&s->tone_out[i]);
00777       }
00778       /* Find highest */
00779       best1 = 0;
00780       max = tone_energy[0];
00781       for (i=1;i<6;i++) {
00782          if (tone_energy[i] > max) {
00783             max = tone_energy[i];
00784             best1 = i;
00785          }
00786       }
00787 
00788       /* Find 2nd highest */
00789       if (best1) {
00790          max = tone_energy[0];
00791          best2 = 0;
00792       } else {
00793          max = tone_energy[1];
00794          best2 = 1;
00795       }
00796 
00797       for (i=0;i<6;i++) {
00798          if (i == best1) continue;
00799          if (tone_energy[i] > max) {
00800             max = tone_energy[i];
00801             best2 = i;
00802          }
00803       }
00804       hit = 0;
00805       if (best1 != best2) 
00806          sofarsogood=1;
00807       else 
00808          sofarsogood=0;
00809       /* Check for relative energies */
00810       for (i=0;i<6;i++) {
00811          if (i == best1) 
00812             continue;
00813          if (i == best2) 
00814             continue;
00815          if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
00816             sofarsogood = 0;
00817             break;
00818          }
00819          if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
00820             sofarsogood = 0;
00821             break;
00822          }
00823       }
00824       
00825       if (sofarsogood) {
00826          /* Check for 2nd harmonic */
00827          if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 
00828             sofarsogood = 0;
00829          else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
00830             sofarsogood = 0;
00831       }
00832       if (sofarsogood) {
00833          hit = mf_hit[best1][best2];
00834          if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00835             /* Zero out frame data if this is part DTMF */
00836             for (i=sample;i<limit;i++) 
00837                amp[i] = 0;
00838             *writeback = 1;
00839          }
00840          /* Look for two consecutive clean hits */
00841          if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
00842             s->mhit = hit;
00843             s->detected_digits++;
00844             if (s->current_digits < MAX_DTMF_DIGITS - 2) {
00845                s->digits[s->current_digits++] = hit;
00846                s->digits[s->current_digits] = '\0';
00847             } else {
00848                s->lost_digits++;
00849             }
00850          }
00851       }
00852       
00853       s->hit1 = s->hit2;
00854       s->hit2 = s->hit3;
00855       s->hit3 = hit;
00856       /* Reinitialise the detector for the next block */
00857       for (i = 0;  i < 6;  i++) {
00858          goertzel_reset(&s->tone_out[i]);
00859          goertzel_reset(&s->tone_out2nd[i]);
00860       }
00861       s->energy = 0.0;
00862       s->current_sample = 0;
00863    }
00864 #else
00865       /* We're at the end of an MF detection block.  */
00866       /* Find the two highest energies. The spec says to look for
00867          two tones and two tones only. Taking this literally -ie
00868          only two tones pass the minimum threshold - doesn't work
00869          well. The sinc function mess, due to rectangular windowing
00870          ensure that! Find the two highest energies and ensure they
00871          are considerably stronger than any of the others. */
00872       energy[0] = goertzel_result(&s->tone_out[0]);
00873       energy[1] = goertzel_result(&s->tone_out[1]);
00874       if (energy[0] > energy[1]) {
00875          best = 0;
00876          second_best = 1;
00877       } else {
00878          best = 1;
00879          second_best = 0;
00880       }
00881       /*endif*/
00882       for (i=2;i<6;i++) {
00883          energy[i] = goertzel_result(&s->tone_out[i]);
00884          if (energy[i] >= energy[best]) {
00885             second_best = best;
00886             best = i;
00887          } else if (energy[i] >= energy[second_best]) {
00888             second_best = i;
00889          }
00890       }
00891       /* Basic signal level and twist tests */
00892       hit = 0;
00893       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00894                && energy[best] < energy[second_best]*BELL_MF_TWIST
00895                && energy[best]*BELL_MF_TWIST > energy[second_best]) {
00896          /* Relative peak test */
00897          hit = -1;
00898          for (i=0;i<6;i++) {
00899             if (i != best && i != second_best) {
00900                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00901                   /* The best two are not clearly the best */
00902                   hit = 0;
00903                   break;
00904                }
00905             }
00906          }
00907       }
00908       if (hit) {
00909          /* Get the values into ascending order */
00910          if (second_best < best) {
00911             i = best;
00912             best = second_best;
00913             second_best = i;
00914          }
00915          best = best*5 + second_best - 1;
00916          hit = bell_mf_positions[best];
00917          /* Look for two successive similar results */
00918          /* The logic in the next test is:
00919             For KP we need 4 successive identical clean detects, with
00920             two blocks of something different preceeding it. For anything
00921             else we need two successive identical clean detects, with
00922             two blocks of something different preceeding it. */
00923          if (hit == s->hits[4] && hit == s->hits[3] &&
00924             ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
00925              (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 
00926              hit != s->hits[0]))) {
00927             s->detected_digits++;
00928             if (s->current_digits < MAX_DTMF_DIGITS) {
00929                s->digits[s->current_digits++] = hit;
00930                s->digits[s->current_digits] = '\0';
00931             } else {
00932                s->lost_digits++;
00933             }
00934          }
00935       } else {
00936          hit = 0;
00937       }
00938       s->hits[0] = s->hits[1];
00939       s->hits[1] = s->hits[2];
00940       s->hits[2] = s->hits[3];
00941       s->hits[3] = s->hits[4];
00942       s->hits[4] = hit;
00943       /* Reinitialise the detector for the next block */
00944       for (i = 0;  i < 6;  i++)
00945          goertzel_reset(&s->tone_out[i]);
00946       s->current_sample = 0;
00947    }
00948 #endif   
00949    if ((!s->mhit) || (s->mhit != hit)) {
00950       s->mhit = 0;
00951       return(0);
00952    }
00953    return (hit);
00954 }
00955 
00956 static int __ast_dsp_digitdetect(struct ast_dsp *dsp, short *s, int len, int *writeback)
00957 {
00958    int res;
00959    
00960    if (dsp->digitmode & DSP_DIGITMODE_MF)
00961       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00962    else
00963       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
00964    return res;
00965 }
00966 
00967 int ast_dsp_digitdetect(struct ast_dsp *dsp, struct ast_frame *inf)
00968 {
00969    short *s;
00970    int len;
00971    int ign=0;
00972 
00973    if (inf->frametype != AST_FRAME_VOICE) {
00974       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
00975       return 0;
00976    }
00977    if (inf->subclass != AST_FORMAT_SLINEAR) {
00978       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
00979       return 0;
00980    }
00981    s = inf->data;
00982    len = inf->datalen / 2;
00983    return __ast_dsp_digitdetect(dsp, s, len, &ign);
00984 }
00985 
00986 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
00987 {
00988    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00989    /* Make sure absolute levels are high enough */
00990    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
00991       return 0;
00992    /* Amplify ignored stuff */
00993    i2 *= TONE_THRESH;
00994    i1 *= TONE_THRESH;
00995    e *= TONE_THRESH;
00996    /* Check first tone */
00997    if ((p1 < i1) || (p1 < i2) || (p1 < e))
00998       return 0;
00999    /* And second */
01000    if ((p2 < i1) || (p2 < i2) || (p2 < e))
01001       return 0;
01002    /* Guess it's there... */
01003    return 1;
01004 }
01005 
01006 int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
01007 {
01008    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01009       if (max > dsp->td.mf.current_digits)
01010          max = dsp->td.mf.current_digits;
01011       if (max > 0) {
01012          memcpy(buf, dsp->td.mf.digits, max);
01013          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01014          dsp->td.mf.current_digits -= max;
01015       }
01016       buf[max] = '\0';
01017       return  max;
01018    } else {
01019       if (max > dsp->td.dtmf.current_digits)
01020          max = dsp->td.dtmf.current_digits;
01021       if (max > 0) {
01022          memcpy (buf, dsp->td.dtmf.digits, max);
01023          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01024          dsp->td.dtmf.current_digits -= max;
01025       }
01026       buf[max] = '\0';
01027       return  max;
01028    }
01029 }
01030 
01031 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
01032 {
01033    int x;
01034    int y;
01035    int pass;
01036    int newstate = DSP_TONE_STATE_SILENCE;
01037    int res = 0;
01038    int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH;
01039    while(len) {
01040       /* Take the lesser of the number of samples we need and what we have */
01041       pass = len;
01042       if (pass > dsp->gsamp_size - dsp->gsamps) 
01043          pass = dsp->gsamp_size - dsp->gsamps;
01044       for (x=0;x<pass;x++) {
01045          for (y=0;y<dsp->freqcount;y++) 
01046             goertzel_sample(&dsp->freqs[y], s[x]);
01047          dsp->genergy += s[x] * s[x];
01048       }
01049       s += pass;
01050       dsp->gsamps += pass;
01051       len -= pass;
01052       if (dsp->gsamps == dsp->gsamp_size) {
01053          float hz[7];
01054          for (y=0;y<7;y++)
01055             hz[y] = goertzel_result(&dsp->freqs[y]);
01056 #if 0
01057          printf("\n350:     425:     440:     480:     620:     950:     1400:    1800:    Energy:   \n");
01058          printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 
01059             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);
01060 #endif
01061          switch(dsp->progmode) {
01062          case PROG_MODE_NA:
01063             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
01064                newstate = DSP_TONE_STATE_BUSY;
01065             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01066                newstate = DSP_TONE_STATE_RINGING;
01067             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01068                newstate = DSP_TONE_STATE_DIALTONE;
01069             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01070                newstate = DSP_TONE_STATE_SPECIAL1;
01071             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01072                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
01073                   newstate = DSP_TONE_STATE_SPECIAL2;
01074             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01075                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
01076                   newstate = DSP_TONE_STATE_SPECIAL3;
01077             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01078                newstate = DSP_TONE_STATE_TALKING;
01079             } else
01080                newstate = DSP_TONE_STATE_SILENCE;
01081             break;
01082          case PROG_MODE_CR:
01083             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01084                newstate = DSP_TONE_STATE_RINGING;
01085             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01086                newstate = DSP_TONE_STATE_TALKING;
01087             } else
01088                newstate = DSP_TONE_STATE_SILENCE;
01089             break;
01090          case PROG_MODE_UK:
01091             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
01092                newstate = DSP_TONE_STATE_HUNGUP;
01093             }
01094             break;
01095          default:
01096             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01097          }
01098          if (newstate == dsp->tstate) {
01099             dsp->tcount++;
01100             if (dsp->tcount == thresh) {
01101                if ((dsp->features & DSP_PROGRESS_BUSY) && 
01102                    dsp->tstate == DSP_TONE_STATE_BUSY) {
01103                   res = AST_CONTROL_BUSY;
01104                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01105                } else if ((dsp->features & DSP_PROGRESS_TALK) && 
01106                      dsp->tstate == DSP_TONE_STATE_TALKING) {
01107                   res = AST_CONTROL_ANSWER;
01108                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01109                } else if ((dsp->features & DSP_PROGRESS_RINGING) && 
01110                      dsp->tstate == DSP_TONE_STATE_RINGING)
01111                   res = AST_CONTROL_RINGING;
01112                else if ((dsp->features & DSP_PROGRESS_CONGESTION) && 
01113                    dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01114                   res = AST_CONTROL_CONGESTION;
01115                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01116                } else if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01117                   dsp->tstate == DSP_TONE_STATE_HUNGUP) {
01118                   res = AST_CONTROL_HANGUP;
01119                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01120                }
01121             }
01122          } else {
01123 #if 0
01124             printf("Newstate: %d\n", newstate);
01125 #endif
01126             dsp->tstate = newstate;
01127             dsp->tcount = 1;
01128          }
01129          
01130          /* Reset goertzel */                
01131          for (x=0;x<7;x++)
01132             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01133          dsp->gsamps = 0;
01134          dsp->genergy = 0.0;
01135       }
01136    }
01137 #if 0
01138    if (res)
01139       printf("Returning %d\n", res);
01140 #endif      
01141    return res;
01142 }
01143 
01144 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
01145 {
01146    if (inf->frametype != AST_FRAME_VOICE) {
01147       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01148       return 0;
01149    }
01150    if (inf->subclass != AST_FORMAT_SLINEAR) {
01151       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01152       return 0;
01153    }
01154    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01155 }
01156 
01157 static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
01158 {
01159    int accum;
01160    int x;
01161    int res = 0;
01162 
01163    if (!len)
01164       return 0;
01165    accum = 0;
01166    for (x=0;x<len; x++) 
01167       accum += abs(s[x]);
01168    accum /= len;
01169    if (accum < dsp->threshold) {
01170       /* Silent */
01171       dsp->totalsilence += len/8;
01172       if (dsp->totalnoise) {
01173          /* Move and save history */
01174          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01175          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01176 /* we don't want to check for busydetect that frequently */
01177 #if 0
01178          dsp->busymaybe = 1;
01179 #endif
01180       }
01181       dsp->totalnoise = 0;
01182       res = 1;
01183    } else {
01184       /* Not silent */
01185       dsp->totalnoise += len/8;
01186       if (dsp->totalsilence) {
01187          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01188          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01189          /* Move and save history */
01190          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01191          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01192          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01193          if (silence1 < silence2) {
01194             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01195                dsp->busymaybe = 1;
01196             else 
01197                dsp->busymaybe = 0;
01198          } else {
01199             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01200                dsp->busymaybe = 1;
01201             else 
01202                dsp->busymaybe = 0;
01203          }
01204       }
01205       dsp->totalsilence = 0;
01206    }
01207    if (totalsilence)
01208       *totalsilence = dsp->totalsilence;
01209    return res;
01210 }
01211 
01212 #ifdef BUSYDETECT_MARTIN
01213 int ast_dsp_busydetect(struct ast_dsp *dsp)
01214 {
01215    int res = 0, x;
01216 #ifndef BUSYDETECT_TONEONLY
01217    int avgsilence = 0, hitsilence = 0;
01218 #endif
01219    int avgtone = 0, hittone = 0;
01220    if (!dsp->busymaybe)
01221       return res;
01222    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01223 #ifndef BUSYDETECT_TONEONLY
01224       avgsilence += dsp->historicsilence[x];
01225 #endif
01226       avgtone += dsp->historicnoise[x];
01227    }
01228 #ifndef BUSYDETECT_TONEONLY
01229    avgsilence /= dsp->busycount;
01230 #endif
01231    avgtone /= dsp->busycount;
01232    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01233 #ifndef BUSYDETECT_TONEONLY
01234       if (avgsilence > dsp->historicsilence[x]) {
01235          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01236             hitsilence++;
01237       } else {
01238          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01239             hitsilence++;
01240       }
01241 #endif
01242       if (avgtone > dsp->historicnoise[x]) {
01243          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01244             hittone++;
01245       } else {
01246          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01247             hittone++;
01248       }
01249    }
01250 #ifndef BUSYDETECT_TONEONLY
01251    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01252        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01253        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01254 #else
01255    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01256 #endif
01257 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01258 #ifdef BUSYDETECT_TONEONLY
01259 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
01260 #endif
01261       if (avgtone > avgsilence) {
01262          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01263             res = 1;
01264       } else {
01265          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01266             res = 1;
01267       }
01268 #else
01269       res = 1;
01270 #endif
01271    }
01272    /* If we know the expected busy tone length, check we are in the range */
01273    if (res && (dsp->busy_tonelength > 0)) {
01274       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01275 #if 0
01276          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
01277                   avgtone, dsp->busy_tonelength);
01278 #endif
01279          res = 0;
01280       }
01281    }
01282 #ifndef BUSYDETECT_TONEONLY
01283    /* If we know the expected busy tone silent-period length, check we are in the range */
01284    if (res && (dsp->busy_quietlength > 0)) {
01285       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01286 #if 0
01287          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01288                   avgsilence, dsp->busy_quietlength);
01289 #endif
01290          res = 0;
01291       }
01292    }
01293 #endif
01294 #if 1
01295    if (res)
01296       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01297 #endif
01298    return res;
01299 }
01300 #endif
01301 
01302 #ifdef BUSYDETECT
01303 int ast_dsp_busydetect(struct ast_dsp *dsp)
01304 {
01305    int x;
01306    int res = 0;
01307    int max, min;
01308 
01309 #if 0
01310    if (dsp->busy_hits > 5);
01311    return 0;
01312 #endif
01313    if (dsp->busymaybe) {
01314 #if 0
01315       printf("Maybe busy!\n");
01316 #endif      
01317       dsp->busymaybe = 0;
01318       min = 9999;
01319       max = 0;
01320       for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01321 #if 0
01322          printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
01323 #endif         
01324          if (dsp->historicsilence[x] < min)
01325             min = dsp->historicsilence[x];
01326          if (dsp->historicnoise[x] < min)
01327             min = dsp->historicnoise[x];
01328          if (dsp->historicsilence[x] > max)
01329             max = dsp->historicsilence[x];
01330          if (dsp->historicnoise[x] > max)
01331             max = dsp->historicnoise[x];
01332       }
01333       if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
01334 #if 0
01335          printf("Busy!\n");
01336 #endif         
01337          res = 1;
01338       }
01339 #if 0
01340       printf("Min: %d, max: %d\n", min, max);
01341 #endif      
01342    }
01343    return res;
01344 }
01345 #endif
01346 
01347 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
01348 {
01349    short *s;
01350    int len;
01351    
01352    if (f->frametype != AST_FRAME_VOICE) {
01353       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01354       return 0;
01355    }
01356    if (f->subclass != AST_FORMAT_SLINEAR) {
01357       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01358       return 0;
01359    }
01360    s = f->data;
01361    len = f->datalen/2;
01362    return __ast_dsp_silence(dsp, s, len, totalsilence);
01363 }
01364 
01365 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
01366 {
01367    int silence;
01368    int res;
01369    int digit;
01370    int x;
01371    short *shortdata;
01372    unsigned char *odata;
01373    int len;
01374    int writeback = 0;
01375 
01376 #define FIX_INF(inf) do { \
01377       if (writeback) { \
01378          switch(inf->subclass) { \
01379          case AST_FORMAT_SLINEAR: \
01380             break; \
01381          case AST_FORMAT_ULAW: \
01382             for (x=0;x<len;x++) \
01383                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01384             break; \
01385          case AST_FORMAT_ALAW: \
01386             for (x=0;x<len;x++) \
01387                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01388             break; \
01389          } \
01390       } \
01391    } while(0) 
01392 
01393    if (!af)
01394       return NULL;
01395    if (af->frametype != AST_FRAME_VOICE)
01396       return af;
01397    odata = af->data;
01398    len = af->datalen;
01399    /* Make sure we have short data */
01400    switch(af->subclass) {
01401    case AST_FORMAT_SLINEAR:
01402       shortdata = af->data;
01403       len = af->datalen / 2;
01404       break;
01405    case AST_FORMAT_ULAW:
01406       shortdata = alloca(af->datalen * 2);
01407       if (!shortdata) {
01408          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01409          return af;
01410       }
01411       for (x=0;x<len;x++) 
01412          shortdata[x] = AST_MULAW(odata[x]);
01413       break;
01414    case AST_FORMAT_ALAW:
01415       shortdata = alloca(af->datalen * 2);
01416       if (!shortdata) {
01417          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01418          return af;
01419       }
01420       for (x=0;x<len;x++) 
01421          shortdata[x] = AST_ALAW(odata[x]);
01422       break;
01423    default:
01424       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01425       return af;
01426    }
01427    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01428    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01429       memset(&dsp->f, 0, sizeof(dsp->f));
01430       dsp->f.frametype = AST_FRAME_NULL;
01431       return &dsp->f;
01432    }
01433    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01434       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01435       memset(&dsp->f, 0, sizeof(dsp->f));
01436       dsp->f.frametype = AST_FRAME_CONTROL;
01437       dsp->f.subclass = AST_CONTROL_BUSY;
01438       ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01439       return &dsp->f;
01440    }
01441    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01442       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01443 #if 0
01444       if (digit)
01445          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01446 #endif         
01447       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01448          if (!dsp->thinkdigit) {
01449             if (digit) {
01450                /* Looks like we might have something.  
01451                 * Request a conference mute for the moment */
01452                memset(&dsp->f, 0, sizeof(dsp->f));
01453                dsp->f.frametype = AST_FRAME_DTMF;
01454                dsp->f.subclass = 'm';
01455                dsp->thinkdigit = 'x';
01456                FIX_INF(af);
01457                if (chan)
01458                   ast_queue_frame(chan, af);
01459                ast_frfree(af);
01460                return &dsp->f;
01461             }
01462          } else {
01463             if (digit) {
01464                /* Thought we saw one last time.  Pretty sure we really have now */
01465                if (dsp->thinkdigit) {
01466                   if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01467                      /* If we found a digit, and we're changing digits, go
01468                         ahead and send this one, but DON'T stop confmute because
01469                         we're detecting something else, too... */
01470                      memset(&dsp->f, 0, sizeof(dsp->f));
01471                      dsp->f.frametype = AST_FRAME_DTMF;
01472                      dsp->f.subclass = dsp->thinkdigit;
01473                      FIX_INF(af);
01474                      if (chan)
01475                         ast_queue_frame(chan, af);
01476                      ast_frfree(af);
01477                   }
01478                   dsp->thinkdigit = digit;
01479                   return &dsp->f;
01480                }
01481                dsp->thinkdigit = digit;
01482             } else {
01483                if (dsp->thinkdigit) {
01484                   memset(&dsp->f, 0, sizeof(dsp->f));
01485                   if (dsp->thinkdigit != 'x') {
01486                      /* If we found a digit, send it now */
01487                      dsp->f.frametype = AST_FRAME_DTMF;
01488                      dsp->f.subclass = dsp->thinkdigit;
01489                      dsp->thinkdigit = 0;
01490                   } else {
01491                      dsp->f.frametype = AST_FRAME_DTMF;
01492                      dsp->f.subclass = 'u';
01493                      dsp->thinkdigit = 0;
01494                   }
01495                   FIX_INF(af);
01496                   if (chan)
01497                      ast_queue_frame(chan, af);
01498                   ast_frfree(af);
01499                   return &dsp->f;
01500                }
01501             }
01502          }
01503       } else if (!digit) {
01504          /* Only check when there is *not* a hit... */
01505          if (dsp->digitmode & DSP_DIGITMODE_MF) {
01506             if (dsp->td.mf.current_digits) {
01507                memset(&dsp->f, 0, sizeof(dsp->f));
01508                dsp->f.frametype = AST_FRAME_DTMF;
01509                dsp->f.subclass = dsp->td.mf.digits[0];
01510                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01511                dsp->td.mf.current_digits--;
01512                FIX_INF(af);
01513                if (chan)
01514                   ast_queue_frame(chan, af);
01515                ast_frfree(af);
01516                return &dsp->f;
01517             }
01518          } else {
01519             if (dsp->td.dtmf.current_digits) {
01520                memset(&dsp->f, 0, sizeof(dsp->f));
01521                dsp->f.frametype = AST_FRAME_DTMF;
01522                dsp->f.subclass = dsp->td.dtmf.digits[0];
01523                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01524                dsp->td.dtmf.current_digits--;
01525                FIX_INF(af);
01526                if (chan)
01527                   ast_queue_frame(chan, af);
01528                ast_frfree(af);
01529                return &dsp->f;
01530             }
01531          }
01532       }
01533    }
01534    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01535       res = __ast_dsp_call_progress(dsp, shortdata, len);
01536       if (res) {
01537          switch(res) {
01538          case AST_CONTROL_ANSWER:
01539          case AST_CONTROL_BUSY:
01540          case AST_CONTROL_RINGING:
01541          case AST_CONTROL_CONGESTION:
01542          case AST_CONTROL_HANGUP:
01543             memset(&dsp->f, 0, sizeof(dsp->f));
01544             dsp->f.frametype = AST_FRAME_CONTROL;
01545             dsp->f.subclass = res;
01546             dsp->f.src = "dsp_progress";
01547             if (chan) 
01548                ast_queue_frame(chan, &dsp->f);
01549             break;
01550          default:
01551             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01552          }
01553       }
01554    }
01555    FIX_INF(af);
01556    return af;
01557 }
01558 
01559 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
01560 {
01561    int max = 0;
01562    int x;
01563    
01564    dsp->gsamp_size = modes[dsp->progmode].size;
01565    dsp->gsamps = 0;
01566    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01567       if (modes[dsp->progmode].freqs[x]) {
01568          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01569          max = x + 1;
01570       }
01571    }
01572    dsp->freqcount = max;
01573 }
01574 
01575 struct ast_dsp *ast_dsp_new(void)
01576 {
01577    struct ast_dsp *dsp;
01578 
01579    dsp = malloc(sizeof(struct ast_dsp));
01580    if (dsp) {
01581       memset(dsp, 0, sizeof(struct ast_dsp));
01582       dsp->threshold = DEFAULT_THRESHOLD;
01583       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01584       dsp->busycount = DSP_HISTORY;
01585       /* Initialize DTMF detector */
01586       ast_dtmf_detect_init(&dsp->td.dtmf);
01587       /* Initialize initial DSP progress detect parameters */
01588       ast_dsp_prog_reset(dsp);
01589    }
01590    return dsp;
01591 }
01592 
01593 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
01594 {
01595    dsp->features = features;
01596 }
01597 
01598 void ast_dsp_free(struct ast_dsp *dsp)
01599 {
01600    free(dsp);
01601 }
01602 
01603 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
01604 {
01605    dsp->threshold = threshold;
01606 }
01607 
01608 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
01609 {
01610    if (cadences < 4)
01611       cadences = 4;
01612    if (cadences > DSP_HISTORY)
01613       cadences = DSP_HISTORY;
01614    dsp->busycount = cadences;
01615 }
01616 
01617 void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
01618 {
01619    dsp->busy_tonelength = tonelength;
01620    dsp->busy_quietlength = quietlength;
01621    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01622 }
01623 
01624 void ast_dsp_digitreset(struct ast_dsp *dsp)
01625 {
01626    int i;
01627    
01628    dsp->thinkdigit = 0;
01629    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01630       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01631       dsp->td.mf.current_digits = 0;
01632       /* Reinitialise the detector for the next block */
01633       for (i = 0;  i < 6;  i++) {
01634          goertzel_reset(&dsp->td.mf.tone_out[i]);
01635 #ifdef OLD_DSP_ROUTINES
01636          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01637 #endif         
01638       }
01639 #ifdef OLD_DSP_ROUTINES
01640       dsp->td.mf.energy = 0.0;
01641       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01642 #else
01643       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;
01644 #endif      
01645       dsp->td.mf.current_sample = 0;
01646    } else {
01647       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01648       dsp->td.dtmf.current_digits = 0;
01649       /* Reinitialise the detector for the next block */
01650       for (i = 0;  i < 4;  i++) {
01651          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01652          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01653 #ifdef OLD_DSP_ROUTINES
01654          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01655          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01656 #endif         
01657       }
01658 #ifdef FAX_DETECT
01659       goertzel_reset (&dsp->td.dtmf.fax_tone);
01660 #endif
01661 #ifdef OLD_DSP_ROUTINES
01662 #ifdef FAX_DETECT
01663       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01664 #endif
01665       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01666 #else
01667       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01668 #endif      
01669       dsp->td.dtmf.energy = 0.0;
01670       dsp->td.dtmf.current_sample = 0;
01671    }
01672 }
01673 
01674 void ast_dsp_reset(struct ast_dsp *dsp)
01675 {
01676    int x;
01677    
01678    dsp->totalsilence = 0;
01679    dsp->gsamps = 0;
01680    for (x=0;x<4;x++)
01681       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01682    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01683    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01684 }
01685 
01686 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
01687 {
01688    int new;
01689    int old;
01690    
01691    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01692    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01693    if (old != new) {
01694       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01695       if (new & DSP_DIGITMODE_MF)
01696          ast_mf_detect_init(&dsp->td.mf);
01697       else
01698          ast_dtmf_detect_init(&dsp->td.dtmf);
01699    }
01700    dsp->digitmode = digitmode;
01701    return 0;
01702 }
01703 
01704 int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
01705 {
01706    int x;
01707    
01708    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01709       if (!strcasecmp(aliases[x].name, zone)) {
01710          dsp->progmode = aliases[x].mode;
01711          ast_dsp_prog_reset(dsp);
01712          return 0;
01713       }
01714    }
01715    return -1;
01716 }
01717 
01718 int ast_dsp_get_tstate(struct ast_dsp *dsp) 
01719 {
01720    return dsp->tstate;
01721 }
01722 
01723 int ast_dsp_get_tcount(struct ast_dsp *dsp) 
01724 {
01725    return dsp->tcount;
01726 }

Generated on Mon Sep 18 09:13:16 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7