Thu Jan 28 17:35:33 2010

Asterisk developer's documentation


dsp.c

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

Generated on Thu Jan 28 17:35:33 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7