Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:53 2009

## Asterisk developer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Directories

# 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: 58388 $")
    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 #ifndef BUSYDETECT_TONEONLY
    01296    if (res)
    01297       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
    01298 #endif
    01299 #endif
    01300    return res;
    01301 }
    01302 #endif
    01303
    01304 #ifdef BUSYDETECT
    01305 int ast_dsp_busydetect(struct ast_dsp *dsp)
    01306 {
    01307    int x;
    01308    int res = 0;
    01309    int max, min;
    01310
    01311 #if 0
    01312    if (dsp->busy_hits > 5);
    01313    return 0;
    01314 #endif
    01315    if (dsp->busymaybe) {
    01316 #if 0
    01317       printf("Maybe busy!\n");
    01318 #endif
    01319       dsp->busymaybe = 0;
    01320       min = 9999;
    01321       max = 0;
    01322       for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
    01323 #if 0
    01324          printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
    01325 #endif
    01326          if (dsp->historicsilence[x] < min)
    01327             min = dsp->historicsilence[x];
    01328          if (dsp->historicnoise[x] < min)
    01329             min = dsp->historicnoise[x];
    01330          if (dsp->historicsilence[x] > max)
    01331             max = dsp->historicsilence[x];
    01332          if (dsp->historicnoise[x] > max)
    01333             max = dsp->historicnoise[x];
    01334       }
    01335       if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
    01336 #if 0
    01337          printf("Busy!\n");
    01338 #endif
    01339          res = 1;
    01340       }
    01341 #if 0
    01342       printf("Min: %d, max: %d\n", min, max);
    01343 #endif
    01344    }
    01345    return res;
    01346 }
    01347 #endif
    01348
    01349 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
    01350 {
    01351    short *s;
    01352    int len;
    01353
    01354    if (f->frametype != AST_FRAME_VOICE) {
    01355       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
    01356       return 0;
    01357    }
    01358    if (f->subclass != AST_FORMAT_SLINEAR) {
    01359       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
    01360       return 0;
    01361    }
    01362    s = f->data;
    01363    len = f->datalen/2;
    01364    return __ast_dsp_silence(dsp, s, len, totalsilence);
    01365 }
    01366
    01367 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
    01368 {
    01369    int silence;
    01370    int res;
    01371    int digit;
    01372    int x;
    01373    short *shortdata;
    01374    unsigned char *odata;
    01375    int len;
    01376    int writeback = 0;
    01377
    01378 #define FIX_INF(inf) do { \
    01379       if (writeback) { \
    01380          switch(inf->subclass) { \
    01381          case AST_FORMAT_SLINEAR: \
    01382             break; \
    01383          case AST_FORMAT_ULAW: \
    01384             for (x=0;x<len;x++) \
    01385                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
    01386             break; \
    01387          case AST_FORMAT_ALAW: \
    01388             for (x=0;x<len;x++) \
    01389                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
    01390             break; \
    01391          } \
    01392       } \
    01393    } while(0)
    01394
    01395    if (!af)
    01396       return NULL;
    01397    if (af->frametype != AST_FRAME_VOICE)
    01398       return af;
    01399    odata = af->data;
    01400    len = af->datalen;
    01401    /* Make sure we have short data */
    01402    switch(af->subclass) {
    01403    case AST_FORMAT_SLINEAR:
    01404       shortdata = af->data;
    01405       len = af->datalen / 2;
    01406       break;
    01407    case AST_FORMAT_ULAW:
    01408       shortdata = alloca(af->datalen * 2);
    01409       if (!shortdata) {
    01410          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
    01411          return af;
    01412       }
    01413       for (x=0;x<len;x++)
    01414          shortdata[x] = AST_MULAW(odata[x]);
    01415       break;
    01416    case AST_FORMAT_ALAW:
    01417       shortdata = alloca(af->datalen * 2);
    01418       if (!shortdata) {
    01419          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
    01420          return af;
    01421       }
    01422       for (x=0;x<len;x++)
    01423          shortdata[x] = AST_ALAW(odata[x]);
    01424       break;
    01425    default:
    01426       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
    01427       return af;
    01428    }
    01429    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
    01430    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
    01431       memset(&dsp->f, 0, sizeof(dsp->f));
    01432       dsp->f.frametype = AST_FRAME_NULL;
    01433       return &dsp->f;
    01434    }
    01435    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
    01436       chan->_softhangup |= AST_SOFTHANGUP_DEV;
    01437       memset(&dsp->f, 0, sizeof(dsp->f));
    01438       dsp->f.frametype = AST_FRAME_CONTROL;
    01439       dsp->f.subclass = AST_CONTROL_BUSY;
    01440       ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
    01441       return &dsp->f;
    01442    }
    01443    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
    01444       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
    01445 #if 0
    01446       if (digit)
    01447          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
    01448 #endif
    01449       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
    01450          if (!dsp->thinkdigit) {
    01451             if (digit) {
    01452                /* Looks like we might have something.
    01453                 * Request a conference mute for the moment */
    01454                memset(&dsp->f, 0, sizeof(dsp->f));
    01455                dsp->f.frametype = AST_FRAME_DTMF;
    01456                dsp->f.subclass = 'm';
    01457                dsp->thinkdigit = 'x';
    01458                FIX_INF(af);
    01459                if (chan)
    01460                   ast_queue_frame(chan, af);
    01461                ast_frfree(af);
    01462                return &dsp->f;
    01463             }
    01464          } else {
    01465             if (digit) {
    01466                /* Thought we saw one last time.  Pretty sure we really have now */
    01467                if (dsp->thinkdigit) {
    01468                   if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
    01469                      /* If we found a digit, and we're changing digits, go
    01470                         ahead and send this one, but DON'T stop confmute because
    01471                         we're detecting something else, too... */
    01472                      memset(&dsp->f, 0, sizeof(dsp->f));
    01473                      dsp->f.frametype = AST_FRAME_DTMF;
    01474                      dsp->f.subclass = dsp->thinkdigit;
    01475                      FIX_INF(af);
    01476                      if (chan)
    01477                         ast_queue_frame(chan, af);
    01478                      ast_frfree(af);
    01479                   }
    01480                   dsp->thinkdigit = digit;
    01481                   return &dsp->f;
    01482                }
    01483                dsp->thinkdigit = digit;
    01484             } else {
    01485                if (dsp->thinkdigit) {
    01486                   memset(&dsp->f, 0, sizeof(dsp->f));
    01487                   if (dsp->thinkdigit != 'x') {
    01488                      /* If we found a digit, send it now */
    01489                      dsp->f.frametype = AST_FRAME_DTMF;
    01490                      dsp->f.subclass = dsp->thinkdigit;
    01491                      dsp->thinkdigit = 0;
    01492                   } else {
    01493                      dsp->f.frametype = AST_FRAME_DTMF;
    01494                      dsp->f.subclass = 'u';
    01495                      dsp->thinkdigit = 0;
    01496                   }
    01497                   FIX_INF(af);
    01498                   if (chan)
    01499                      ast_queue_frame(chan, af);
    01500                   ast_frfree(af);
    01501                   return &dsp->f;
    01502                }
    01503             }
    01504          }
    01505       } else if (!digit) {
    01506          /* Only check when there is *not* a hit... */
    01507          if (dsp->digitmode & DSP_DIGITMODE_MF) {
    01508             if (dsp->td.mf.current_digits) {
    01509                memset(&dsp->f, 0, sizeof(dsp->f));
    01510                dsp->f.frametype = AST_FRAME_DTMF;
    01511                dsp->f.subclass = dsp->td.mf.digits[0];
    01512                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
    01513                dsp->td.mf.current_digits--;
    01514                FIX_INF(af);
    01515                if (chan)
    01516                   ast_queue_frame(chan, af);
    01517                ast_frfree(af);
    01518                return &dsp->f;
    01519             }
    01520          } else {
    01521             if (dsp->td.dtmf.current_digits) {
    01522                memset(&dsp->f, 0, sizeof(dsp->f));
    01523                dsp->f.frametype = AST_FRAME_DTMF;
    01524                dsp->f.subclass = dsp->td.dtmf.digits[0];
    01525                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
    01526                dsp->td.dtmf.current_digits--;
    01527                FIX_INF(af);
    01528                if (chan)
    01529                   ast_queue_frame(chan, af);
    01530                ast_frfree(af);
    01531                return &dsp->f;
    01532             }
    01533          }
    01534       }
    01535    }
    01536    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
    01537       res = __ast_dsp_call_progress(dsp, shortdata, len);
    01538       if (res) {
    01539          switch(res) {
    01540          case AST_CONTROL_ANSWER:
    01541          case AST_CONTROL_BUSY:
    01542          case AST_CONTROL_RINGING:
    01543          case AST_CONTROL_CONGESTION:
    01544          case AST_CONTROL_HANGUP:
    01545             memset(&dsp->f, 0, sizeof(dsp->f));
    01546             dsp->f.frametype = AST_FRAME_CONTROL;
    01547             dsp->f.subclass = res;
    01548             dsp->f.src = "dsp_progress";
    01549             if (chan)
    01550                ast_queue_frame(chan, &dsp->f);
    01551             break;
    01552          default:
    01553             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
    01554          }
    01555       }
    01556    }
    01557    FIX_INF(af);
    01558    return af;
    01559 }
    01560
    01561 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
    01562 {
    01563    int max = 0;
    01564    int x;
    01565
    01566    dsp->gsamp_size = modes[dsp->progmode].size;
    01567    dsp->gsamps = 0;
    01568    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
    01569       if (modes[dsp->progmode].freqs[x]) {
    01570          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
    01571          max = x + 1;
    01572       }
    01573    }
    01574    dsp->freqcount = max;
    01575 }
    01576
    01577 struct ast_dsp *ast_dsp_new(void)
    01578 {
    01579    struct ast_dsp *dsp;
    01580
    01581    dsp = malloc(sizeof(struct ast_dsp));
    01582    if (dsp) {
    01583       memset(dsp, 0, sizeof(struct ast_dsp));
    01584       dsp->threshold = DEFAULT_THRESHOLD;
    01585       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
    01586       dsp->busycount = DSP_HISTORY;
    01587       /* Initialize DTMF detector */
    01588       ast_dtmf_detect_init(&dsp->td.dtmf);
    01589       /* Initialize initial DSP progress detect parameters */
    01590       ast_dsp_prog_reset(dsp);
    01591    }
    01592    return dsp;
    01593 }
    01594
    01595 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
    01596 {
    01597    dsp->features = features;
    01598 }
    01599
    01600 void ast_dsp_free(struct ast_dsp *dsp)
    01601 {
    01602    free(dsp);
    01603 }
    01604
    01605 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
    01606 {
    01607    dsp->threshold = threshold;
    01608 }
    01609
    01610 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
    01611 {
    01612    if (cadences < 4)
    01613       cadences = 4;
    01614    if (cadences > DSP_HISTORY)
    01615       cadences = DSP_HISTORY;
    01616    dsp->busycount = cadences;
    01617 }
    01618
    01619 void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
    01620 {
    01621    dsp->busy_tonelength = tonelength;
    01622    dsp->busy_quietlength = quietlength;
    01623    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
    01624 }
    01625
    01626 void ast_dsp_digitreset(struct ast_dsp *dsp)
    01627 {
    01628    int i;
    01629
    01630    dsp->thinkdigit = 0;
    01631    if (dsp->digitmode & DSP_DIGITMODE_MF) {
    01632       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
    01633       dsp->td.mf.current_digits = 0;
    01634       /* Reinitialise the detector for the next block */
    01635       for (i = 0;  i < 6;  i++) {
    01636          goertzel_reset(&dsp->td.mf.tone_out[i]);
    01637 #ifdef OLD_DSP_ROUTINES
    01638          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
    01639 #endif
    01640       }
    01641 #ifdef OLD_DSP_ROUTINES
    01642       dsp->td.mf.energy = 0.0;
    01643       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
    01644 #else
    01645       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;
    01646 #endif
    01647       dsp->td.mf.current_sample = 0;
    01648    } else {
    01649       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
    01650       dsp->td.dtmf.current_digits = 0;
    01651       /* Reinitialise the detector for the next block */
    01652       for (i = 0;  i < 4;  i++) {
    01653          goertzel_reset(&dsp->td.dtmf.row_out[i]);
    01654          goertzel_reset(&dsp->td.dtmf.col_out[i]);
    01655 #ifdef OLD_DSP_ROUTINES
    01656          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
    01657          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
    01658 #endif
    01659       }
    01660 #ifdef FAX_DETECT
    01661       goertzel_reset (&dsp->td.dtmf.fax_tone);
    01662 #endif
    01663 #ifdef OLD_DSP_ROUTINES
    01664 #ifdef FAX_DETECT
    01665       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
    01666 #endif
    01667       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
    01668 #else
    01669       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
    01670 #endif
    01671       dsp->td.dtmf.energy = 0.0;
    01672       dsp->td.dtmf.current_sample = 0;
    01673    }
    01674 }
    01675
    01676 void ast_dsp_reset(struct ast_dsp *dsp)
    01677 {
    01678    int x;
    01679
    01680    dsp->totalsilence = 0;
    01681    dsp->gsamps = 0;
    01682    for (x=0;x<4;x++)
    01683       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
    01684    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
    01685    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
    01686 }
    01687
    01688 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
    01689 {
    01690    int new;
    01691    int old;
    01692
    01693    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
    01694    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
    01695    if (old != new) {
    01696       /* Must initialize structures if switching from MF to DTMF or vice-versa */
    01697       if (new & DSP_DIGITMODE_MF)
    01698          ast_mf_detect_init(&dsp->td.mf);
    01699       else
    01700          ast_dtmf_detect_init(&dsp->td.dtmf);
    01701    }
    01702    dsp->digitmode = digitmode;
    01703    return 0;
    01704 }
    01705
    01706 int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
    01707 {
    01708    int x;
    01709
    01710    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
    01711       if (!strcasecmp(aliases[x].name, zone)) {
    01712          dsp->progmode = aliases[x].mode;
    01713          ast_dsp_prog_reset(dsp);
    01714          return 0;
    01715       }
    01716    }
    01717    return -1;
    01718 }
    01719
    01720 int ast_dsp_get_tstate(struct ast_dsp *dsp)
    01721 {
    01722    return dsp->tstate;
    01723 }
    01724
    01725 int ast_dsp_get_tcount(struct ast_dsp *dsp)
    01726 {
    01727    return dsp->tcount;
    01728 }