Fri Apr 15 20:39:49 2016

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

struct  ast_dsp
struct  digit_detect_state_t
struct  dtmf_detect_state_t
struct  fragment_t
struct  goertzel_result_t
struct  goertzel_state_t
struct  mf_detect_state_t
struct  progalias
struct  progress
struct  tone_detect_state_t

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#define CONFIG_FILE_NAME   "dsp.conf"
#define DEF_DTMF_HITS_TO_BEGIN   2
#define DEF_DTMF_MISSES_TO_END   3
#define DEF_DTMF_NORMAL_TWIST   6.31
#define DEF_DTMF_REVERSE_TWIST   2.51
#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31
#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98
#define DEFAULT_THRESHOLD   512
 This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
#define DSP_HISTORY   15
#define DTMF_2ND_HARMONIC_COL   63.1
#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)
#define DTMF_GSIZE   102
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_THRESHOLD   8.0e7
#define FAX_TONE_CED_DB   16
#define FAX_TONE_CED_DURATION   2600
#define FAX_TONE_CED_FREQ   2100
#define FAX_TONE_CNG_DB   16
#define FAX_TONE_CNG_DURATION   500
#define FAX_TONE_CNG_FREQ   1100
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define SAMPLE_RATE   8000
#define SAMPLES_IN_FRAME   160
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0

Enumerations

enum  busy_detect {
  BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 7, BUSY_THRESHOLD = 100, BUSY_MIN = 75,
  BUSY_MAX = 3100
}
enum  freq_index {
  HZ_350 = 0, HZ_440, HZ_480, HZ_620,
  HZ_950, HZ_1400, HZ_1800, HZ_425 = 0,
  HZ_350UK = 0, HZ_400UK, HZ_440UK
}
enum  gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 }
enum  gsamp_thresh {
  THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4,
  THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300
}
enum  prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK }

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static int __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
static int _dsp_init (int reload)
static void ast_digit_detect_init (digit_detect_state_t *s, int mf)
int ast_dsp_busydetect (struct ast_dsp *dsp)
 Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
 Scans for progress indication in audio.
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector.
void ast_dsp_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf.
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_init (void)
 Load dsp settings from dsp.conf.
struct ast_dspast_dsp_new (void)
int ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
 Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
struct ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
int ast_dsp_reload (void)
 Reloads dsp settings from dsp.conf.
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength)
 Set expected lengths of the busy tone.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
int ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode.
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set.
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set threshold value for silence.
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
int ast_dsp_was_muted (struct ast_dsp *dsp)
 Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.
static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void ast_fax_detect_init (struct ast_dsp *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static void ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp)
static int dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void goertzel_init (goertzel_state_t *s, float freq, int samples)
static void goertzel_reset (goertzel_state_t *s)
static float goertzel_result (goertzel_state_t *s)
static void goertzel_sample (goertzel_state_t *s, short sample)
static void goertzel_update (goertzel_state_t *s, short *samps, int count)
static int mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void mute_fragment (struct ast_dsp *dsp, fragment_t *fragment)
static int pair_there (float p1, float p2, float i1, float i2, float e)
static void store_digit (digit_detect_state_t *s, char digit)
static int tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)

Variables

static struct progalias aliases []
static const char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static const int DEFAULT_SILENCE_THRESHOLD = 256
 The default silence threshold we will use if an alternate configured value is not present or is invalid.
static const float dtmf_col []
static int dtmf_hits_to_begin
static int dtmf_misses_to_end
static float dtmf_normal_twist
static const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_reverse_twist
static const float dtmf_row []
static const float mf_tones []
static struct progress modes []
static float relax_dtmf_normal_twist
static float relax_dtmf_reverse_twist
static int thresholds [THRESHOLD_MAX]

Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>
Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 184 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 182 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 183 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 237 of file dsp.c.

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 224 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 229 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_NORMAL_TWIST   6.31

Definition at line 165 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_REVERSE_TWIST   2.51

Definition at line 172 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31

Definition at line 166 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98

Definition at line 173 of file dsp.c.

Referenced by _dsp_init().

#define DEFAULT_THRESHOLD   512

This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.

Definition at line 121 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 132 of file dsp.c.

Referenced by __ast_dsp_silence_noise(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().

#define DTMF_2ND_HARMONIC_COL   63.1

Definition at line 179 of file dsp.c.

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 178 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 219 of file dsp.c.

Referenced by ast_dtmf_detect_init(), and dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 177 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 176 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 161 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 180 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 163 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 162 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 203 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 202 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 201 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 195 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 194 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 193 of file dsp.c.

Referenced by ast_fax_detect_init().

#define MAX_DTMF_DIGITS   128

Definition at line 147 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 216 of file dsp.c.

Referenced by ast_mf_detect_init(), and mf_detect().

#define SAMPLE_RATE   8000

Definition at line 205 of file dsp.c.

#define SAMPLES_IN_FRAME   160

Definition at line 213 of file dsp.c.

Referenced by ast_tone_detect_init().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 135 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 134 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

Enumerator:
BUSY_PERCENT 

The percentage difference between the two last silence periods

BUSY_PAT_PERCENT 

The percentage difference between measured and actual pattern

BUSY_THRESHOLD 

Max number of ms difference between max and min times in busy

BUSY_MIN 

Busy must be at least 80 ms in half-cadence

BUSY_MAX 

Busy can't be longer than 3100 ms in half-cadence

Definition at line 123 of file dsp.c.

00123                  {
00124    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last silence periods */
00125    BUSY_PAT_PERCENT = 7,   /*!< The percentage difference between measured and actual pattern */
00126    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00127    BUSY_MIN = 75,          /*!< Busy must be at least 80 ms in half-cadence */
00128    BUSY_MAX =3100          /*!< Busy can't be longer than 3100 ms in half-cadence */
00129 };

enum freq_index
Enumerator:
HZ_350 

For US modes {

HZ_440 
HZ_480 
HZ_620 
HZ_950 
HZ_1400 
HZ_1800 

}

HZ_425 

For CR/BR modes

HZ_350UK 

For UK mode

HZ_400UK 
HZ_440UK 

Definition at line 75 of file dsp.c.

00075                 { 
00076    /*! For US modes { */
00077    HZ_350 = 0,
00078    HZ_440,
00079    HZ_480,
00080    HZ_620,
00081    HZ_950,
00082    HZ_1400,
00083    HZ_1800, /*!< } */
00084 
00085    /*! For CR/BR modes */
00086    HZ_425 = 0,
00087 
00088    /*! For UK mode */
00089    HZ_350UK = 0,
00090    HZ_400UK,
00091    HZ_440UK
00092 };

enum gsamp_size

Number of goertzels for progress detect

Enumerator:
GSAMP_SIZE_NA 

North America - 350, 440, 480, 620, 950, 1400, 1800 Hz

GSAMP_SIZE_CR 

Costa Rica, Brazil - Only care about 425 Hz

GSAMP_SIZE_UK 

UK disconnect goertzel feed - should trigger 400hz

Definition at line 63 of file dsp.c.

00063                 {
00064    GSAMP_SIZE_NA = 183,       /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
00065    GSAMP_SIZE_CR = 188,       /*!< Costa Rica, Brazil - Only care about 425 Hz */
00066    GSAMP_SIZE_UK = 160        /*!< UK disconnect goertzel feed - should trigger 400hz */
00067 };

All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)

Enumerator:
THRESH_RING 

Need at least 150ms ring to accept

THRESH_TALK 

Talk detection does not work continuously

THRESH_BUSY 

Need at least 80ms to accept

THRESH_CONGESTION 

Need at least 80ms to accept

THRESH_HANGUP 

Need at least 1300ms to accept hangup

THRESH_RING2ANSWER 

Timeout from start of ring to answer (about 6600 ms)

Definition at line 138 of file dsp.c.

00138                   {
00139    THRESH_RING = 8,           /*!< Need at least 150ms ring to accept */
00140    THRESH_TALK = 2,           /*!< Talk detection does not work continuously */
00141    THRESH_BUSY = 4,           /*!< Need at least 80ms to accept */
00142    THRESH_CONGESTION = 4,     /*!< Need at least 80ms to accept */
00143    THRESH_HANGUP = 60,        /*!< Need at least 1300ms to accept hangup */
00144    THRESH_RING2ANSWER = 300   /*!< Timeout from start of ring to answer (about 6600 ms) */
00145 };

enum prog_mode
Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 69 of file dsp.c.

00069                {
00070    PROG_MODE_NA = 0,
00071    PROG_MODE_CR,
00072    PROG_MODE_UK
00073 };


Function Documentation

static int __ast_dsp_call_progress ( struct ast_dsp dsp,
short *  s,
int  len 
) [static]

Definition at line 1033 of file dsp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_350UK, HZ_400UK, HZ_425, HZ_440, HZ_440UK, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

01034 {
01035    int x;
01036    int y;
01037    int pass;
01038    int newstate = DSP_TONE_STATE_SILENCE;
01039    int res = 0;
01040    while (len) {
01041       /* Take the lesser of the number of samples we need and what we have */
01042       pass = len;
01043       if (pass > dsp->gsamp_size - dsp->gsamps) {
01044          pass = dsp->gsamp_size - dsp->gsamps;
01045       }
01046       for (x = 0; x < pass; x++) {
01047          for (y = 0; y < dsp->freqcount; y++) {
01048             goertzel_sample(&dsp->freqs[y], s[x]);
01049          }
01050          dsp->genergy += s[x] * s[x];
01051       }
01052       s += pass;
01053       dsp->gsamps += pass;
01054       len -= pass;
01055       if (dsp->gsamps == dsp->gsamp_size) {
01056          float hz[7];
01057          for (y = 0; y < 7; y++) {
01058             hz[y] = goertzel_result(&dsp->freqs[y]);
01059          }
01060          switch (dsp->progmode) {
01061          case PROG_MODE_NA:
01062             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
01063                newstate = DSP_TONE_STATE_BUSY;
01064             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01065                newstate = DSP_TONE_STATE_RINGING;
01066             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01067                newstate = DSP_TONE_STATE_DIALTONE;
01068             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01069                newstate = DSP_TONE_STATE_SPECIAL1;
01070             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01071                /* End of SPECIAL1 or middle of SPECIAL2 */
01072                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
01073                   newstate = DSP_TONE_STATE_SPECIAL2;
01074                }
01075             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01076                /* End of SPECIAL2 or middle of SPECIAL3 */
01077                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01078                   newstate = DSP_TONE_STATE_SPECIAL3;
01079                }
01080             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01081                newstate = DSP_TONE_STATE_TALKING;
01082             } else {
01083                newstate = DSP_TONE_STATE_SILENCE;
01084             }
01085             break;
01086          case PROG_MODE_CR:
01087             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01088                newstate = DSP_TONE_STATE_RINGING;
01089             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01090                newstate = DSP_TONE_STATE_TALKING;
01091             } else {
01092                newstate = DSP_TONE_STATE_SILENCE;
01093             }
01094             break;
01095          case PROG_MODE_UK:
01096             if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
01097                newstate = DSP_TONE_STATE_HUNGUP;
01098             } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
01099                newstate = DSP_TONE_STATE_DIALTONE;
01100             }
01101             break;
01102          default:
01103             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
01104          }
01105          if (newstate == dsp->tstate) {
01106             dsp->tcount++;
01107             if (dsp->ringtimeout) {
01108                dsp->ringtimeout++;
01109             }
01110             switch (dsp->tstate) {
01111             case DSP_TONE_STATE_RINGING:
01112                if ((dsp->features & DSP_PROGRESS_RINGING) &&
01113                    (dsp->tcount == THRESH_RING)) {
01114                   res = AST_CONTROL_RINGING;
01115                   dsp->ringtimeout = 1;
01116                }
01117                break;
01118             case DSP_TONE_STATE_BUSY:
01119                if ((dsp->features & DSP_PROGRESS_BUSY) &&
01120                    (dsp->tcount == THRESH_BUSY)) {
01121                   res = AST_CONTROL_BUSY;
01122                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01123                }
01124                break;
01125             case DSP_TONE_STATE_TALKING:
01126                if ((dsp->features & DSP_PROGRESS_TALK) &&
01127                    (dsp->tcount == THRESH_TALK)) {
01128                   res = AST_CONTROL_ANSWER;
01129                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01130                }
01131                break;
01132             case DSP_TONE_STATE_SPECIAL3:
01133                if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01134                    (dsp->tcount == THRESH_CONGESTION)) {
01135                   res = AST_CONTROL_CONGESTION;
01136                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01137                }
01138                break;
01139             case DSP_TONE_STATE_HUNGUP:
01140                if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01141                    (dsp->tcount == THRESH_HANGUP)) {
01142                   res = AST_CONTROL_HANGUP;
01143                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01144                }
01145                break;
01146             }
01147             if (dsp->ringtimeout == THRESH_RING2ANSWER) {
01148                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
01149                res = AST_CONTROL_ANSWER;
01150                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01151             }
01152          } else {
01153             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01154             ast_debug(5, "Start state %d\n", newstate);
01155             dsp->tstate = newstate;
01156             dsp->tcount = 1;
01157          }
01158 
01159          /* Reset goertzel */
01160          for (x = 0; x < 7; x++) {
01161             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01162          }
01163          dsp->gsamps = 0;
01164          dsp->genergy = 0.0;
01165       }
01166    }
01167 
01168    return res;
01169 }

static int __ast_dsp_silence_noise ( struct ast_dsp dsp,
short *  s,
int  len,
int *  totalsilence,
int *  totalnoise 
) [static]

Definition at line 1184 of file dsp.c.

References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalnoise, and ast_dsp::totalsilence.

Referenced by ast_dsp_noise(), ast_dsp_process(), and ast_dsp_silence().

01185 {
01186    int accum;
01187    int x;
01188    int res = 0;
01189 
01190    if (!len) {
01191       return 0;
01192    }
01193    accum = 0;
01194    for (x = 0; x < len; x++) {
01195       accum += abs(s[x]);
01196    }
01197    accum /= len;
01198    if (accum < dsp->threshold) {
01199       /* Silent */
01200       dsp->totalsilence += len / 8;
01201       if (dsp->totalnoise) {
01202          /* Move and save history */
01203          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
01204          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01205 /* we don't want to check for busydetect that frequently */
01206 #if 0
01207          dsp->busymaybe = 1;
01208 #endif
01209       }
01210       dsp->totalnoise = 0;
01211       res = 1;
01212    } else {
01213       /* Not silent */
01214       dsp->totalnoise += len / 8;
01215       if (dsp->totalsilence) {
01216          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01217          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01218          /* Move and save history */
01219          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
01220          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01221          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01222          if (silence1 < silence2) {
01223             if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
01224                dsp->busymaybe = 1;
01225             } else {
01226                dsp->busymaybe = 0;
01227             }
01228          } else {
01229             if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
01230                dsp->busymaybe = 1;
01231             } else {
01232                dsp->busymaybe = 0;
01233             }
01234          }
01235       }
01236       dsp->totalsilence = 0;
01237    }
01238    if (totalsilence) {
01239       *totalsilence = dsp->totalsilence;
01240    }
01241    if (totalnoise) {
01242       *totalnoise = dsp->totalnoise;
01243    }
01244    return res;
01245 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1748 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_log(), ast_variable_browse(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEF_DTMF_HITS_TO_BEGIN, DEF_DTMF_MISSES_TO_END, DEF_DTMF_NORMAL_TWIST, DEF_DTMF_REVERSE_TWIST, DEF_RELAX_DTMF_NORMAL_TWIST, DEF_RELAX_DTMF_REVERSE_TWIST, LOG_WARNING, ast_variable::name, ast_variable::next, THRESHOLD_SILENCE, and ast_variable::value.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01749 {
01750    struct ast_config *cfg;
01751    struct ast_variable *v;
01752    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01753    int cfg_threshold;
01754    float cfg_twist;
01755 
01756    if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
01757       return 0;
01758    }
01759 
01760    thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01761    dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
01762    dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
01763    relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST;
01764    relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST;
01765         dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN;
01766         dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END;
01767 
01768    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01769       return 0;
01770    }
01771 
01772    for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
01773       if (!strcasecmp(v->name, "silencethreshold")) {
01774          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01775             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01776          } else if (cfg_threshold < 0) {
01777             ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
01778          } else {
01779             thresholds[THRESHOLD_SILENCE] = cfg_threshold;
01780          }
01781       } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
01782          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01783             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01784          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01785             ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
01786          } else {
01787             dtmf_normal_twist = cfg_twist;
01788          }
01789       } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
01790          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01791             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01792          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01793             ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
01794          } else {
01795             dtmf_reverse_twist = cfg_twist;
01796          }
01797       } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
01798          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01799             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01800          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01801             ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
01802          } else {
01803             relax_dtmf_normal_twist = cfg_twist;
01804          }
01805       } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
01806          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01807             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01808          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01809             ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
01810          } else {
01811             relax_dtmf_reverse_twist = cfg_twist;
01812          }
01813       } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
01814          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01815             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01816          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01817             ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
01818          } else {
01819             dtmf_hits_to_begin = cfg_threshold;
01820          }
01821       } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
01822          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01823             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01824          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01825             ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
01826          } else {
01827             dtmf_misses_to_end = cfg_threshold;
01828          }
01829       }
01830    }
01831    ast_config_destroy(cfg);
01832 
01833    return 0;
01834 }

static void ast_digit_detect_init ( digit_detect_state_t s,
int  mf 
) [static]
int ast_dsp_busydetect ( struct ast_dsp dsp  ) 

Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.

Definition at line 1247 of file dsp.c.

References ast_debug, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, and MAX.

Referenced by ast_dsp_process().

01248 {
01249    int res = 0, x;
01250 #ifndef BUSYDETECT_TONEONLY
01251    int avgsilence = 0, hitsilence = 0;
01252 #endif
01253    int avgtone = 0, hittone = 0;
01254    if (!dsp->busymaybe) {
01255       return res;
01256    }
01257    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01258 #ifndef BUSYDETECT_TONEONLY
01259       avgsilence += dsp->historicsilence[x];
01260 #endif
01261       avgtone += dsp->historicnoise[x];
01262    }
01263 #ifndef BUSYDETECT_TONEONLY
01264    avgsilence /= dsp->busycount;
01265 #endif
01266    avgtone /= dsp->busycount;
01267    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01268 #ifndef BUSYDETECT_TONEONLY
01269       if (avgsilence > dsp->historicsilence[x]) {
01270          if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
01271             hitsilence++;
01272          }
01273       } else {
01274          if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
01275             hitsilence++;
01276          }
01277       }
01278 #endif
01279       if (avgtone > dsp->historicnoise[x]) {
01280          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01281             hittone++;
01282          }
01283       } else {
01284          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01285             hittone++;
01286          }
01287       }
01288    }
01289 #ifndef BUSYDETECT_TONEONLY
01290    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01291        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01292        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01293 #else
01294    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01295 #endif
01296 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01297       if (avgtone > avgsilence) {
01298          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
01299             res = 1;
01300          }
01301       } else {
01302          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
01303             res = 1;
01304          }
01305       }
01306 #else
01307       res = 1;
01308 #endif
01309    }
01310    /* If we know the expected busy tone length, check we are in the range */
01311    if (res && (dsp->busy_tonelength > 0)) {
01312       if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*BUSY_PAT_PERCENT/100, 20)) {
01313 #ifdef BUSYDETECT_DEBUG
01314          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01315             avgtone, dsp->busy_tonelength);
01316 #endif
01317          res = 0;
01318       }
01319    }
01320 #ifndef BUSYDETECT_TONEONLY
01321    /* If we know the expected busy tone silent-period length, check we are in the range */
01322    if (res && (dsp->busy_quietlength > 0)) {
01323       if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*BUSY_PAT_PERCENT/100, 20)) {
01324 #ifdef BUSYDETECT_DEBUG
01325       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01326          avgsilence, dsp->busy_quietlength);
01327 #endif
01328          res = 0;
01329       }
01330    }
01331 #endif
01332 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01333    if (res) {
01334       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01335    } else {
01336       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01337    }
01338 #endif
01339    return res;
01340 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1171 of file dsp.c.

References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.

01172 {
01173    if (inf->frametype != AST_FRAME_VOICE) {
01174       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01175       return 0;
01176    }
01177    if (inf->subclass.codec != AST_FORMAT_SLINEAR) {
01178       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01179       return 0;
01180    }
01181    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01182 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1650 of file dsp.c.

References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, mf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, ast_dsp::dtmf_began, dtmf_detect_state_t::energy, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::misses, dtmf_detect_state_t::row_out, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by analog_ss_thread(), and my_dsp_reset_and_flush_digits().

01651 {
01652    int i;
01653    
01654    dsp->dtmf_began = 0;
01655    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01656       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01657       /* Reinitialise the detector for the next block */
01658       for (i = 0;  i < 6;  i++) {
01659          goertzel_reset(&s->tone_out[i]);
01660       }
01661       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01662       s->current_sample = 0;
01663    } else {
01664       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01665       /* Reinitialise the detector for the next block */
01666       for (i = 0;  i < 4;  i++) {
01667          goertzel_reset(&s->row_out[i]);
01668          goertzel_reset(&s->col_out[i]);
01669       }
01670       s->lasthit = s->current_hit = 0;
01671       s->energy = 0.0;
01672       s->current_sample = 0;
01673       s->hits = 0;
01674       s->misses = 0;
01675    }
01676 
01677    dsp->digit_state.digits[0] = '\0';
01678    dsp->digit_state.current_digits = 0;
01679 }

void ast_dsp_free ( struct ast_dsp dsp  ) 
int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1743 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01744 {
01745    return dsp->tcount;
01746 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1836 of file dsp.c.

Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), and setup_privacy_args().

01837 {
01838    return thresholds[which];
01839 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1738 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01739 {
01740    return dsp->tstate;
01741 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1841 of file dsp.c.

References _dsp_init().

Referenced by main().

01842 {
01843    return _dsp_init(0);
01844 }

struct ast_dsp* ast_dsp_new ( void   )  [read]
int ast_dsp_noise ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalnoise 
)

Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.

Since:
1.6.1

Definition at line 1360 of file dsp.c.

References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.

Referenced by do_waiting().

01361 {
01362        short *s;
01363        int len;
01364 
01365        if (f->frametype != AST_FRAME_VOICE) {
01366                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01367                return 0;
01368        }
01369        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01370                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01371                return 0;
01372        }
01373        s = f->data.ptr;
01374        len = f->datalen/2;
01375        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01376 }

struct ast_frame* ast_dsp_process ( struct ast_channel chan,
struct ast_dsp dsp,
struct ast_frame af 
) [read]

Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.

Definition at line 1379 of file dsp.c.

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), ast_channel::_softhangup, AST_ALAW, ast_alloca, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_frisolate(), ast_getformatname(), AST_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_frame_subclass::codec, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, digit_detect_state_t::digitlen, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame::frametype, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_frame_subclass::integer, ast_frame::len, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_frame::ptr, SAMPLE_RATE, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().

01380 {
01381    int silence;
01382    int res;
01383    int digit = 0, fax_digit = 0;
01384    int x;
01385    short *shortdata;
01386    unsigned char *odata;
01387    int len;
01388    struct ast_frame *outf = NULL;
01389 
01390    if (!af) {
01391       return NULL;
01392    }
01393    if (af->frametype != AST_FRAME_VOICE) {
01394       return af;
01395    }
01396 
01397    odata = af->data.ptr;
01398    len = af->datalen;
01399    /* Make sure we have short data */
01400    switch (af->subclass.codec) {
01401    case AST_FORMAT_SLINEAR:
01402       shortdata = af->data.ptr;
01403       len = af->datalen / 2;
01404       break;
01405    case AST_FORMAT_ULAW:
01406    case AST_FORMAT_TESTLAW:
01407       shortdata = ast_alloca(af->datalen * 2);
01408       for (x = 0;x < len; x++) {
01409          shortdata[x] = AST_MULAW(odata[x]);
01410       }
01411       break;
01412    case AST_FORMAT_ALAW:
01413       shortdata = ast_alloca(af->datalen * 2);
01414       for (x = 0; x < len; x++) {
01415          shortdata[x] = AST_ALAW(odata[x]);
01416       }
01417       break;
01418    default:
01419       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01420       if (dsp->display_inband_dtmf_warning)
01421          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec));
01422       dsp->display_inband_dtmf_warning = 0;
01423       return af;
01424    }
01425 
01426    /* Initially we do not want to mute anything */
01427    dsp->mute_fragments = 0;
01428 
01429    /* Need to run the silence detection stuff for silence suppression and busy detection */
01430    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01431       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01432    }
01433 
01434    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01435       memset(&dsp->f, 0, sizeof(dsp->f));
01436       dsp->f.frametype = AST_FRAME_NULL;
01437       ast_frfree(af);
01438       return ast_frisolate(&dsp->f);
01439    }
01440    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01441       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01442       memset(&dsp->f, 0, sizeof(dsp->f));
01443       dsp->f.frametype = AST_FRAME_CONTROL;
01444       dsp->f.subclass.integer = AST_CONTROL_BUSY;
01445       ast_frfree(af);
01446       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01447       return ast_frisolate(&dsp->f);
01448    }
01449 
01450    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01451       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01452          fax_digit = 'f';
01453       }
01454 
01455       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01456          fax_digit = 'e';
01457       }
01458    }
01459 
01460    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01461       if (dsp->digitmode & DSP_DIGITMODE_MF)
01462          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01463       else
01464          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
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 / 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             break;
01536          default:
01537             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01538          }
01539       }
01540    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01541       res = __ast_dsp_call_progress(dsp, shortdata, len);
01542    }
01543 
01544 done:
01545    /* Mute fragment of the frame */
01546    for (x = 0; x < dsp->mute_fragments; x++) {
01547       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01548    }
01549 
01550    switch (af->subclass.codec) {
01551    case AST_FORMAT_SLINEAR:
01552       break;
01553    case AST_FORMAT_ULAW:
01554       for (x = 0; x < len; x++) {
01555          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01556       }
01557       break;
01558    case AST_FORMAT_ALAW:
01559       for (x = 0; x < len; x++) {
01560          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01561       }
01562       break;
01563    }
01564 
01565    if (outf) {
01566       if (chan) {
01567          ast_queue_frame(chan, af);
01568       }
01569       ast_frfree(af);
01570       return ast_frisolate(outf);
01571    } else {
01572       return af;
01573    }
01574 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1576 of file dsp.c.

References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, ast_dsp::ringtimeout, and progress::size.

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01577 {
01578    int max = 0;
01579    int x;
01580    
01581    dsp->gsamp_size = modes[dsp->progmode].size;
01582    dsp->gsamps = 0;
01583    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01584       if (modes[dsp->progmode].freqs[x]) {
01585          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01586          max = x + 1;
01587       }
01588    }
01589    dsp->freqcount = max;
01590    dsp->ringtimeout= 0;
01591 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1846 of file dsp.c.

References _dsp_init().

01847 {
01848    return _dsp_init(1);
01849 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

Definition at line 1681 of file dsp.c.

References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::ringtimeout, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by debug_check_frame_for_silence().

01682 {
01683    int x;
01684    
01685    dsp->totalsilence = 0;
01686    dsp->gsamps = 0;
01687    for (x = 0; x < 4; x++) {
01688       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01689    }
01690    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01691    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01692    dsp->ringtimeout= 0;
01693 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1632 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01633 {
01634    if (cadences < 4) {
01635       cadences = 4;
01636    }
01637    if (cadences > DSP_HISTORY) {
01638       cadences = DSP_HISTORY;
01639    }
01640    dsp->busycount = cadences;
01641 }

void ast_dsp_set_busy_pattern ( struct ast_dsp dsp,
int  tonelength,
int  quietlength 
)

Set expected lengths of the busy tone.

Definition at line 1643 of file dsp.c.

References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.

Referenced by dahdi_new().

01644 {
01645    dsp->busy_tonelength = tonelength;
01646    dsp->busy_quietlength = quietlength;
01647    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01648 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1719 of file dsp.c.

References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.

Referenced by dahdi_new().

01720 {
01721    int x;
01722    
01723    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01724       if (!strcasecmp(aliases[x].name, zone)) {
01725          dsp->progmode = aliases[x].mode;
01726          ast_dsp_prog_reset(dsp);
01727          return 0;
01728       }
01729    }
01730    return -1;
01731 }

int ast_dsp_set_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Version:
1.6.1 renamed from ast_dsp_digitmode to ast_dsp_set_digitmode

Definition at line 1695 of file dsp.c.

References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), mkintf(), and my_dsp_set_digitmode().

01696 {
01697    int new;
01698    int old;
01699    
01700    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01701    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01702    if (old != new) {
01703       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01704       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01705    }
01706    dsp->digitmode = digitmode;
01707    return 0;
01708 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1710 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01711 {
01712    if (dsp->faxmode != faxmode) {
01713       ast_fax_detect_init(dsp);
01714    }
01715    dsp->faxmode = faxmode;
01716    return 0;
01717 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)
void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1627 of file dsp.c.

References ast_dsp::threshold.

Referenced by __ast_play_and_record(), do_waiting(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), and record_exec().

01628 {
01629    dsp->threshold = threshold;
01630 }

int ast_dsp_silence ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalsilence 
)

Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.

Definition at line 1342 of file dsp.c.

References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.

Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), debug_check_frame_for_silence(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().

01343 {
01344    short *s;
01345    int len;
01346    
01347    if (f->frametype != AST_FRAME_VOICE) {
01348       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01349       return 0;
01350    }
01351    if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01352       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01353       return 0;
01354    }
01355    s = f->data.ptr;
01356    len = f->datalen/2;
01357    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01358 }

int ast_dsp_was_muted ( struct ast_dsp dsp  ) 

Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.

Since:
1.6.1

Definition at line 1733 of file dsp.c.

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01734 {
01735    return (dsp->mute_fragments > 0);
01736 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 498 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, DTMF_GSIZE, dtmf_detect_state_t::energy, goertzel_init(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, and dtmf_detect_state_t::row_out.

Referenced by ast_digit_detect_init().

00499 {
00500    int i;
00501 
00502    s->lasthit = 0;
00503    s->current_hit = 0;
00504    for (i = 0;  i < 4;  i++) {
00505       goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE);
00506       goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE);
00507       s->energy = 0.0;
00508    }
00509    s->current_sample = 0;
00510    s->hits = 0;
00511    s->misses = 0;
00512 }

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]
static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 514 of file dsp.c.

References mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, goertzel_init(), mf_detect_state_t::hits, MF_GSIZE, and mf_detect_state_t::tone_out.

Referenced by ast_digit_detect_init().

00515 {
00516    int i;
00517    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00518    for (i = 0;  i < 6;  i++) {
00519       goertzel_init (&s->tone_out[i], mf_tones[i], MF_GSIZE);
00520    }
00521    s->current_sample = 0;
00522    s->current_hit = 0;
00523 }

static void ast_tone_detect_init ( tone_detect_state_t s,
int  freq,
int  duration,
int  amp 
) [static]

Definition at line 432 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_init(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, SAMPLE_RATE, SAMPLES_IN_FRAME, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_fax_detect_init().

00433 {
00434    int duration_samples;
00435    float x;
00436    int periods_in_block;
00437 
00438    s->freq = freq;
00439 
00440    /* Desired tone duration in samples */
00441    duration_samples = duration * SAMPLE_RATE / 1000;
00442    /* We want to allow 10% deviation of tone duration */
00443    duration_samples = duration_samples * 9 / 10;
00444 
00445    /* If we want to remove tone, it is important to have block size not
00446       to exceed frame size. Otherwise by the moment tone is detected it is too late
00447       to squelch it from previous frames */
00448    s->block_size = SAMPLES_IN_FRAME;
00449 
00450    periods_in_block = s->block_size * freq / SAMPLE_RATE;
00451 
00452    /* Make sure we will have at least 5 periods at target frequency for analisys.
00453       This may make block larger than expected packet and will make squelching impossible
00454       but at least we will be detecting the tone */
00455    if (periods_in_block < 5)
00456       periods_in_block = 5;
00457 
00458    /* Now calculate final block size. It will contain integer number of periods */
00459    s->block_size = periods_in_block * SAMPLE_RATE / freq;
00460 
00461    /* tone_detect is currently only used to detect fax tones and we
00462       do not need squelching the fax tones */
00463    s->squelch = 0;
00464 
00465    /* Account for the first and the last block to be incomplete
00466       and thus no tone will be detected in them */
00467    s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
00468 
00469    goertzel_init(&s->tone, freq, s->block_size);
00470 
00471    s->samples_pending = s->block_size;
00472    s->hit_count = 0;
00473    s->last_hit = 0;
00474    s->energy = 0.0;
00475 
00476    /* We want tone energy to be amp decibels above the rest of the signal (the noise).
00477       According to Parseval's theorem the energy computed in time domain equals to energy
00478       computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
00479       from the energy in the time domain we will get energy of the remaining signal (without the tone
00480       we are detecting). We will be checking that
00481       10*log(Ew / (Et - Ew)) > amp
00482       Calculate threshold so that we will be actually checking
00483       Ew > Et * threshold
00484    */
00485 
00486    x = pow(10.0, amp / 10.0);
00487    s->threshold = x / (x + 1);
00488 
00489    ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
00490 }

static int dtmf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
) [static]

Definition at line 658 of file dsp.c.

References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, digit_detect_state_t::digitlen, digit_detect_state_t::dtmf, DTMF_GSIZE, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, fragment_t::end, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, mute, mute_fragment(), dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, fragment_t::start, store_digit(), and digit_detect_state_t::td.

Referenced by ast_dsp_process().

00659 {
00660    float row_energy[4];
00661    float col_energy[4];
00662    int i;
00663    int j;
00664    int sample;
00665    short samp;
00666    int best_row;
00667    int best_col;
00668    int hit;
00669    int limit;
00670    fragment_t mute = {0, 0};
00671 
00672    if (squelch && s->td.dtmf.mute_samples > 0) {
00673       mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
00674       s->td.dtmf.mute_samples -= mute.end;
00675    }
00676 
00677    hit = 0;
00678    for (sample = 0; sample < samples; sample = limit) {
00679       /* DTMF_GSIZE is optimised to meet the DTMF specs. */
00680       if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
00681          limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
00682       } else {
00683          limit = samples;
00684       }
00685       /* The following unrolled loop takes only 35% (rough estimate) of the 
00686          time of a rolled loop on the machine on which it was developed */
00687       for (j = sample; j < limit; j++) {
00688          samp = amp[j];
00689          s->td.dtmf.energy += (int32_t) samp * (int32_t) samp;
00690          /* With GCC 2.95, the following unrolled code seems to take about 35%
00691             (rough estimate) as long as a neat little 0-3 loop */
00692          goertzel_sample(s->td.dtmf.row_out, samp);
00693          goertzel_sample(s->td.dtmf.col_out, samp);
00694          goertzel_sample(s->td.dtmf.row_out + 1, samp);
00695          goertzel_sample(s->td.dtmf.col_out + 1, samp);
00696          goertzel_sample(s->td.dtmf.row_out + 2, samp);
00697          goertzel_sample(s->td.dtmf.col_out + 2, samp);
00698          goertzel_sample(s->td.dtmf.row_out + 3, samp);
00699          goertzel_sample(s->td.dtmf.col_out + 3, samp);
00700       }
00701       s->td.dtmf.current_sample += (limit - sample);
00702       if (s->td.dtmf.current_sample < DTMF_GSIZE) {
00703          continue;
00704       }
00705       /* We are at the end of a DTMF detection block */
00706       /* Find the peak row and the peak column */
00707       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00708       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00709 
00710       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00711          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00712          if (row_energy[i] > row_energy[best_row]) {
00713             best_row = i;
00714          }
00715          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00716          if (col_energy[i] > col_energy[best_col]) {
00717             best_col = i;
00718          }
00719       }
00720       hit = 0;
00721       /* Basic signal level test and the twist test */
00722       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00723           col_energy[best_col] >= DTMF_THRESHOLD &&
00724           col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
00725           row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
00726          /* Relative peak test */
00727          for (i = 0;  i < 4;  i++) {
00728             if ((i != best_col &&
00729                 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00730                 (i != best_row 
00731                  && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00732                break;
00733             }
00734          }
00735          /* ... and fraction of total energy test */
00736          if (i >= 4 &&
00737              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
00738             /* Got a hit */
00739             hit = dtmf_positions[(best_row << 2) + best_col];
00740          }
00741       } 
00742 
00743 /*
00744  * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03)
00745  * (40ms reference is tunable with hits_to_begin and misses_to_end)
00746  * each hit/miss is 12.75ms with DTMF_GSIZE at 102
00747  *
00748  * Character recognition: When not DRC *(1) and then
00749  *      Shall exist VSC > 40 ms (hits_to_begin)
00750  *      May exist 20 ms <= VSC <= 40 ms
00751  *      Shall not exist VSC < 20 ms
00752  *
00753  * Character recognition: When DRC and then
00754  *      Shall cease Not VSC > 40 ms (misses_to_end)
00755  *      May cease 20 ms >= Not VSC >= 40 ms
00756  *      Shall not cease Not VSC < 20 ms
00757  *
00758  * *(1) or optionally a different digit recognition condition
00759  *
00760  * Legend: VSC The continuous existence of a valid signal condition.
00761  *      Not VSC The continuous non-existence of valid signal condition.
00762  *      DRC The existence of digit recognition condition.
00763  *      Not DRC The non-existence of digit recognition condition.
00764  */
00765 
00766 /*
00767  * Example: hits_to_begin=2 misses_to_end=3
00768  * -------A last_hit=A hits=0&1
00769  * ------AA hits=2 current_hit=A misses=0       BEGIN A
00770  * -----AA- misses=1 last_hit=' ' hits=0
00771  * ----AA-- misses=2
00772  * ---AA--- misses=3 current_hit=' '            END A
00773  * --AA---B last_hit=B hits=0&1
00774  * -AA---BC last_hit=C hits=0&1
00775  * AA---BCC hits=2 current_hit=C misses=0       BEGIN C
00776  * A---BCC- misses=1 last_hit=' ' hits=0
00777  * ---BCC-C misses=0 last_hit=C hits=0&1
00778  * --BCC-CC misses=0
00779  *
00780  * Example: hits_to_begin=3 misses_to_end=2
00781  * -------A last_hit=A hits=0&1
00782  * ------AA hits=2
00783  * -----AAA hits=3 current_hit=A misses=0       BEGIN A
00784  * ----AAAB misses=1 last_hit=B hits=0&1
00785  * ---AAABB misses=2 current_hit=' ' hits=2     END A
00786  * --AAABBB hits=3 current_hit=B misses=0       BEGIN B
00787  * -AAABBBB misses=0
00788  *
00789  * Example: hits_to_begin=2 misses_to_end=2
00790  * -------A last_hit=A hits=0&1
00791  * ------AA hits=2 current_hit=A misses=0       BEGIN A
00792  * -----AAB misses=1 hits=0&1
00793  * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B
00794  * ---AABBB misses=0
00795  */
00796 
00797       if (s->td.dtmf.current_hit) {
00798          /* We are in the middle of a digit already */
00799          if (hit != s->td.dtmf.current_hit) {
00800             s->td.dtmf.misses++;
00801             if (s->td.dtmf.misses == dtmf_misses_to_end) {
00802                /* There were enough misses to consider digit ended */
00803                s->td.dtmf.current_hit = 0;
00804             }
00805          } else {
00806             s->td.dtmf.misses = 0;
00807             /* Current hit was same as last, so increment digit duration (of last digit) */
00808             s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
00809          }
00810       }
00811 
00812       /* Look for a start of a new digit no matter if we are already in the middle of some
00813          digit or not. This is because hits_to_begin may be smaller than misses_to_end
00814          and we may find begin of new digit before we consider last one ended. */
00815 
00816       if (hit != s->td.dtmf.lasthit) {
00817          s->td.dtmf.lasthit = hit;
00818          s->td.dtmf.hits = 0;
00819       }
00820       if (hit && hit != s->td.dtmf.current_hit) {
00821          s->td.dtmf.hits++;
00822          if (s->td.dtmf.hits == dtmf_hits_to_begin) {
00823             store_digit(s, hit);
00824             s->digitlen[s->current_digits - 1] = dtmf_hits_to_begin * DTMF_GSIZE;
00825             s->td.dtmf.current_hit = hit;
00826             s->td.dtmf.misses = 0;
00827          }
00828       }
00829 
00830       /* If we had a hit in this block, include it into mute fragment */
00831       if (squelch && hit) {
00832          if (mute.end < sample - DTMF_GSIZE) {
00833             /* There is a gap between fragments */
00834             mute_fragment(dsp, &mute);
00835             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00836          }
00837          mute.end = limit + DTMF_GSIZE;
00838       }
00839 
00840       /* Reinitialise the detector for the next block */
00841       for (i = 0; i < 4; i++) {
00842          goertzel_reset(&s->td.dtmf.row_out[i]);
00843          goertzel_reset(&s->td.dtmf.col_out[i]);
00844       }
00845       s->td.dtmf.energy = 0.0;
00846       s->td.dtmf.current_sample = 0;
00847    }
00848 
00849    if (squelch && mute.end) {
00850       if (mute.end > samples) {
00851          s->td.dtmf.mute_samples = mute.end - samples;
00852          mute.end = samples;
00853       }
00854       mute_fragment(dsp, &mute);
00855    }
00856 
00857    return (s->td.dtmf.current_hit); /* return the debounced hit */
00858 }

static void goertzel_init ( goertzel_state_t s,
float  freq,
int  samples 
) [inline, static]

Definition at line 360 of file dsp.c.

References goertzel_state_t::chunky, cos, goertzel_state_t::fac, M_PI, SAMPLE_RATE, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().

00361 {
00362    s->v2 = s->v3 = s->chunky = 0.0;
00363    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00364    s->samples = samples;
00365 }

static void goertzel_reset ( goertzel_state_t s  )  [inline, static]

Definition at line 367 of file dsp.c.

References goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_digitreset(), dtmf_detect(), mf_detect(), and tone_detect().

00368 {
00369    s->v2 = s->v3 = s->chunky = 0.0;
00370 }

static float goertzel_result ( goertzel_state_t s  )  [inline, static]

Definition at line 351 of file dsp.c.

References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_result_t::power, goertzel_state_t::v2, goertzel_state_t::v3, and goertzel_result_t::value.

Referenced by __ast_dsp_call_progress(), dtmf_detect(), mf_detect(), and tone_detect().

00352 {
00353    goertzel_result_t r;
00354    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00355    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00356    r.power = s->chunky * 2;
00357    return (float)r.value * (float)(1 << r.power);
00358 }

static void goertzel_sample ( goertzel_state_t s,
short  sample 
) [inline, static]

Definition at line 325 of file dsp.c.

References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_call_progress(), dtmf_detect(), goertzel_update(), mf_detect(), and tone_detect().

00326 {
00327    int v1;
00328    
00329    v1 = s->v2;
00330    s->v2 = s->v3;
00331    
00332    s->v3 = (s->fac * s->v2) >> 15;
00333    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00334    if (abs(s->v3) > 32768) {
00335       s->chunky++;
00336       s->v3 = s->v3 >> 1;
00337       s->v2 = s->v2 >> 1;
00338    }
00339 }

static void goertzel_update ( goertzel_state_t s,
short *  samps,
int  count 
) [inline, static]

Definition at line 341 of file dsp.c.

References goertzel_sample().

00342 {
00343    int i;
00344    
00345    for (i = 0; i < count; i++) {
00346       goertzel_sample(s, samps[i]);
00347    }
00348 }

static int mf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
) [static]

Definition at line 860 of file dsp.c.

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute, mute_fragment(), mf_detect_state_t::mute_samples, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_process().

00862 {
00863    float energy[6];
00864    int best;
00865    int second_best;
00866    int i;
00867    int j;
00868    int sample;
00869    short samp;
00870    int hit;
00871    int limit;
00872    fragment_t mute = {0, 0};
00873 
00874    if (squelch && s->td.mf.mute_samples > 0) {
00875       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00876       s->td.mf.mute_samples -= mute.end;
00877    }
00878 
00879    hit = 0;
00880    for (sample = 0;  sample < samples;  sample = limit) {
00881       /* 80 is optimised to meet the MF specs. */
00882       /* XXX So then why is MF_GSIZE defined as 120? */
00883       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00884          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00885       } else {
00886          limit = samples;
00887       }
00888       /* The following unrolled loop takes only 35% (rough estimate) of the 
00889          time of a rolled loop on the machine on which it was developed */
00890       for (j = sample;  j < limit;  j++) {
00891          /* With GCC 2.95, the following unrolled code seems to take about 35%
00892             (rough estimate) as long as a neat little 0-3 loop */
00893          samp = amp[j];
00894          goertzel_sample(s->td.mf.tone_out, samp);
00895          goertzel_sample(s->td.mf.tone_out + 1, samp);
00896          goertzel_sample(s->td.mf.tone_out + 2, samp);
00897          goertzel_sample(s->td.mf.tone_out + 3, samp);
00898          goertzel_sample(s->td.mf.tone_out + 4, samp);
00899          goertzel_sample(s->td.mf.tone_out + 5, samp);
00900       }
00901       s->td.mf.current_sample += (limit - sample);
00902       if (s->td.mf.current_sample < MF_GSIZE) {
00903          continue;
00904       }
00905       /* We're at the end of an MF detection block.  */
00906       /* Find the two highest energies. The spec says to look for
00907          two tones and two tones only. Taking this literally -ie
00908          only two tones pass the minimum threshold - doesn't work
00909          well. The sinc function mess, due to rectangular windowing
00910          ensure that! Find the two highest energies and ensure they
00911          are considerably stronger than any of the others. */
00912       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00913       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00914       if (energy[0] > energy[1]) {
00915          best = 0;
00916          second_best = 1;
00917       } else {
00918          best = 1;
00919          second_best = 0;
00920       }
00921       /*endif*/
00922       for (i = 2; i < 6; i++) {
00923          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00924          if (energy[i] >= energy[best]) {
00925             second_best = best;
00926             best = i;
00927          } else if (energy[i] >= energy[second_best]) {
00928             second_best = i;
00929          }
00930       }
00931       /* Basic signal level and twist tests */
00932       hit = 0;
00933       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00934                && energy[best] < energy[second_best]*BELL_MF_TWIST
00935                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00936          /* Relative peak test */
00937          hit = -1;
00938          for (i = 0; i < 6; i++) {
00939             if (i != best && i != second_best) {
00940                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00941                   /* The best two are not clearly the best */
00942                   hit = 0;
00943                   break;
00944                }
00945             }
00946          }
00947       }
00948       if (hit) {
00949          /* Get the values into ascending order */
00950          if (second_best < best) {
00951             i = best;
00952             best = second_best;
00953             second_best = i;
00954          }
00955          best = best * 5 + second_best - 1;
00956          hit = bell_mf_positions[best];
00957          /* Look for two successive similar results */
00958          /* The logic in the next test is:
00959             For KP we need 4 successive identical clean detects, with
00960             two blocks of something different preceeding it. For anything
00961             else we need two successive identical clean detects, with
00962             two blocks of something different preceeding it. */
00963          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00964             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00965              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00966              hit != s->td.mf.hits[0]))) {
00967             store_digit(s, hit);
00968          }
00969       }
00970 
00971 
00972       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00973          /* Two successive block without a hit terminate current digit */
00974          s->td.mf.current_hit = 0;
00975       }
00976 
00977       s->td.mf.hits[0] = s->td.mf.hits[1];
00978       s->td.mf.hits[1] = s->td.mf.hits[2];
00979       s->td.mf.hits[2] = s->td.mf.hits[3];
00980       s->td.mf.hits[3] = s->td.mf.hits[4];
00981       s->td.mf.hits[4] = hit;
00982 
00983       /* If we had a hit in this block, include it into mute fragment */
00984       if (squelch && hit) {
00985          if (mute.end < sample - MF_GSIZE) {
00986             /* There is a gap between fragments */
00987             mute_fragment(dsp, &mute);
00988             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00989          }
00990          mute.end = limit + MF_GSIZE;
00991       }
00992 
00993       /* Reinitialise the detector for the next block */
00994       for (i = 0;  i < 6;  i++)
00995          goertzel_reset(&s->td.mf.tone_out[i]);
00996       s->td.mf.current_sample = 0;
00997    }
00998 
00999    if (squelch && mute.end) {
01000       if (mute.end > samples) {
01001          s->td.mf.mute_samples = mute.end - samples;
01002          mute.end = samples;
01003       }
01004       mute_fragment(dsp, &mute);
01005    }
01006 
01007    return (s->td.mf.current_hit); /* return the debounced hit */
01008 }

static void mute_fragment ( struct ast_dsp dsp,
fragment_t fragment 
) [static]

Definition at line 422 of file dsp.c.

References ARRAY_LEN, ast_log(), LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.

Referenced by dtmf_detect(), mf_detect(), and tone_detect().

00423 {
00424    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00425       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00426       return;
00427    }
00428 
00429    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00430 }

static int pair_there ( float  p1,
float  p2,
float  i1,
float  i2,
float  e 
) [inline, static]

Definition at line 1010 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

01011 {
01012    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
01013    /* Make sure absolute levels are high enough */
01014    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
01015       return 0;
01016    }
01017    /* Amplify ignored stuff */
01018    i2 *= TONE_THRESH;
01019    i1 *= TONE_THRESH;
01020    e *= TONE_THRESH;
01021    /* Check first tone */
01022    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
01023       return 0;
01024    }
01025    /* And second */
01026    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
01027       return 0;
01028    }
01029    /* Guess it's there... */
01030    return 1;
01031 }

static void store_digit ( digit_detect_state_t s,
char  digit 
) [static]

Definition at line 645 of file dsp.c.

References ast_log(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digitlen, digit_detect_state_t::digits, LOG_WARNING, digit_detect_state_t::lost_digits, and MAX_DTMF_DIGITS.

Referenced by dtmf_detect(), and mf_detect().

00646 {
00647    s->detected_digits++;
00648    if (s->current_digits < MAX_DTMF_DIGITS) {
00649       s->digitlen[s->current_digits] = 0;
00650       s->digits[s->current_digits++] = digit;
00651       s->digits[s->current_digits] = '\0';
00652    } else {
00653       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00654       s->lost_digits++;
00655    }
00656 }

static int tone_detect ( struct ast_dsp dsp,
tone_detect_state_t s,
int16_t *  amp,
int  samples 
) [static]

Definition at line 539 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, fragment_t::end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute, mute_fragment(), tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_dsp_process().

00540 {
00541    float tone_energy;
00542    int i;
00543    int hit = 0;
00544    int limit;
00545    int res = 0;
00546    int16_t *ptr;
00547    short samp;
00548    int start, end;
00549    fragment_t mute = {0, 0};
00550 
00551    if (s->squelch && s->mute_samples > 0) {
00552       mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
00553       s->mute_samples -= mute.end;
00554    }
00555 
00556    for (start = 0;  start < samples;  start = end) {
00557       /* Process in blocks. */
00558       limit = samples - start;
00559       if (limit > s->samples_pending) {
00560          limit = s->samples_pending;
00561       }
00562       end = start + limit;
00563 
00564       for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
00565          samp = *ptr;
00566          /* signed 32 bit int should be enough to square any possible signed 16 bit value */
00567          s->energy += (int32_t) samp * (int32_t) samp;
00568 
00569          goertzel_sample(&s->tone, samp);
00570       }
00571 
00572       s->samples_pending -= limit;
00573 
00574       if (s->samples_pending) {
00575          /* Finished incomplete (last) block */
00576          break;
00577       }
00578 
00579       tone_energy = goertzel_result(&s->tone);
00580 
00581       /* Scale to make comparable */
00582       tone_energy *= 2.0;
00583       s->energy *= s->block_size;
00584 
00585       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));
00586       hit = 0;
00587       if (tone_energy > s->energy * s->threshold) {
00588          ast_debug(10, "Hit! count=%d\n", s->hit_count);
00589          hit = 1;
00590       }
00591 
00592       if (s->hit_count) {
00593          s->hit_count++;
00594       }
00595 
00596       if (hit == s->last_hit) {
00597          if (!hit) {
00598             /* Two successive misses. Tone ended */
00599             s->hit_count = 0;
00600          } else if (!s->hit_count) {
00601             s->hit_count++;
00602          }
00603 
00604       }
00605 
00606       if (s->hit_count == s->hits_required) {
00607          ast_debug(1, "%d Hz done detected\n", s->freq);
00608          res = 1;
00609       }
00610 
00611       s->last_hit = hit;
00612 
00613       /* If we had a hit in this block, include it into mute fragment */
00614       if (s->squelch && hit) {
00615          if (mute.end < start - s->block_size) {
00616             /* There is a gap between fragments */
00617             mute_fragment(dsp, &mute);
00618             mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
00619          }
00620          mute.end = end + s->block_size;
00621       }
00622 
00623       /* Reinitialise the detector for the next block */
00624       /* Reset for the next block */
00625       goertzel_reset(&s->tone);
00626 
00627       /* Advance to the next block */
00628       s->energy = 0.0;
00629       s->samples_pending = s->block_size;
00630 
00631       amp += limit;
00632    }
00633 
00634    if (s->squelch && mute.end) {
00635       if (mute.end > samples) {
00636          s->mute_samples = mute.end - samples;
00637          mute.end = samples;
00638       }
00639       mute_fragment(dsp, &mute);
00640    }
00641 
00642    return res;
00643 }


Variable Documentation

struct progalias aliases[] [static]
const char bell_mf_positions[] = "1247C-358A--69*---0B----#" [static]

Definition at line 316 of file dsp.c.

const int DEFAULT_SILENCE_THRESHOLD = 256 [static]

The default silence threshold we will use if an alternate configured value is not present or is invalid.

Definition at line 235 of file dsp.c.

const float dtmf_col[] [static]
Initial value:
 {
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 309 of file dsp.c.

int dtmf_hits_to_begin [static]

Definition at line 322 of file dsp.c.

int dtmf_misses_to_end [static]

Definition at line 323 of file dsp.c.

float dtmf_normal_twist [static]

Definition at line 318 of file dsp.c.

const char dtmf_positions[] = "123A" "456B" "789C" "*0#D" [static]

Definition at line 315 of file dsp.c.

float dtmf_reverse_twist [static]

Definition at line 319 of file dsp.c.

const float dtmf_row[] [static]
Initial value:
 {
   697.0,  770.0,  852.0,  941.0
}

Definition at line 306 of file dsp.c.

const float mf_tones[] [static]
Initial value:
 {
   700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
}

Definition at line 312 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().

float relax_dtmf_normal_twist [static]

Definition at line 320 of file dsp.c.

float relax_dtmf_reverse_twist [static]

Definition at line 321 of file dsp.c.

int thresholds[THRESHOLD_MAX] [static]

Definition at line 317 of file dsp.c.


Generated on 15 Apr 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1