Wed Apr 6 11:29:44 2011

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: 268690 $")
00046 
00047 #include <math.h>
00048 
00049 #include "asterisk/frame.h"
00050 #include "asterisk/channel.h"
00051 #include "asterisk/dsp.h"
00052 #include "asterisk/ulaw.h"
00053 #include "asterisk/alaw.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/options.h"
00056 #include "asterisk/config.h"
00057 
00058 /*! Number of goertzels for progress detect */
00059 enum gsamp_size {
00060    GSAMP_SIZE_NA = 183,       /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
00061    GSAMP_SIZE_CR = 188,       /*!< Costa Rica, Brazil - Only care about 425 Hz */
00062    GSAMP_SIZE_UK = 160        /*!< UK disconnect goertzel feed - should trigger 400hz */
00063 };
00064 
00065 enum prog_mode {
00066    PROG_MODE_NA = 0,
00067    PROG_MODE_CR,
00068    PROG_MODE_UK
00069 };
00070 
00071 enum freq_index { 
00072    /*! For US modes { */
00073    HZ_350 = 0,
00074    HZ_440,
00075    HZ_480,
00076    HZ_620,
00077    HZ_950,
00078    HZ_1400,
00079    HZ_1800, /*!< } */
00080 
00081    /*! For CR/BR modes */
00082    HZ_425 = 0,
00083 
00084    /*! For UK mode */
00085    HZ_350UK = 0,
00086    HZ_400UK,
00087    HZ_440UK
00088 };
00089 
00090 static struct progalias {
00091    char *name;
00092    enum prog_mode mode;
00093 } aliases[] = {
00094    { "us", PROG_MODE_NA },
00095    { "ca", PROG_MODE_NA },
00096    { "cr", PROG_MODE_CR },
00097    { "br", PROG_MODE_CR },
00098    { "uk", PROG_MODE_UK },
00099 };
00100 
00101 static struct progress {
00102    enum gsamp_size size;
00103    int freqs[7];
00104 } modes[] = {
00105    { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */
00106    { GSAMP_SIZE_CR, { 425 } },                                 /*!< Costa Rica, Brazil */
00107    { GSAMP_SIZE_UK, { 350, 400, 440 } },                                   /*!< UK */
00108 };
00109 
00110 /*!\brief This value is the minimum threshold, calculated by averaging all
00111  * of the samples within a frame, for which a frame is determined to either
00112  * be silence (below the threshold) or noise (above the threshold).  Please
00113  * note that while the default threshold is an even exponent of 2, there is
00114  * no requirement that it be so.  The threshold will accept any value between
00115  * 0 and 32767.
00116  */
00117 #define DEFAULT_THRESHOLD  512
00118 
00119 enum busy_detect {
00120    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last tone periods */
00121    BUSY_PAT_PERCENT = 8,   /*!< The percentage difference between measured and actual pattern */
00122    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00123    BUSY_MIN = 150,       /*!< Busy must be at least 150 ms in half-cadence */
00124    BUSY_MAX = 600          /*!< Busy can't be longer than 600 ms in half-cadence */
00125 };
00126 
00127 /*! Remember last 15 units */
00128 #define DSP_HISTORY     15
00129 
00130 #define TONE_THRESH     10.0  /*!< How much louder the tone should be than channel energy */
00131 #define TONE_MIN_THRESH    1e8   /*!< How much tone there should be at least to attempt */
00132 
00133 /*! All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms) */
00134 enum gsamp_thresh {
00135    THRESH_RING = 8,           /*!< Need at least 150ms ring to accept */
00136    THRESH_TALK = 2,           /*!< Talk detection does not work continuously */
00137    THRESH_BUSY = 4,           /*!< Need at least 80ms to accept */
00138    THRESH_CONGESTION = 4,     /*!< Need at least 80ms to accept */
00139    THRESH_HANGUP = 60,        /*!< Need at least 1300ms to accept hangup */
00140    THRESH_RING2ANSWER = 300   /*!< Timeout from start of ring to answer (about 6600 ms) */
00141 };
00142 
00143 #define  MAX_DTMF_DIGITS      128
00144 
00145 /* Basic DTMF specs:
00146  *
00147  * Minimum tone on = 40ms
00148  * Minimum tone off = 50ms
00149  * Maximum digit rate = 10 per second
00150  * Normal twist <= 8dB accepted
00151  * Reverse twist <= 4dB accepted
00152  * S/N >= 15dB will detect OK
00153  * Attenuation <= 26dB will detect OK
00154  * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
00155  */
00156 
00157 #define DTMF_THRESHOLD     8.0e7
00158 #define FAX_THRESHOLD      8.0e7
00159 #define FAX_2ND_HARMONIC   2.0     /* 4dB */
00160 #define DTMF_NORMAL_TWIST  6.3     /* 8dB */
00161 #ifdef   RADIO_RELAX
00162 #define DTMF_REVERSE_TWIST          (relax ? 6.5 : 2.5)     /* 4dB normal */
00163 #else
00164 #define DTMF_REVERSE_TWIST          (relax ? 4.0 : 2.5)     /* 4dB normal */
00165 #endif
00166 #define DTMF_RELATIVE_PEAK_ROW   6.3     /* 8dB */
00167 #define DTMF_RELATIVE_PEAK_COL   6.3     /* 8dB */
00168 #define DTMF_2ND_HARMONIC_ROW       (relax ? 1.7 : 2.5)     /* 4dB normal */
00169 #define DTMF_2ND_HARMONIC_COL 63.1    /* 18dB */
00170 #define DTMF_TO_TOTAL_ENERGY  42.0
00171 
00172 #define BELL_MF_THRESHOLD  1.6e9
00173 #define BELL_MF_TWIST      4.0     /* 6dB */
00174 #define BELL_MF_RELATIVE_PEAK 12.6    /* 11dB */
00175 
00176 #if defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
00177 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
00178 #endif
00179 
00180 /* The CNG signal consists of the transmission of 1100 Hz for 1/2 second,
00181  * followed by a 3 second silent (2100 Hz OFF) period.
00182  */
00183 #define FAX_TONE_CNG_FREQ  1100
00184 #define FAX_TONE_CNG_DURATION 500
00185 #define FAX_TONE_CNG_DB    16
00186 
00187 /* This signal may be sent by the Terminating FAX machine anywhere between
00188  * 1.8 to 2.5 seconds AFTER answering the call.  The CED signal consists
00189  * of a 2100 Hz tone that is from 2.6 to 4 seconds in duration.
00190 */
00191 #define FAX_TONE_CED_FREQ  2100
00192 #define FAX_TONE_CED_DURATION 2600
00193 #define FAX_TONE_CED_DB    16
00194 
00195 #define SAMPLE_RATE     8000
00196 
00197 /* How many samples a frame has.  This constant is used when calculating
00198  * Goertzel block size for tone_detect.  It is only important if we want to
00199  * remove (squelch) the tone. In this case it is important to have block
00200  * size not to exceed size of voice frame.  Otherwise by the moment the tone
00201  * is detected it is too late to squelch it from previous frames.
00202  */
00203 #define SAMPLES_IN_FRAME   160
00204 
00205 /* MF goertzel size */
00206 #define MF_GSIZE     120
00207 
00208 /* DTMF goertzel size */
00209 #define DTMF_GSIZE      102
00210 
00211 /* How many successive hits needed to consider begin of a digit */
00212 #define DTMF_HITS_TO_BEGIN 2
00213 /* How many successive misses needed to consider end of a digit */
00214 #define DTMF_MISSES_TO_END 3
00215 
00216 /*!
00217  * \brief The default silence threshold we will use if an alternate
00218  * configured value is not present or is invalid.
00219  */
00220 static const int DEFAULT_SILENCE_THRESHOLD = 256;
00221 
00222 #define CONFIG_FILE_NAME "dsp.conf"
00223 
00224 typedef struct {
00225    int v2;
00226    int v3;
00227    int chunky;
00228    int fac;
00229    int samples;
00230 } goertzel_state_t;
00231 
00232 typedef struct {
00233    int value;
00234    int power;
00235 } goertzel_result_t;
00236 
00237 typedef struct
00238 {
00239    int freq;
00240    int block_size;
00241    int squelch;      /* Remove (squelch) tone */
00242    goertzel_state_t tone;
00243    float energy;     /* Accumulated energy of the current block */
00244    int samples_pending; /* Samples remain to complete the current block */
00245    int mute_samples; /* How many additional samples needs to be muted to suppress already detected tone */
00246 
00247    int hits_required;   /* How many successive blocks with tone we are looking for */
00248    float threshold;  /* Energy of the tone relative to energy from all other signals to consider a hit */
00249 
00250    int hit_count;    /* How many successive blocks we consider tone present */
00251    int last_hit;     /* Indicates if the last processed block was a hit */
00252 
00253 } tone_detect_state_t;
00254 
00255 typedef struct
00256 {
00257    goertzel_state_t row_out[4];
00258    goertzel_state_t col_out[4];
00259    int hits_to_begin;      /* How many successive hits needed to consider begin of a digit */
00260    int misses_to_end;      /* How many successive misses needed to consider end of a digit */
00261    int hits;         /* How many successive hits we have seen already */
00262    int misses;       /* How many successive misses we have seen already */
00263    int lasthit;
00264    int current_hit;
00265    float energy;
00266    int current_sample;
00267    int mute_samples;
00268 } dtmf_detect_state_t;
00269 
00270 typedef struct
00271 {
00272    goertzel_state_t tone_out[6];
00273    int current_hit;
00274    int hits[5];
00275    int current_sample;
00276    int mute_samples;
00277 } mf_detect_state_t;
00278 
00279 typedef struct
00280 {
00281    char digits[MAX_DTMF_DIGITS + 1];
00282    int digitlen[MAX_DTMF_DIGITS + 1];
00283    int current_digits;
00284    int detected_digits;
00285    int lost_digits;
00286 
00287    union {
00288       dtmf_detect_state_t dtmf;
00289       mf_detect_state_t mf;
00290    } td;
00291 } digit_detect_state_t;
00292 
00293 static const float dtmf_row[] = {
00294    697.0,  770.0,  852.0,  941.0
00295 };
00296 static const float dtmf_col[] = {
00297    1209.0, 1336.0, 1477.0, 1633.0
00298 };
00299 static const float mf_tones[] = {
00300    700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
00301 };
00302 static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
00303 static const char bell_mf_positions[] = "1247C-358A--69*---0B----#";
00304 static int thresholds[THRESHOLD_MAX];
00305 
00306 static inline void goertzel_sample(goertzel_state_t *s, short sample)
00307 {
00308    int v1;
00309    
00310    v1 = s->v2;
00311    s->v2 = s->v3;
00312    
00313    s->v3 = (s->fac * s->v2) >> 15;
00314    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00315    if (abs(s->v3) > 32768) {
00316       s->chunky++;
00317       s->v3 = s->v3 >> 1;
00318       s->v2 = s->v2 >> 1;
00319       v1 = v1 >> 1;
00320    }
00321 }
00322 
00323 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
00324 {
00325    int i;
00326    
00327    for (i = 0; i < count; i++) {
00328       goertzel_sample(s, samps[i]);
00329    }
00330 }
00331 
00332 
00333 static inline float goertzel_result(goertzel_state_t *s)
00334 {
00335    goertzel_result_t r;
00336    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00337    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00338    r.power = s->chunky * 2;
00339    return (float)r.value * (float)(1 << r.power);
00340 }
00341 
00342 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
00343 {
00344    s->v2 = s->v3 = s->chunky = 0.0;
00345    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00346    s->samples = samples;
00347 }
00348 
00349 static inline void goertzel_reset(goertzel_state_t *s)
00350 {
00351    s->v2 = s->v3 = s->chunky = 0.0;
00352 }
00353 
00354 typedef struct {
00355    int start;
00356    int end;
00357 } fragment_t;
00358 
00359 /* Note on tone suppression (squelching). Individual detectors (DTMF/MF/generic tone)
00360  * report fragmens of the frame in which detected tone resides and which needs
00361  * to be "muted" in order to suppress the tone. To mark fragment for muting,
00362  * detectors call mute_fragment passing fragment_t there. Multiple fragments
00363  * can be marked and ast_dsp_process later will mute all of them.
00364  *
00365  * Note: When tone starts in the middle of a Goertzel block, it won't be properly
00366  * detected in that block, only in the next. If we only mute the next block
00367  * where tone is actually detected, the user will still hear beginning
00368  * of the tone in preceeding block. This is why we usually want to mute some amount
00369  * of samples preceeding and following the block where tone was detected.
00370 */
00371 
00372 struct ast_dsp {
00373    struct ast_frame f;
00374    int threshold;
00375    int totalsilence;
00376    int totalnoise;
00377    int features;
00378    int ringtimeout;
00379    int busymaybe;
00380    int busycount;
00381    int busytoneonly;
00382    int busycompare;
00383    int busy_tonelength;
00384    int busy_quietlength;
00385    int busy_pattern_fuzzy;
00386    int historicnoise[DSP_HISTORY];
00387    int historicsilence[DSP_HISTORY];
00388    goertzel_state_t freqs[7];
00389    int freqcount;
00390    int gsamps;
00391    enum gsamp_size gsamp_size;
00392    enum prog_mode progmode;
00393    int tstate;
00394    int tcount;
00395    int digitmode;
00396    int faxmode;
00397    int dtmf_began;
00398    int display_inband_dtmf_warning;
00399    float genergy;
00400    int mute_fragments;
00401    fragment_t mute_data[5];
00402    digit_detect_state_t digit_state;
00403    tone_detect_state_t cng_tone_state;
00404    tone_detect_state_t ced_tone_state;
00405 };
00406 
00407 static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
00408 {
00409    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00410       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00411       return;
00412    }
00413 
00414    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00415 }
00416 
00417 static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp)
00418 {
00419    int duration_samples;
00420    float x;
00421    int periods_in_block;
00422 
00423    s->freq = freq;
00424 
00425    /* Desired tone duration in samples */
00426    duration_samples = duration * SAMPLE_RATE / 1000;
00427    /* We want to allow 10% deviation of tone duration */
00428    duration_samples = duration_samples * 9 / 10;
00429 
00430    /* If we want to remove tone, it is important to have block size not
00431       to exceed frame size. Otherwise by the moment tone is detected it is too late
00432       to squelch it from previous frames */
00433    s->block_size = SAMPLES_IN_FRAME;
00434 
00435    periods_in_block = s->block_size * freq / SAMPLE_RATE;
00436 
00437    /* Make sure we will have at least 5 periods at target frequency for analisys.
00438       This may make block larger than expected packet and will make squelching impossible
00439       but at least we will be detecting the tone */
00440    if (periods_in_block < 5)
00441       periods_in_block = 5;
00442 
00443    /* Now calculate final block size. It will contain integer number of periods */
00444    s->block_size = periods_in_block * SAMPLE_RATE / freq;
00445 
00446    /* tone_detect is currently only used to detect fax tones and we
00447       do not need suqlching the fax tones */
00448    s->squelch = 0;
00449 
00450    /* Account for the first and the last block to be incomplete
00451       and thus no tone will be detected in them */
00452    s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
00453 
00454    goertzel_init(&s->tone, freq, s->block_size);
00455 
00456    s->samples_pending = s->block_size;
00457    s->hit_count = 0;
00458    s->last_hit = 0;
00459    s->energy = 0.0;
00460 
00461    /* We want tone energy to be amp decibels above the rest of the signal (the noise).
00462       According to Parseval's theorem the energy computed in time domain equals to energy
00463       computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
00464       from the energy in the time domain we will get energy of the remaining signal (without the tone
00465       we are detecting). We will be checking that
00466       10*log(Ew / (Et - Ew)) > amp
00467       Calculate threshold so that we will be actually checking
00468       Ew > Et * threshold
00469    */
00470 
00471    x = pow(10.0, amp / 10.0);
00472    s->threshold = x / (x + 1);
00473 
00474    ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
00475 }
00476 
00477 static void ast_fax_detect_init(struct ast_dsp *s)
00478 {
00479    ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB);
00480    ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB);
00481 }
00482 
00483 static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
00484 {
00485    int i;
00486 
00487    s->lasthit = 0;
00488    s->current_hit = 0;
00489    for (i = 0;  i < 4;  i++) {
00490       goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE);
00491       goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE);
00492       s->energy = 0.0;
00493    }
00494    s->current_sample = 0;
00495    s->hits = 0;
00496    s->misses = 0;
00497 
00498    s->hits_to_begin = DTMF_HITS_TO_BEGIN;
00499    s->misses_to_end = DTMF_MISSES_TO_END;
00500 }
00501 
00502 static void ast_mf_detect_init (mf_detect_state_t *s)
00503 {
00504    int i;
00505    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00506    for (i = 0;  i < 6;  i++) {
00507       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00508    }
00509    s->current_sample = 0;
00510    s->current_hit = 0;
00511 }
00512 
00513 static void ast_digit_detect_init(digit_detect_state_t *s, int mf)
00514 {
00515    s->current_digits = 0;
00516    s->detected_digits = 0;
00517    s->lost_digits = 0;
00518    s->digits[0] = '\0';
00519 
00520    if (mf) {
00521       ast_mf_detect_init(&s->td.mf);
00522    } else {
00523       ast_dtmf_detect_init(&s->td.dtmf);
00524    }
00525 }
00526 
00527 static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
00528 {
00529    float tone_energy;
00530    int i;
00531    int hit = 0;
00532    int limit;
00533    int res = 0;
00534    int16_t *ptr;
00535    int start, end;
00536    fragment_t mute = {0, 0};
00537 
00538    if (s->squelch && s->mute_samples > 0) {
00539       mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
00540       s->mute_samples -= mute.end;
00541    }
00542 
00543    for (start = 0;  start < samples;  start = end) {
00544       /* Process in blocks. */
00545       limit = samples - start;
00546       if (limit > s->samples_pending) {
00547          limit = s->samples_pending;
00548       }
00549       end = start + limit;
00550 
00551       for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
00552          /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */
00553          s->energy += (int32_t) *ptr * (int32_t) *ptr;
00554 
00555          goertzel_sample(&s->tone, *ptr);
00556       }
00557 
00558       s->samples_pending -= limit;
00559 
00560       if (s->samples_pending) {
00561          /* Finished incomplete (last) block */
00562          break;
00563       }
00564 
00565       tone_energy = goertzel_result(&s->tone);
00566 
00567       /* Scale to make comparable */
00568       tone_energy *= 2.0;
00569       s->energy *= s->block_size;
00570 
00571       ast_debug(10, "tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
00572       hit = 0;
00573       if (tone_energy > s->energy * s->threshold) {
00574          ast_debug(10, "Hit! count=%d\n", s->hit_count);
00575          hit = 1;
00576       }
00577 
00578       if (s->hit_count) {
00579          s->hit_count++;
00580       }
00581 
00582       if (hit == s->last_hit) {
00583          if (!hit) {
00584             /* Two successive misses. Tone ended */
00585             s->hit_count = 0;
00586          } else if (!s->hit_count) {
00587             s->hit_count++;
00588          }
00589 
00590       }
00591 
00592       if (s->hit_count == s->hits_required) {
00593          ast_debug(1, "%d Hz done detected\n", s->freq);
00594          res = 1;
00595       }
00596 
00597       s->last_hit = hit;
00598 
00599       /* If we had a hit in this block, include it into mute fragment */
00600       if (s->squelch && hit) {
00601          if (mute.end < start - s->block_size) {
00602             /* There is a gap between fragments */
00603             mute_fragment(dsp, &mute);
00604             mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
00605          }
00606          mute.end = end + s->block_size;
00607       }
00608 
00609       /* Reinitialise the detector for the next block */
00610       /* Reset for the next block */
00611       goertzel_reset(&s->tone);
00612 
00613       /* Advance to the next block */
00614       s->energy = 0.0;
00615       s->samples_pending = s->block_size;
00616 
00617       amp += limit;
00618    }
00619 
00620    if (s->squelch && mute.end) {
00621       if (mute.end > samples) {
00622          s->mute_samples = mute.end - samples;
00623          mute.end = samples;
00624       }
00625       mute_fragment(dsp, &mute);
00626    }
00627 
00628    return res;
00629 }
00630 
00631 static void store_digit(digit_detect_state_t *s, char digit)
00632 {
00633    s->detected_digits++;
00634    if (s->current_digits < MAX_DTMF_DIGITS) {
00635       s->digitlen[s->current_digits] = 0;
00636       s->digits[s->current_digits++] = digit;
00637       s->digits[s->current_digits] = '\0';
00638    } else {
00639       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00640       s->lost_digits++;
00641    }
00642 }
00643 
00644 static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
00645 {
00646    float row_energy[4];
00647    float col_energy[4];
00648    float famp;
00649    int i;
00650    int j;
00651    int sample;
00652    int best_row;
00653    int best_col;
00654    int hit;
00655    int limit;
00656    fragment_t mute = {0, 0};
00657 
00658    if (squelch && s->td.dtmf.mute_samples > 0) {
00659       mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
00660       s->td.dtmf.mute_samples -= mute.end;
00661    }
00662 
00663    hit = 0;
00664    for (sample = 0; sample < samples; sample = limit) {
00665       /* DTMF_GSIZE is optimised to meet the DTMF specs. */
00666       if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
00667          limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
00668       } else {
00669          limit = samples;
00670       }
00671       /* The following unrolled loop takes only 35% (rough estimate) of the 
00672          time of a rolled loop on the machine on which it was developed */
00673       for (j = sample; j < limit; j++) {
00674          famp = amp[j];
00675          s->td.dtmf.energy += famp*famp;
00676          /* With GCC 2.95, the following unrolled code seems to take about 35%
00677             (rough estimate) as long as a neat little 0-3 loop */
00678          goertzel_sample(s->td.dtmf.row_out, amp[j]);
00679          goertzel_sample(s->td.dtmf.col_out, amp[j]);
00680          goertzel_sample(s->td.dtmf.row_out + 1, amp[j]);
00681          goertzel_sample(s->td.dtmf.col_out + 1, amp[j]);
00682          goertzel_sample(s->td.dtmf.row_out + 2, amp[j]);
00683          goertzel_sample(s->td.dtmf.col_out + 2, amp[j]);
00684          goertzel_sample(s->td.dtmf.row_out + 3, amp[j]);
00685          goertzel_sample(s->td.dtmf.col_out + 3, amp[j]);
00686       }
00687       s->td.dtmf.current_sample += (limit - sample);
00688       if (s->td.dtmf.current_sample < DTMF_GSIZE) {
00689          continue;
00690       }
00691       /* We are at the end of a DTMF detection block */
00692       /* Find the peak row and the peak column */
00693       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00694       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00695 
00696       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00697          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00698          if (row_energy[i] > row_energy[best_row]) {
00699             best_row = i;
00700          }
00701          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00702          if (col_energy[i] > col_energy[best_col]) {
00703             best_col = i;
00704          }
00705       }
00706       hit = 0;
00707       /* Basic signal level test and the twist test */
00708       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00709           col_energy[best_col] >= DTMF_THRESHOLD &&
00710           col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST &&
00711           col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) {
00712          /* Relative peak test */
00713          for (i = 0;  i < 4;  i++) {
00714             if ((i != best_col &&
00715                 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00716                 (i != best_row 
00717                  && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00718                break;
00719             }
00720          }
00721          /* ... and fraction of total energy test */
00722          if (i >= 4 &&
00723              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
00724             /* Got a hit */
00725             hit = dtmf_positions[(best_row << 2) + best_col];
00726          }
00727       } 
00728 
00729       if (s->td.dtmf.current_hit) {
00730          /* We are in the middle of a digit already */
00731          if (hit != s->td.dtmf.current_hit) {
00732             s->td.dtmf.misses++;
00733             if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
00734                /* There were enough misses to consider digit ended */
00735                s->td.dtmf.current_hit = 0;
00736             }
00737          } else {
00738             s->td.dtmf.misses = 0;
00739             /* Current hit was same as last, so increment digit duration (of last digit) */
00740             s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
00741          }
00742       }
00743 
00744       /* Look for a start of a new digit no matter if we are already in the middle of some
00745          digit or not. This is because hits_to_begin may be smaller than misses_to_end
00746          and we may find begin of new digit before we consider last one ended. */
00747       if (hit) {
00748          if (hit == s->td.dtmf.lasthit) {
00749             s->td.dtmf.hits++;
00750          } else {
00751             s->td.dtmf.hits = 1;
00752          }
00753 
00754          if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin && hit != s->td.dtmf.current_hit) {
00755             store_digit(s, hit);
00756             s->td.dtmf.current_hit = hit;
00757             s->td.dtmf.misses = 0;
00758          }
00759       } else {
00760          s->td.dtmf.hits = 0;
00761       }
00762 
00763       s->td.dtmf.lasthit = hit;
00764 
00765       /* If we had a hit in this block, include it into mute fragment */
00766       if (squelch && hit) {
00767          if (mute.end < sample - DTMF_GSIZE) {
00768             /* There is a gap between fragments */
00769             mute_fragment(dsp, &mute);
00770             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00771          }
00772          mute.end = limit + DTMF_GSIZE;
00773       }
00774 
00775       /* Reinitialise the detector for the next block */
00776       for (i = 0; i < 4; i++) {
00777          goertzel_reset(&s->td.dtmf.row_out[i]);
00778          goertzel_reset(&s->td.dtmf.col_out[i]);
00779       }
00780       s->td.dtmf.energy = 0.0;
00781       s->td.dtmf.current_sample = 0;
00782    }
00783 
00784    if (squelch && mute.end) {
00785       if (mute.end > samples) {
00786          s->td.dtmf.mute_samples = mute.end - samples;
00787          mute.end = samples;
00788       }
00789       mute_fragment(dsp, &mute);
00790    }
00791 
00792    return (s->td.dtmf.current_hit); /* return the debounced hit */
00793 }
00794 
00795 static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[],
00796                  int samples, int squelch, int relax)
00797 {
00798    float energy[6];
00799    int best;
00800    int second_best;
00801    float famp;
00802    int i;
00803    int j;
00804    int sample;
00805    int hit;
00806    int limit;
00807    fragment_t mute = {0, 0};
00808 
00809    if (squelch && s->td.mf.mute_samples > 0) {
00810       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00811       s->td.mf.mute_samples -= mute.end;
00812    }
00813 
00814    hit = 0;
00815    for (sample = 0;  sample < samples;  sample = limit) {
00816       /* 80 is optimised to meet the MF specs. */
00817       /* XXX So then why is MF_GSIZE defined as 120? */
00818       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00819          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00820       } else {
00821          limit = samples;
00822       }
00823       /* The following unrolled loop takes only 35% (rough estimate) of the 
00824          time of a rolled loop on the machine on which it was developed */
00825       for (j = sample;  j < limit;  j++) {
00826          famp = amp[j];
00827          /* With GCC 2.95, the following unrolled code seems to take about 35%
00828             (rough estimate) as long as a neat little 0-3 loop */
00829          goertzel_sample(s->td.mf.tone_out, amp[j]);
00830          goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
00831          goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
00832          goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
00833          goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
00834          goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
00835       }
00836       s->td.mf.current_sample += (limit - sample);
00837       if (s->td.mf.current_sample < MF_GSIZE) {
00838          continue;
00839       }
00840       /* We're at the end of an MF detection block.  */
00841       /* Find the two highest energies. The spec says to look for
00842          two tones and two tones only. Taking this literally -ie
00843          only two tones pass the minimum threshold - doesn't work
00844          well. The sinc function mess, due to rectangular windowing
00845          ensure that! Find the two highest energies and ensure they
00846          are considerably stronger than any of the others. */
00847       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00848       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00849       if (energy[0] > energy[1]) {
00850          best = 0;
00851          second_best = 1;
00852       } else {
00853          best = 1;
00854          second_best = 0;
00855       }
00856       /*endif*/
00857       for (i = 2; i < 6; i++) {
00858          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00859          if (energy[i] >= energy[best]) {
00860             second_best = best;
00861             best = i;
00862          } else if (energy[i] >= energy[second_best]) {
00863             second_best = i;
00864          }
00865       }
00866       /* Basic signal level and twist tests */
00867       hit = 0;
00868       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00869                && energy[best] < energy[second_best]*BELL_MF_TWIST
00870                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00871          /* Relative peak test */
00872          hit = -1;
00873          for (i = 0; i < 6; i++) {
00874             if (i != best && i != second_best) {
00875                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00876                   /* The best two are not clearly the best */
00877                   hit = 0;
00878                   break;
00879                }
00880             }
00881          }
00882       }
00883       if (hit) {
00884          /* Get the values into ascending order */
00885          if (second_best < best) {
00886             i = best;
00887             best = second_best;
00888             second_best = i;
00889          }
00890          best = best * 5 + second_best - 1;
00891          hit = bell_mf_positions[best];
00892          /* Look for two successive similar results */
00893          /* The logic in the next test is:
00894             For KP we need 4 successive identical clean detects, with
00895             two blocks of something different preceeding it. For anything
00896             else we need two successive identical clean detects, with
00897             two blocks of something different preceeding it. */
00898          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00899             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00900              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00901              hit != s->td.mf.hits[0]))) {
00902             store_digit(s, hit);
00903          }
00904       }
00905 
00906 
00907       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00908          /* Two successive block without a hit terminate current digit */
00909          s->td.mf.current_hit = 0;
00910       }
00911 
00912       s->td.mf.hits[0] = s->td.mf.hits[1];
00913       s->td.mf.hits[1] = s->td.mf.hits[2];
00914       s->td.mf.hits[2] = s->td.mf.hits[3];
00915       s->td.mf.hits[3] = s->td.mf.hits[4];
00916       s->td.mf.hits[4] = hit;
00917 
00918       /* If we had a hit in this block, include it into mute fragment */
00919       if (squelch && hit) {
00920          if (mute.end < sample - MF_GSIZE) {
00921             /* There is a gap between fragments */
00922             mute_fragment(dsp, &mute);
00923             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00924          }
00925          mute.end = limit + DTMF_GSIZE;
00926       }
00927 
00928       /* Reinitialise the detector for the next block */
00929       for (i = 0;  i < 6;  i++)
00930          goertzel_reset(&s->td.mf.tone_out[i]);
00931       s->td.mf.current_sample = 0;
00932    }
00933 
00934    if (squelch && mute.end) {
00935       if (mute.end > samples) {
00936          s->td.mf.mute_samples = mute.end - samples;
00937          mute.end = samples;
00938       }
00939       mute_fragment(dsp, &mute);
00940    }
00941 
00942    return (s->td.mf.current_hit); /* return the debounced hit */
00943 }
00944 
00945 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
00946 {
00947    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00948    /* Make sure absolute levels are high enough */
00949    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
00950       return 0;
00951    }
00952    /* Amplify ignored stuff */
00953    i2 *= TONE_THRESH;
00954    i1 *= TONE_THRESH;
00955    e *= TONE_THRESH;
00956    /* Check first tone */
00957    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
00958       return 0;
00959    }
00960    /* And second */
00961    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
00962       return 0;
00963    }
00964    /* Guess it's there... */
00965    return 1;
00966 }
00967 
00968 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
00969 {
00970    int x;
00971    int y;
00972    int pass;
00973    int newstate = DSP_TONE_STATE_SILENCE;
00974    int res = 0;
00975    while (len) {
00976       /* Take the lesser of the number of samples we need and what we have */
00977       pass = len;
00978       if (pass > dsp->gsamp_size - dsp->gsamps) {
00979          pass = dsp->gsamp_size - dsp->gsamps;
00980       }
00981       for (x = 0; x < pass; x++) {
00982          for (y = 0; y < dsp->freqcount; y++) {
00983             goertzel_sample(&dsp->freqs[y], s[x]);
00984          }
00985          dsp->genergy += s[x] * s[x];
00986       }
00987       s += pass;
00988       dsp->gsamps += pass;
00989       len -= pass;
00990       if (dsp->gsamps == dsp->gsamp_size) {
00991          float hz[7];
00992          for (y = 0; y < 7; y++) {
00993             hz[y] = goertzel_result(&dsp->freqs[y]);
00994          }
00995          switch (dsp->progmode) {
00996          case PROG_MODE_NA:
00997             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
00998                newstate = DSP_TONE_STATE_BUSY;
00999             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01000                newstate = DSP_TONE_STATE_RINGING;
01001             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01002                newstate = DSP_TONE_STATE_DIALTONE;
01003             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01004                newstate = DSP_TONE_STATE_SPECIAL1;
01005             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01006                /* End of SPECIAL1 or middle of SPECIAL2 */
01007                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
01008                   newstate = DSP_TONE_STATE_SPECIAL2;
01009                }
01010             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01011                /* End of SPECIAL2 or middle of SPECIAL3 */
01012                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01013                   newstate = DSP_TONE_STATE_SPECIAL3;
01014                }
01015             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01016                newstate = DSP_TONE_STATE_TALKING;
01017             } else {
01018                newstate = DSP_TONE_STATE_SILENCE;
01019             }
01020             break;
01021          case PROG_MODE_CR:
01022             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01023                newstate = DSP_TONE_STATE_RINGING;
01024             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01025                newstate = DSP_TONE_STATE_TALKING;
01026             } else {
01027                newstate = DSP_TONE_STATE_SILENCE;
01028             }
01029             break;
01030          case PROG_MODE_UK:
01031             if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
01032                newstate = DSP_TONE_STATE_HUNGUP;
01033             } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
01034                newstate = DSP_TONE_STATE_DIALTONE;
01035             }
01036             break;
01037          default:
01038             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01039          }
01040          if (newstate == dsp->tstate) {
01041             dsp->tcount++;
01042             if (dsp->ringtimeout) {
01043                dsp->ringtimeout++;
01044             }
01045             switch (dsp->tstate) {
01046             case DSP_TONE_STATE_RINGING:
01047                if ((dsp->features & DSP_PROGRESS_RINGING) &&
01048                    (dsp->tcount == THRESH_RING)) {
01049                   res = AST_CONTROL_RINGING;
01050                   dsp->ringtimeout = 1;
01051                }
01052                break;
01053             case DSP_TONE_STATE_BUSY:
01054                if ((dsp->features & DSP_PROGRESS_BUSY) &&
01055                    (dsp->tcount == THRESH_BUSY)) {
01056                   res = AST_CONTROL_BUSY;
01057                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01058                }
01059                break;
01060             case DSP_TONE_STATE_TALKING:
01061                if ((dsp->features & DSP_PROGRESS_TALK) &&
01062                    (dsp->tcount == THRESH_TALK)) {
01063                   res = AST_CONTROL_ANSWER;
01064                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01065                }
01066                break;
01067             case DSP_TONE_STATE_SPECIAL3:
01068                if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01069                    (dsp->tcount == THRESH_CONGESTION)) {
01070                   res = AST_CONTROL_CONGESTION;
01071                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01072                }
01073                break;
01074             case DSP_TONE_STATE_HUNGUP:
01075                if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01076                    (dsp->tcount == THRESH_HANGUP)) {
01077                   res = AST_CONTROL_HANGUP;
01078                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01079                }
01080                break;
01081             }
01082             if (dsp->ringtimeout == THRESH_RING2ANSWER) {
01083                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
01084                res = AST_CONTROL_ANSWER;
01085                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01086             }
01087          } else {
01088             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01089             ast_debug(5, "Start state %d\n", newstate);
01090             dsp->tstate = newstate;
01091             dsp->tcount = 1;
01092          }
01093 
01094          /* Reset goertzel */
01095          for (x = 0; x < 7; x++) {
01096             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01097          }
01098          dsp->gsamps = 0;
01099          dsp->genergy = 0.0;
01100       }
01101    }
01102 
01103    return res;
01104 }
01105 
01106 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
01107 {
01108    if (inf->frametype != AST_FRAME_VOICE) {
01109       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01110       return 0;
01111    }
01112    if (inf->subclass.codec != AST_FORMAT_SLINEAR) {
01113       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01114       return 0;
01115    }
01116    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01117 }
01118 
01119 static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
01120 {
01121    int accum;
01122    int x;
01123    int res = 0;
01124 
01125    if (!len) {
01126       return 0;
01127    }
01128    accum = 0;
01129    for (x = 0; x < len; x++) {
01130       accum += abs(s[x]);
01131    }
01132    accum /= len;
01133    if (accum < dsp->threshold) {
01134       /* Silent */
01135       dsp->totalsilence += len / 8;
01136 #ifdef DEBUG_DSP_BUSYDETECT
01137       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01138 #endif
01139       if (dsp->totalnoise) {
01140          /* Move and save history */
01141          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0]));
01142          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01143          /* check if previous tone differs BUSY_PERCENT from the one before it */
01144          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01145          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01146          if (tone1 < tone2) {
01147            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01148                dsp->busymaybe = 1;
01149            else
01150                dsp->busymaybe = 0;
01151          } else {
01152            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01153                dsp->busymaybe = 1;
01154             else
01155                dsp->busymaybe = 0;
01156          }
01157       }
01158       dsp->totalnoise = 0;
01159       res = 1;
01160    } else {
01161       /* Not silent */
01162       dsp->totalnoise += len / 8;
01163 #ifdef DEBUG_DSP_BUSYDETECT
01164       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01165 #endif     
01166       if (dsp->totalsilence) {
01167          /* Move and save history */
01168          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0]));
01169          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01170       }
01171       dsp->totalsilence = 0;
01172    }
01173    if (totalsilence) {
01174       *totalsilence = dsp->totalsilence;
01175    }
01176    if (totalnoise) {
01177       *totalnoise = dsp->totalnoise;
01178    }
01179    return res;
01180 }
01181 
01182 int ast_dsp_busydetect(struct ast_dsp *dsp)
01183 {
01184    int res = 0, x;
01185    int avgsilence = 0, hitsilence = 0;
01186    int avgtone = 0, hittone = 0;
01187 #ifdef DEBUG_DSP_BUSYDETECT
01188    char buf[16];
01189    char silence_list[64]="", tone_list[64]="";
01190 #endif
01191    
01192    if (!dsp->busymaybe) {
01193       return res;
01194    }
01195    dsp->busymaybe = 0;
01196 
01197    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01198       avgsilence += dsp->historicsilence[x];
01199       avgtone += dsp->historicnoise[x];
01200    }
01201    avgsilence /= dsp->busycount;
01202    avgtone /= dsp->busycount;
01203 #ifdef DEBUG_DSP_BUSYDETECT
01204    sprintf(silence_list,"Silences: ");
01205    sprintf(tone_list,"Tones:    ");
01206 #endif
01207    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01208 #ifdef DEBUG_DSP_BUSYDETECT
01209       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01210       strcat(silence_list, buf);
01211       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01212       strcat(tone_list, buf); 
01213 #endif
01214       if (!dsp->busytoneonly) {
01215          if (avgsilence > dsp->historicsilence[x]) {
01216             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01217                hitsilence++;
01218          } else {
01219             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01220                hitsilence++;
01221          }
01222       }
01223       if (avgtone > dsp->historicnoise[x]) {
01224          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01225             hittone++;
01226          }
01227       } else {
01228          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01229             hittone++;
01230          }
01231       }
01232    }
01233 #ifdef DEBUG_DSP_BUSYDETECT
01234    fprintf(stderr, "BUSY DETECTOR\n");   
01235    fprintf(stderr, "%s\n", tone_list);
01236    fprintf(stderr, "%s\n", silence_list)
01237 #endif
01238    if ((dsp->busytoneonly || 
01239        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01240       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01241       if (dsp->busycompare) {
01242            if (dsp->busytoneonly) {
01243              res = 1;
01244             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01245          } else {
01246               if (avgtone > avgsilence) {
01247                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01248                     res = 1;
01249             } else {
01250                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01251                    res = 1;
01252             }
01253          }
01254       } else {
01255          res = 1;
01256       }
01257    }
01258    /* If we know the expected busy tone length, check we are in the range */
01259    if (res && (dsp->busy_tonelength > 0)) {
01260       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01261 #ifdef BUSYDETECT_DEBUG
01262          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01263             avgtone, dsp->busy_tonelength);
01264 #endif
01265          res = 0;
01266       }
01267    }
01268    /* If we know the expected busy tone silent-period length, check we are in the range */
01269    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01270       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01271 #ifdef BUSYDETECT_DEBUG
01272       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01273          avgsilence, dsp->busy_quietlength);
01274 #endif
01275          res = 0;
01276       }
01277    }
01278    if (res) {
01279       if (option_debug)
01280          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01281    } else {
01282       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01283    }
01284    return res;
01285 }
01286 
01287 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
01288 {
01289    short *s;
01290    int len;
01291    
01292    if (f->frametype != AST_FRAME_VOICE) {
01293       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01294       return 0;
01295    }
01296    if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01297       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01298       return 0;
01299    }
01300    s = f->data.ptr;
01301    len = f->datalen/2;
01302    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01303 }
01304 
01305 int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
01306 {
01307        short *s;
01308        int len;
01309 
01310        if (f->frametype != AST_FRAME_VOICE) {
01311                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01312                return 0;
01313        }
01314        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01315                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01316                return 0;
01317        }
01318        s = f->data.ptr;
01319        len = f->datalen/2;
01320        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01321 }
01322 
01323 
01324 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
01325 {
01326    int silence;
01327    int res;
01328    int digit = 0, fax_digit = 0;
01329    int x;
01330    short *shortdata;
01331    unsigned char *odata;
01332    int len;
01333    struct ast_frame *outf = NULL;
01334 
01335    if (!af) {
01336       return NULL;
01337    }
01338    if (af->frametype != AST_FRAME_VOICE) {
01339       return af;
01340    }
01341 
01342    odata = af->data.ptr;
01343    len = af->datalen;
01344    /* Make sure we have short data */
01345    switch (af->subclass.codec) {
01346    case AST_FORMAT_SLINEAR:
01347       shortdata = af->data.ptr;
01348       len = af->datalen / 2;
01349       break;
01350    case AST_FORMAT_ULAW:
01351    case AST_FORMAT_TESTLAW:
01352       shortdata = alloca(af->datalen * 2);
01353       for (x = 0;x < len; x++) {
01354          shortdata[x] = AST_MULAW(odata[x]);
01355       }
01356       break;
01357    case AST_FORMAT_ALAW:
01358       shortdata = alloca(af->datalen * 2);
01359       for (x = 0; x < len; x++) {
01360          shortdata[x] = AST_ALAW(odata[x]);
01361       }
01362       break;
01363    default:
01364       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01365       if (dsp->display_inband_dtmf_warning)
01366          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec));
01367       dsp->display_inband_dtmf_warning = 0;
01368       return af;
01369    }
01370 
01371    /* Initially we do not want to mute anything */
01372    dsp->mute_fragments = 0;
01373 
01374    /* Need to run the silence detection stuff for silence suppression and busy detection */
01375    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01376       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01377    }
01378 
01379    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01380       memset(&dsp->f, 0, sizeof(dsp->f));
01381       dsp->f.frametype = AST_FRAME_NULL;
01382       ast_frfree(af);
01383       return ast_frisolate(&dsp->f);
01384    }
01385    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01386       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01387       memset(&dsp->f, 0, sizeof(dsp->f));
01388       dsp->f.frametype = AST_FRAME_CONTROL;
01389       /* Signal this as it was a channel hangup, to avoid msg "channel.c:3473 ast_waitfordigit_full: Unexpected control subclass '5'" */
01390       dsp->f.subclass.integer = AST_CONTROL_HANGUP;
01391       ast_frfree(af);
01392       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01393       return ast_frisolate(&dsp->f);
01394    }
01395 
01396    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01397       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01398          fax_digit = 'f';
01399       }
01400 
01401       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01402          fax_digit = 'e';
01403       }
01404    }
01405 
01406    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01407       if (dsp->digitmode & DSP_DIGITMODE_MF)
01408          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01409       else
01410          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01411 
01412       if (dsp->digit_state.current_digits) {
01413          int event = 0, event_len = 0;
01414          char event_digit = 0;
01415 
01416          if (!dsp->dtmf_began) {
01417             /* We have not reported DTMF_BEGIN for anything yet */
01418 
01419             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01420                event = AST_FRAME_DTMF_BEGIN;
01421                event_digit = dsp->digit_state.digits[0];
01422             }
01423             dsp->dtmf_began = 1;
01424 
01425          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01426             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01427             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01428                event = AST_FRAME_DTMF_END;
01429                event_digit = dsp->digit_state.digits[0];
01430                event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE;
01431             }
01432             memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
01433             memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
01434             dsp->digit_state.current_digits--;
01435             dsp->dtmf_began = 0;
01436 
01437             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01438                /* Reset Busy Detector as we have some confirmed activity */ 
01439                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01440                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01441                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01442             }
01443          }
01444 
01445          if (event) {
01446             memset(&dsp->f, 0, sizeof(dsp->f));
01447             dsp->f.frametype = event;
01448             dsp->f.subclass.integer = event_digit;
01449             dsp->f.len = event_len;
01450             outf = &dsp->f;
01451             goto done;
01452          }
01453       }
01454    }
01455 
01456    if (fax_digit) {
01457       /* Fax was detected - digit is either 'f' or 'e' */
01458 
01459       memset(&dsp->f, 0, sizeof(dsp->f));
01460       dsp->f.frametype = AST_FRAME_DTMF;
01461       dsp->f.subclass.integer = fax_digit;
01462       outf = &dsp->f;
01463       goto done;
01464    }
01465 
01466    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01467       res = __ast_dsp_call_progress(dsp, shortdata, len);
01468       if (res) {
01469          switch (res) {
01470          case AST_CONTROL_ANSWER:
01471          case AST_CONTROL_BUSY:
01472          case AST_CONTROL_RINGING:
01473          case AST_CONTROL_CONGESTION:
01474          case AST_CONTROL_HANGUP:
01475             memset(&dsp->f, 0, sizeof(dsp->f));
01476             dsp->f.frametype = AST_FRAME_CONTROL;
01477             dsp->f.subclass.integer = res;
01478             dsp->f.src = "dsp_progress";
01479             if (chan) 
01480                ast_queue_frame(chan, &dsp->f);
01481             break;
01482          default:
01483             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01484          }
01485       }
01486    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01487       res = __ast_dsp_call_progress(dsp, shortdata, len);
01488    }
01489 
01490 done:
01491    /* Mute fragment of the frame */
01492    for (x = 0; x < dsp->mute_fragments; x++) {
01493       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01494    }
01495 
01496    switch (af->subclass.codec) {
01497    case AST_FORMAT_SLINEAR:
01498       break;
01499    case AST_FORMAT_ULAW:
01500       for (x = 0; x < len; x++) {
01501          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01502       }
01503       break;
01504    case AST_FORMAT_ALAW:
01505       for (x = 0; x < len; x++) {
01506          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01507       }
01508       break;
01509    }
01510 
01511    if (outf) {
01512       if (chan) {
01513          ast_queue_frame(chan, af);
01514       }
01515       ast_frfree(af);
01516       return ast_frisolate(outf);
01517    } else {
01518       return af;
01519    }
01520 }
01521 
01522 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
01523 {
01524    int max = 0;
01525    int x;
01526    
01527    dsp->gsamp_size = modes[dsp->progmode].size;
01528    dsp->gsamps = 0;
01529    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01530       if (modes[dsp->progmode].freqs[x]) {
01531          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01532          max = x + 1;
01533       }
01534    }
01535    dsp->freqcount = max;
01536    dsp->ringtimeout= 0;
01537 }
01538 
01539 struct ast_dsp *ast_dsp_new(void)
01540 {
01541    struct ast_dsp *dsp;
01542    
01543    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01544       dsp->threshold = DEFAULT_THRESHOLD;
01545       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01546       dsp->busycount = DSP_HISTORY;
01547       dsp->digitmode = DSP_DIGITMODE_DTMF;
01548       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01549       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01550 #ifdef BUSYDETECT_TONEONLY
01551       dsp->busytoneonly = 1;
01552 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01553 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01554 #endif
01555 #else
01556    dsp->busytoneonly = 0;
01557 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01558    dsp->busycompare = 1;
01559 #else
01560    dsp->busycompare = 0;
01561 #endif
01562 #endif
01563       /* Initialize digit detector */
01564       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01565       dsp->display_inband_dtmf_warning = 1;
01566       /* Initialize initial DSP progress detect parameters */
01567       ast_dsp_prog_reset(dsp);
01568       /* Initialize fax detector */
01569       ast_fax_detect_init(dsp);
01570    }
01571    return dsp;
01572 }
01573 
01574 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
01575 {
01576    dsp->features = features;
01577 }
01578 
01579 void ast_dsp_free(struct ast_dsp *dsp)
01580 {
01581    ast_free(dsp);
01582 }
01583 
01584 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
01585 {
01586    if (threshold < 256)
01587      dsp->threshold = 256;
01588    else
01589      dsp->threshold = threshold;
01590 }
01591 
01592 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
01593 {
01594    if (cadences < 4) {
01595       cadences = 4;
01596    }
01597    if (cadences > DSP_HISTORY) {
01598       cadences = DSP_HISTORY;
01599    }
01600    dsp->busycount = cadences;
01601 }
01602 
01603 void ast_dsp_set_busy_compare(struct ast_dsp *dsp, int compare)
01604 {
01605   if (compare > 0)
01606       dsp->busycompare = 1;
01607   else
01608       dsp->busycompare = 0;
01609 }
01610 
01611 void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
01612 {
01613    dsp->busy_tonelength = tonelength;
01614    if (quietlength > 0)
01615       dsp->busy_quietlength = quietlength;
01616    else 
01617      dsp->busytoneonly = 1;
01618    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01619    if( fuzzy > 0 && fuzzy < 50 ) 
01620       dsp->busy_pattern_fuzzy = fuzzy;
01621 }
01622 
01623 void ast_dsp_digitreset(struct ast_dsp *dsp)
01624 {
01625    int i;
01626    
01627    dsp->dtmf_began = 0;
01628    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01629       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01630       /* Reinitialise the detector for the next block */
01631       for (i = 0;  i < 6;  i++) {
01632          goertzel_reset(&s->tone_out[i]);
01633       }
01634       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01635       s->current_sample = 0;
01636    } else {
01637       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01638       /* Reinitialise the detector for the next block */
01639       for (i = 0;  i < 4;  i++) {
01640          goertzel_reset(&s->row_out[i]);
01641          goertzel_reset(&s->col_out[i]);
01642       }
01643       s->lasthit = s->current_hit = 0;
01644       s->energy = 0.0;
01645       s->current_sample = 0;
01646       s->hits = 0;
01647       s->misses = 0;
01648    }
01649 
01650    dsp->digit_state.digits[0] = '\0';
01651    dsp->digit_state.current_digits = 0;
01652 }
01653 
01654 void ast_dsp_reset(struct ast_dsp *dsp)
01655 {
01656    int x;
01657    
01658    dsp->totalsilence = 0;
01659    dsp->gsamps = 0;
01660    for (x = 0; x < 4; x++) {
01661       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01662    }
01663    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01664    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01665    dsp->ringtimeout= 0;
01666 }
01667 
01668 int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
01669 {
01670    int new;
01671    int old;
01672    
01673    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01674    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01675    if (old != new) {
01676       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01677       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01678    }
01679    dsp->digitmode = digitmode;
01680    return 0;
01681 }
01682 
01683 int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
01684 {
01685    if (dsp->faxmode != faxmode) {
01686       ast_fax_detect_init(dsp);
01687    }
01688    dsp->faxmode = faxmode;
01689    return 0;
01690 }
01691 
01692 int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
01693 {
01694    int x;
01695    
01696    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01697       if (!strcasecmp(aliases[x].name, zone)) {
01698          dsp->progmode = aliases[x].mode;
01699          ast_dsp_prog_reset(dsp);
01700          return 0;
01701       }
01702    }
01703    return -1;
01704 }
01705 
01706 int ast_dsp_was_muted(struct ast_dsp *dsp)
01707 {
01708    return (dsp->mute_fragments > 0);
01709 }
01710 
01711 int ast_dsp_get_tstate(struct ast_dsp *dsp) 
01712 {
01713    return dsp->tstate;
01714 }
01715 
01716 int ast_dsp_get_tcount(struct ast_dsp *dsp) 
01717 {
01718    return dsp->tcount;
01719 }
01720 
01721 static int _dsp_init(int reload)
01722 {
01723    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01724    struct ast_config *cfg;
01725 
01726    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01727    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01728       ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD);
01729       thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01730       return 0;
01731    }
01732 
01733    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01734       return 0;
01735    }
01736 
01737    if (cfg) {
01738       const char *value;
01739 
01740       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01741       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01742          ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01743          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01744       } else if (!value) {
01745          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01746       }
01747 
01748       ast_config_destroy(cfg);
01749    }
01750    return 0;
01751 }
01752 
01753 int ast_dsp_get_threshold_from_settings(enum threshold which)
01754 {
01755    return thresholds[which];
01756 }
01757 
01758 int ast_dsp_init(void)
01759 {
01760    return _dsp_init(0);
01761 }
01762 
01763 int ast_dsp_reload(void)
01764 {
01765    return _dsp_init(1);
01766 }
01767 

Generated on Wed Apr 6 11:29:44 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7