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

Generated on Sat Feb 11 06:33:14 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6