Sat Mar 10 01:54:16 2012

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: 349728 $")
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 4
00213 /* How many successive misses needed to consider end of a digit */
00214 #define DTMF_MISSES_TO_END 4
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 (hit == s->td.dtmf.lasthit) {
00730          if (s->td.dtmf.current_hit) {
00731             /* We are in the middle of a digit already */
00732             if (hit) {
00733                if (hit != s->td.dtmf.current_hit) {
00734                   /* Look for a start of a new digit.
00735                      This is because hits_to_begin may be smaller than misses_to_end
00736                      and we may find the beginning of new digit before we consider last one ended. */
00737                   s->td.dtmf.current_hit = 0;
00738                } else {
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             } else {
00743                /* No Digit */
00744                s->td.dtmf.misses++;
00745                if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
00746                   /* There were enough misses to consider digit ended */
00747                   s->td.dtmf.current_hit = 0;
00748                }
00749             }
00750          } else if (hit) {
00751             /* Detecting new digit */
00752             s->td.dtmf.hits++;
00753             if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin) {
00754                store_digit(s, hit);
00755                s->td.dtmf.current_hit = hit;
00756             }
00757          }
00758       } else {
00759          s->td.dtmf.hits = 1;
00760          s->td.dtmf.misses = 1;
00761          s->td.dtmf.lasthit = hit;
00762       }
00763 
00764       /* If we had a hit in this block, include it into mute fragment */
00765       if (squelch && hit) {
00766          if (mute.end < sample - DTMF_GSIZE) {
00767             /* There is a gap between fragments */
00768             mute_fragment(dsp, &mute);
00769             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00770          }
00771          mute.end = limit + DTMF_GSIZE;
00772       }
00773 
00774       /* Reinitialise the detector for the next block */
00775       for (i = 0; i < 4; i++) {
00776          goertzel_reset(&s->td.dtmf.row_out[i]);
00777          goertzel_reset(&s->td.dtmf.col_out[i]);
00778       }
00779       s->td.dtmf.energy = 0.0;
00780       s->td.dtmf.current_sample = 0;
00781    }
00782 
00783    if (squelch && mute.end) {
00784       if (mute.end > samples) {
00785          s->td.dtmf.mute_samples = mute.end - samples;
00786          mute.end = samples;
00787       }
00788       mute_fragment(dsp, &mute);
00789    }
00790 
00791    return (s->td.dtmf.current_hit); /* return the debounced hit */
00792 }
00793 
00794 static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[],
00795                  int samples, int squelch, int relax)
00796 {
00797    float energy[6];
00798    int best;
00799    int second_best;
00800    int i;
00801    int j;
00802    int sample;
00803    int hit;
00804    int limit;
00805    fragment_t mute = {0, 0};
00806 
00807    if (squelch && s->td.mf.mute_samples > 0) {
00808       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00809       s->td.mf.mute_samples -= mute.end;
00810    }
00811 
00812    hit = 0;
00813    for (sample = 0;  sample < samples;  sample = limit) {
00814       /* 80 is optimised to meet the MF specs. */
00815       /* XXX So then why is MF_GSIZE defined as 120? */
00816       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00817          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00818       } else {
00819          limit = samples;
00820       }
00821       /* The following unrolled loop takes only 35% (rough estimate) of the 
00822          time of a rolled loop on the machine on which it was developed */
00823       for (j = sample;  j < limit;  j++) {
00824          /* With GCC 2.95, the following unrolled code seems to take about 35%
00825             (rough estimate) as long as a neat little 0-3 loop */
00826          goertzel_sample(s->td.mf.tone_out, amp[j]);
00827          goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
00828          goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
00829          goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
00830          goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
00831          goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
00832       }
00833       s->td.mf.current_sample += (limit - sample);
00834       if (s->td.mf.current_sample < MF_GSIZE) {
00835          continue;
00836       }
00837       /* We're at the end of an MF detection block.  */
00838       /* Find the two highest energies. The spec says to look for
00839          two tones and two tones only. Taking this literally -ie
00840          only two tones pass the minimum threshold - doesn't work
00841          well. The sinc function mess, due to rectangular windowing
00842          ensure that! Find the two highest energies and ensure they
00843          are considerably stronger than any of the others. */
00844       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00845       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00846       if (energy[0] > energy[1]) {
00847          best = 0;
00848          second_best = 1;
00849       } else {
00850          best = 1;
00851          second_best = 0;
00852       }
00853       /*endif*/
00854       for (i = 2; i < 6; i++) {
00855          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00856          if (energy[i] >= energy[best]) {
00857             second_best = best;
00858             best = i;
00859          } else if (energy[i] >= energy[second_best]) {
00860             second_best = i;
00861          }
00862       }
00863       /* Basic signal level and twist tests */
00864       hit = 0;
00865       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00866                && energy[best] < energy[second_best]*BELL_MF_TWIST
00867                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00868          /* Relative peak test */
00869          hit = -1;
00870          for (i = 0; i < 6; i++) {
00871             if (i != best && i != second_best) {
00872                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00873                   /* The best two are not clearly the best */
00874                   hit = 0;
00875                   break;
00876                }
00877             }
00878          }
00879       }
00880       if (hit) {
00881          /* Get the values into ascending order */
00882          if (second_best < best) {
00883             i = best;
00884             best = second_best;
00885             second_best = i;
00886          }
00887          best = best * 5 + second_best - 1;
00888          hit = bell_mf_positions[best];
00889          /* Look for two successive similar results */
00890          /* The logic in the next test is:
00891             For KP we need 4 successive identical clean detects, with
00892             two blocks of something different preceeding it. For anything
00893             else we need two successive identical clean detects, with
00894             two blocks of something different preceeding it. */
00895          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00896             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00897              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00898              hit != s->td.mf.hits[0]))) {
00899             store_digit(s, hit);
00900          }
00901       }
00902 
00903 
00904       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00905          /* Two successive block without a hit terminate current digit */
00906          s->td.mf.current_hit = 0;
00907       }
00908 
00909       s->td.mf.hits[0] = s->td.mf.hits[1];
00910       s->td.mf.hits[1] = s->td.mf.hits[2];
00911       s->td.mf.hits[2] = s->td.mf.hits[3];
00912       s->td.mf.hits[3] = s->td.mf.hits[4];
00913       s->td.mf.hits[4] = hit;
00914 
00915       /* If we had a hit in this block, include it into mute fragment */
00916       if (squelch && hit) {
00917          if (mute.end < sample - MF_GSIZE) {
00918             /* There is a gap between fragments */
00919             mute_fragment(dsp, &mute);
00920             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00921          }
00922          mute.end = limit + DTMF_GSIZE;
00923       }
00924 
00925       /* Reinitialise the detector for the next block */
00926       for (i = 0;  i < 6;  i++)
00927          goertzel_reset(&s->td.mf.tone_out[i]);
00928       s->td.mf.current_sample = 0;
00929    }
00930 
00931    if (squelch && mute.end) {
00932       if (mute.end > samples) {
00933          s->td.mf.mute_samples = mute.end - samples;
00934          mute.end = samples;
00935       }
00936       mute_fragment(dsp, &mute);
00937    }
00938 
00939    return (s->td.mf.current_hit); /* return the debounced hit */
00940 }
00941 
00942 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
00943 {
00944    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00945    /* Make sure absolute levels are high enough */
00946    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
00947       return 0;
00948    }
00949    /* Amplify ignored stuff */
00950    i2 *= TONE_THRESH;
00951    i1 *= TONE_THRESH;
00952    e *= TONE_THRESH;
00953    /* Check first tone */
00954    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
00955       return 0;
00956    }
00957    /* And second */
00958    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
00959       return 0;
00960    }
00961    /* Guess it's there... */
00962    return 1;
00963 }
00964 
00965 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
00966 {
00967    int x;
00968    int y;
00969    int pass;
00970    int newstate = DSP_TONE_STATE_SILENCE;
00971    int res = 0;
00972    while (len) {
00973       /* Take the lesser of the number of samples we need and what we have */
00974       pass = len;
00975       if (pass > dsp->gsamp_size - dsp->gsamps) {
00976          pass = dsp->gsamp_size - dsp->gsamps;
00977       }
00978       for (x = 0; x < pass; x++) {
00979          for (y = 0; y < dsp->freqcount; y++) {
00980             goertzel_sample(&dsp->freqs[y], s[x]);
00981          }
00982          dsp->genergy += s[x] * s[x];
00983       }
00984       s += pass;
00985       dsp->gsamps += pass;
00986       len -= pass;
00987       if (dsp->gsamps == dsp->gsamp_size) {
00988          float hz[7];
00989          for (y = 0; y < 7; y++) {
00990             hz[y] = goertzel_result(&dsp->freqs[y]);
00991          }
00992          switch (dsp->progmode) {
00993          case PROG_MODE_NA:
00994             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
00995                newstate = DSP_TONE_STATE_BUSY;
00996             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
00997                newstate = DSP_TONE_STATE_RINGING;
00998             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
00999                newstate = DSP_TONE_STATE_DIALTONE;
01000             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01001                newstate = DSP_TONE_STATE_SPECIAL1;
01002             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01003                /* End of SPECIAL1 or middle of SPECIAL2 */
01004                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
01005                   newstate = DSP_TONE_STATE_SPECIAL2;
01006                }
01007             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01008                /* End of SPECIAL2 or middle of SPECIAL3 */
01009                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01010                   newstate = DSP_TONE_STATE_SPECIAL3;
01011                }
01012             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01013                newstate = DSP_TONE_STATE_TALKING;
01014             } else {
01015                newstate = DSP_TONE_STATE_SILENCE;
01016             }
01017             break;
01018          case PROG_MODE_CR:
01019             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01020                newstate = DSP_TONE_STATE_RINGING;
01021             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01022                newstate = DSP_TONE_STATE_TALKING;
01023             } else {
01024                newstate = DSP_TONE_STATE_SILENCE;
01025             }
01026             break;
01027          case PROG_MODE_UK:
01028             if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
01029                newstate = DSP_TONE_STATE_HUNGUP;
01030             } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
01031                newstate = DSP_TONE_STATE_DIALTONE;
01032             }
01033             break;
01034          default:
01035             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01036          }
01037          if (newstate == dsp->tstate) {
01038             dsp->tcount++;
01039             if (dsp->ringtimeout) {
01040                dsp->ringtimeout++;
01041             }
01042             switch (dsp->tstate) {
01043             case DSP_TONE_STATE_RINGING:
01044                if ((dsp->features & DSP_PROGRESS_RINGING) &&
01045                    (dsp->tcount == THRESH_RING)) {
01046                   res = AST_CONTROL_RINGING;
01047                   dsp->ringtimeout = 1;
01048                }
01049                break;
01050             case DSP_TONE_STATE_BUSY:
01051                if ((dsp->features & DSP_PROGRESS_BUSY) &&
01052                    (dsp->tcount == THRESH_BUSY)) {
01053                   res = AST_CONTROL_BUSY;
01054                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01055                }
01056                break;
01057             case DSP_TONE_STATE_TALKING:
01058                if ((dsp->features & DSP_PROGRESS_TALK) &&
01059                    (dsp->tcount == THRESH_TALK)) {
01060                   res = AST_CONTROL_ANSWER;
01061                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01062                }
01063                break;
01064             case DSP_TONE_STATE_SPECIAL3:
01065                if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01066                    (dsp->tcount == THRESH_CONGESTION)) {
01067                   res = AST_CONTROL_CONGESTION;
01068                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01069                }
01070                break;
01071             case DSP_TONE_STATE_HUNGUP:
01072                if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01073                    (dsp->tcount == THRESH_HANGUP)) {
01074                   res = AST_CONTROL_HANGUP;
01075                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01076                }
01077                break;
01078             }
01079             if (dsp->ringtimeout == THRESH_RING2ANSWER) {
01080                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
01081                res = AST_CONTROL_ANSWER;
01082                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01083             }
01084          } else {
01085             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01086             ast_debug(5, "Start state %d\n", newstate);
01087             dsp->tstate = newstate;
01088             dsp->tcount = 1;
01089          }
01090 
01091          /* Reset goertzel */
01092          for (x = 0; x < 7; x++) {
01093             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01094          }
01095          dsp->gsamps = 0;
01096          dsp->genergy = 0.0;
01097       }
01098    }
01099 
01100    return res;
01101 }
01102 
01103 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
01104 {
01105    if (inf->frametype != AST_FRAME_VOICE) {
01106       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01107       return 0;
01108    }
01109    if (inf->subclass.codec != AST_FORMAT_SLINEAR) {
01110       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01111       return 0;
01112    }
01113    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01114 }
01115 
01116 static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
01117 {
01118    int accum;
01119    int x;
01120    int res = 0;
01121 
01122    if (!len) {
01123       return 0;
01124    }
01125    accum = 0;
01126    for (x = 0; x < len; x++) {
01127       accum += abs(s[x]);
01128    }
01129    accum /= len;
01130    if (accum < dsp->threshold) {
01131       /* Silent */
01132       dsp->totalsilence += len / 8;
01133 #ifdef DEBUG_DSP_BUSYDETECT
01134       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01135 #endif
01136       if (dsp->totalnoise) {
01137          /* Move and save history */
01138          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0]));
01139          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01140          /* check if previous tone differs BUSY_PERCENT from the one before it */
01141          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01142          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01143          if (tone1 < tone2) {
01144            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01145                dsp->busymaybe = 1;
01146            else
01147                dsp->busymaybe = 0;
01148          } else {
01149            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01150                dsp->busymaybe = 1;
01151             else
01152                dsp->busymaybe = 0;
01153          }
01154       }
01155       dsp->totalnoise = 0;
01156       res = 1;
01157    } else {
01158       /* Not silent */
01159       dsp->totalnoise += len / 8;
01160 #ifdef DEBUG_DSP_BUSYDETECT
01161       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01162 #endif     
01163       if (dsp->totalsilence) {
01164          /* Move and save history */
01165          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0]));
01166          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01167       }
01168       dsp->totalsilence = 0;
01169    }
01170    if (totalsilence) {
01171       *totalsilence = dsp->totalsilence;
01172    }
01173    if (totalnoise) {
01174       *totalnoise = dsp->totalnoise;
01175    }
01176    return res;
01177 }
01178 
01179 int ast_dsp_busydetect(struct ast_dsp *dsp)
01180 {
01181    int res = 0, x;
01182    int avgsilence = 0, hitsilence = 0;
01183    int avgtone = 0, hittone = 0;
01184 #ifdef DEBUG_DSP_BUSYDETECT
01185    char buf[16];
01186    char silence_list[64]="", tone_list[64]="";
01187 #endif
01188    
01189    if (!dsp->busymaybe) {
01190       return res;
01191    }
01192    dsp->busymaybe = 0;
01193 
01194    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01195       avgsilence += dsp->historicsilence[x];
01196       avgtone += dsp->historicnoise[x];
01197    }
01198    avgsilence /= dsp->busycount;
01199    avgtone /= dsp->busycount;
01200 #ifdef DEBUG_DSP_BUSYDETECT
01201    sprintf(silence_list,"Silences: ");
01202    sprintf(tone_list,"Tones:    ");
01203 #endif
01204    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01205 #ifdef DEBUG_DSP_BUSYDETECT
01206       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01207       strcat(silence_list, buf);
01208       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01209       strcat(tone_list, buf); 
01210 #endif
01211       if (!dsp->busytoneonly) {
01212          if (avgsilence > dsp->historicsilence[x]) {
01213             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01214                hitsilence++;
01215          } else {
01216             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01217                hitsilence++;
01218          }
01219       }
01220       if (avgtone > dsp->historicnoise[x]) {
01221          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01222             hittone++;
01223          }
01224       } else {
01225          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01226             hittone++;
01227          }
01228       }
01229    }
01230 #ifdef DEBUG_DSP_BUSYDETECT
01231    fprintf(stderr, "BUSY DETECTOR\n");   
01232    fprintf(stderr, "%s\n", tone_list);
01233    fprintf(stderr, "%s\n", silence_list)
01234 #endif
01235    if ((dsp->busytoneonly || 
01236        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01237       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01238       if (dsp->busycompare) {
01239            if (dsp->busytoneonly) {
01240              res = 1;
01241             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01242          } else {
01243               if (avgtone > avgsilence) {
01244                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01245                     res = 1;
01246             } else {
01247                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01248                    res = 1;
01249             }
01250          }
01251       } else {
01252          res = 1;
01253       }
01254    }
01255    /* If we know the expected busy tone length, check we are in the range */
01256    if (res && (dsp->busy_tonelength > 0)) {
01257       if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) {
01258 #ifdef BUSYDETECT_DEBUG
01259          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01260             avgtone, dsp->busy_tonelength);
01261 #endif
01262          res = 0;
01263       }
01264    }
01265    /* If we know the expected busy tone silent-period length, check we are in the range */
01266    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01267       if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) {
01268 #ifdef BUSYDETECT_DEBUG
01269       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01270          avgsilence, dsp->busy_quietlength);
01271 #endif
01272          res = 0;
01273       }
01274    }
01275    if (res) {
01276       if (option_debug)
01277          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01278    } else {
01279       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01280    }
01281    return res;
01282 }
01283 
01284 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
01285 {
01286    short *s;
01287    int len;
01288    
01289    if (f->frametype != AST_FRAME_VOICE) {
01290       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01291       return 0;
01292    }
01293    if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01294       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01295       return 0;
01296    }
01297    s = f->data.ptr;
01298    len = f->datalen/2;
01299    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01300 }
01301 
01302 int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
01303 {
01304        short *s;
01305        int len;
01306 
01307        if (f->frametype != AST_FRAME_VOICE) {
01308                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01309                return 0;
01310        }
01311        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01312                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01313                return 0;
01314        }
01315        s = f->data.ptr;
01316        len = f->datalen/2;
01317        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01318 }
01319 
01320 
01321 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
01322 {
01323    int silence;
01324    int res;
01325    int digit = 0, fax_digit = 0;
01326    int x;
01327    short *shortdata;
01328    unsigned char *odata;
01329    int len;
01330    struct ast_frame *outf = NULL;
01331 
01332    if (!af) {
01333       return NULL;
01334    }
01335    if (af->frametype != AST_FRAME_VOICE) {
01336       return af;
01337    }
01338 
01339    odata = af->data.ptr;
01340    len = af->datalen;
01341    /* Make sure we have short data */
01342    switch (af->subclass.codec) {
01343    case AST_FORMAT_SLINEAR:
01344       shortdata = af->data.ptr;
01345       len = af->datalen / 2;
01346       break;
01347    case AST_FORMAT_ULAW:
01348    case AST_FORMAT_TESTLAW:
01349       shortdata = alloca(af->datalen * 2);
01350       for (x = 0;x < len; x++) {
01351          shortdata[x] = AST_MULAW(odata[x]);
01352       }
01353       break;
01354    case AST_FORMAT_ALAW:
01355       shortdata = alloca(af->datalen * 2);
01356       for (x = 0; x < len; x++) {
01357          shortdata[x] = AST_ALAW(odata[x]);
01358       }
01359       break;
01360    default:
01361       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01362       if (dsp->display_inband_dtmf_warning)
01363          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec));
01364       dsp->display_inband_dtmf_warning = 0;
01365       return af;
01366    }
01367 
01368    /* Initially we do not want to mute anything */
01369    dsp->mute_fragments = 0;
01370 
01371    /* Need to run the silence detection stuff for silence suppression and busy detection */
01372    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01373       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01374    }
01375 
01376    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01377       memset(&dsp->f, 0, sizeof(dsp->f));
01378       dsp->f.frametype = AST_FRAME_NULL;
01379       ast_frfree(af);
01380       return ast_frisolate(&dsp->f);
01381    }
01382    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01383       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01384       memset(&dsp->f, 0, sizeof(dsp->f));
01385       dsp->f.frametype = AST_FRAME_CONTROL;
01386       /* Signal this as it was a channel hangup, to avoid msg "channel.c:3473 ast_waitfordigit_full: Unexpected control subclass '5'" */
01387       dsp->f.subclass.integer = AST_CONTROL_HANGUP;
01388       ast_frfree(af);
01389       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01390       return ast_frisolate(&dsp->f);
01391    }
01392 
01393    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01394       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01395          fax_digit = 'f';
01396       }
01397 
01398       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01399          fax_digit = 'e';
01400       }
01401    }
01402 
01403    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01404       if (dsp->digitmode & DSP_DIGITMODE_MF)
01405          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01406       else
01407          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01408 
01409       if (dsp->digit_state.current_digits) {
01410          int event = 0, event_len = 0;
01411          char event_digit = 0;
01412 
01413          if (!dsp->dtmf_began) {
01414             /* We have not reported DTMF_BEGIN for anything yet */
01415 
01416             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01417                event = AST_FRAME_DTMF_BEGIN;
01418                event_digit = dsp->digit_state.digits[0];
01419             }
01420             dsp->dtmf_began = 1;
01421 
01422          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01423             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01424             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01425                event = AST_FRAME_DTMF_END;
01426                event_digit = dsp->digit_state.digits[0];
01427                event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE;
01428             }
01429             memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
01430             memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
01431             dsp->digit_state.current_digits--;
01432             dsp->dtmf_began = 0;
01433 
01434             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01435                /* Reset Busy Detector as we have some confirmed activity */ 
01436                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01437                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01438                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01439             }
01440          }
01441 
01442          if (event) {
01443             memset(&dsp->f, 0, sizeof(dsp->f));
01444             dsp->f.frametype = event;
01445             dsp->f.subclass.integer = event_digit;
01446             dsp->f.len = event_len;
01447             outf = &dsp->f;
01448             goto done;
01449          }
01450       }
01451    }
01452 
01453    if (fax_digit) {
01454       /* Fax was detected - digit is either 'f' or 'e' */
01455 
01456       memset(&dsp->f, 0, sizeof(dsp->f));
01457       dsp->f.frametype = AST_FRAME_DTMF;
01458       dsp->f.subclass.integer = fax_digit;
01459       outf = &dsp->f;
01460       goto done;
01461    }
01462 
01463    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01464       res = __ast_dsp_call_progress(dsp, shortdata, len);
01465       if (res) {
01466          switch (res) {
01467          case AST_CONTROL_ANSWER:
01468          case AST_CONTROL_BUSY:
01469          case AST_CONTROL_RINGING:
01470          case AST_CONTROL_CONGESTION:
01471          case AST_CONTROL_HANGUP:
01472             memset(&dsp->f, 0, sizeof(dsp->f));
01473             dsp->f.frametype = AST_FRAME_CONTROL;
01474             dsp->f.subclass.integer = res;
01475             dsp->f.src = "dsp_progress";
01476             if (chan) 
01477                ast_queue_frame(chan, &dsp->f);
01478             break;
01479          default:
01480             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01481          }
01482       }
01483    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01484       res = __ast_dsp_call_progress(dsp, shortdata, len);
01485    }
01486 
01487 done:
01488    /* Mute fragment of the frame */
01489    for (x = 0; x < dsp->mute_fragments; x++) {
01490       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01491    }
01492 
01493    switch (af->subclass.codec) {
01494    case AST_FORMAT_SLINEAR:
01495       break;
01496    case AST_FORMAT_ULAW:
01497       for (x = 0; x < len; x++) {
01498          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01499       }
01500       break;
01501    case AST_FORMAT_ALAW:
01502       for (x = 0; x < len; x++) {
01503          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01504       }
01505       break;
01506    }
01507 
01508    if (outf) {
01509       if (chan) {
01510          ast_queue_frame(chan, af);
01511       }
01512       ast_frfree(af);
01513       return ast_frisolate(outf);
01514    } else {
01515       return af;
01516    }
01517 }
01518 
01519 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
01520 {
01521    int max = 0;
01522    int x;
01523    
01524    dsp->gsamp_size = modes[dsp->progmode].size;
01525    dsp->gsamps = 0;
01526    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01527       if (modes[dsp->progmode].freqs[x]) {
01528          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01529          max = x + 1;
01530       }
01531    }
01532    dsp->freqcount = max;
01533    dsp->ringtimeout= 0;
01534 }
01535 
01536 struct ast_dsp *ast_dsp_new(void)
01537 {
01538    struct ast_dsp *dsp;
01539    
01540    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01541       dsp->threshold = DEFAULT_THRESHOLD;
01542       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01543       dsp->busycount = DSP_HISTORY;
01544       dsp->digitmode = DSP_DIGITMODE_DTMF;
01545       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01546       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01547 #ifdef BUSYDETECT_TONEONLY
01548       dsp->busytoneonly = 1;
01549 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01550 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01551 #endif
01552 #else
01553    dsp->busytoneonly = 0;
01554 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01555    dsp->busycompare = 1;
01556 #else
01557    dsp->busycompare = 0;
01558 #endif
01559 #endif
01560       /* Initialize digit detector */
01561       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01562       dsp->display_inband_dtmf_warning = 1;
01563       /* Initialize initial DSP progress detect parameters */
01564       ast_dsp_prog_reset(dsp);
01565       /* Initialize fax detector */
01566       ast_fax_detect_init(dsp);
01567    }
01568    return dsp;
01569 }
01570 
01571 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
01572 {
01573    dsp->features = features;
01574    if (!(features & DSP_FEATURE_DIGIT_DETECT)) {
01575       dsp->display_inband_dtmf_warning = 0;
01576    }
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 Sat Mar 10 01:54:16 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7