Thu Sep 9 06:28:08 2010

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 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_HITS_TO_BEGIN   2
#define DTMF_MISSES_TO_END   3
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)
#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 const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static const float dtmf_row []
static const float mf_tones []
static struct progress modes []
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 174 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 172 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 173 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 222 of file dsp.c.

#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 117 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 128 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 169 of file dsp.c.

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 168 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 209 of file dsp.c.

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

#define DTMF_HITS_TO_BEGIN   2

Definition at line 212 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_MISSES_TO_END   3

Definition at line 214 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_NORMAL_TWIST   6.3

Definition at line 160 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 167 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 166 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)

Definition at line 164 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 159 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 158 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 193 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 192 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 191 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 185 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 184 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 183 of file dsp.c.

Referenced by ast_fax_detect_init().

#define MAX_DTMF_DIGITS   128

Definition at line 143 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 206 of file dsp.c.

Referenced by mf_detect().

#define SAMPLE_RATE   8000

Definition at line 195 of file dsp.c.

#define SAMPLES_IN_FRAME   160

Definition at line 203 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 131 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 130 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 119 of file dsp.c.

00119                  {
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 };

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 71 of file dsp.c.

00071                 { 
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 };

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 59 of file dsp.c.

00059                 {
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 };

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 134 of file dsp.c.

00134                   {
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 };

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 65 of file dsp.c.

00065                {
00066    PROG_MODE_NA = 0,
00067    PROG_MODE_CR,
00068    PROG_MODE_UK
00069 };


Function Documentation

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

Definition at line 965 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().

00966 {
00967    int x;
00968    int y;
00969    int pass;
00970    int newstate = DSP_TONE_STATE_SILENCE;
00971    int res = 0;
00972    while (len) {
00973       /* Take the lesser of the number of samples we need and what we have */
00974       pass = len;
00975       if (pass > dsp->gsamp_size - dsp->gsamps) {
00976          pass = dsp->gsamp_size - dsp->gsamps;
00977       }
00978       for (x = 0; x < pass; x++) {
00979          for (y = 0; y < dsp->freqcount; y++) {
00980             goertzel_sample(&dsp->freqs[y], s[x]);
00981          }
00982          dsp->genergy += s[x] * s[x];
00983       }
00984       s += pass;
00985       dsp->gsamps += pass;
00986       len -= pass;
00987       if (dsp->gsamps == dsp->gsamp_size) {
00988          float hz[7];
00989          for (y = 0; y < 7; y++) {
00990             hz[y] = goertzel_result(&dsp->freqs[y]);
00991          }
00992          switch (dsp->progmode) {
00993          case PROG_MODE_NA:
00994             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
00995                newstate = DSP_TONE_STATE_BUSY;
00996             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
00997                newstate = DSP_TONE_STATE_RINGING;
00998             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
00999                newstate = DSP_TONE_STATE_DIALTONE;
01000             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01001                newstate = DSP_TONE_STATE_SPECIAL1;
01002             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01003                /* End of SPECIAL1 or middle of SPECIAL2 */
01004                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
01005                   newstate = DSP_TONE_STATE_SPECIAL2;
01006                }
01007             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01008                /* End of SPECIAL2 or middle of SPECIAL3 */
01009                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01010                   newstate = DSP_TONE_STATE_SPECIAL3;
01011                }
01012             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01013                newstate = DSP_TONE_STATE_TALKING;
01014             } else {
01015                newstate = DSP_TONE_STATE_SILENCE;
01016             }
01017             break;
01018          case PROG_MODE_CR:
01019             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01020                newstate = DSP_TONE_STATE_RINGING;
01021             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01022                newstate = DSP_TONE_STATE_TALKING;
01023             } else {
01024                newstate = DSP_TONE_STATE_SILENCE;
01025             }
01026             break;
01027          case PROG_MODE_UK:
01028             if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
01029                newstate = DSP_TONE_STATE_HUNGUP;
01030             } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
01031                newstate = DSP_TONE_STATE_DIALTONE;
01032             }
01033             break;
01034          default:
01035             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01036          }
01037          if (newstate == dsp->tstate) {
01038             dsp->tcount++;
01039             if (dsp->ringtimeout) {
01040                dsp->ringtimeout++;
01041             }
01042             switch (dsp->tstate) {
01043             case DSP_TONE_STATE_RINGING:
01044                if ((dsp->features & DSP_PROGRESS_RINGING) &&
01045                    (dsp->tcount == THRESH_RING)) {
01046                   res = AST_CONTROL_RINGING;
01047                   dsp->ringtimeout = 1;
01048                }
01049                break;
01050             case DSP_TONE_STATE_BUSY:
01051                if ((dsp->features & DSP_PROGRESS_BUSY) &&
01052                    (dsp->tcount == THRESH_BUSY)) {
01053                   res = AST_CONTROL_BUSY;
01054                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01055                }
01056                break;
01057             case DSP_TONE_STATE_TALKING:
01058                if ((dsp->features & DSP_PROGRESS_TALK) &&
01059                    (dsp->tcount == THRESH_TALK)) {
01060                   res = AST_CONTROL_ANSWER;
01061                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01062                }
01063                break;
01064             case DSP_TONE_STATE_SPECIAL3:
01065                if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01066                    (dsp->tcount == THRESH_CONGESTION)) {
01067                   res = AST_CONTROL_CONGESTION;
01068                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01069                }
01070                break;
01071             case DSP_TONE_STATE_HUNGUP:
01072                if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01073                    (dsp->tcount == THRESH_HANGUP)) {
01074                   res = AST_CONTROL_HANGUP;
01075                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01076                }
01077                break;
01078             }
01079             if (dsp->ringtimeout == THRESH_RING2ANSWER) {
01080                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
01081                res = AST_CONTROL_ANSWER;
01082                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01083             }
01084          } else {
01085             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01086             ast_debug(5, "Start state %d\n", newstate);
01087             dsp->tstate = newstate;
01088             dsp->tcount = 1;
01089          }
01090 
01091          /* Reset goertzel */
01092          for (x = 0; x < 7; x++) {
01093             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01094          }
01095          dsp->gsamps = 0;
01096          dsp->genergy = 0.0;
01097       }
01098    }
01099 
01100    return res;
01101 }

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

Definition at line 1116 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().

01117 {
01118    int accum;
01119    int x;
01120    int res = 0;
01121 
01122    if (!len) {
01123       return 0;
01124    }
01125    accum = 0;
01126    for (x = 0; x < len; x++) {
01127       accum += abs(s[x]);
01128    }
01129    accum /= len;
01130    if (accum < dsp->threshold) {
01131       /* Silent */
01132       dsp->totalsilence += len / 8;
01133       if (dsp->totalnoise) {
01134          /* Move and save history */
01135          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
01136          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01137 /* we don't want to check for busydetect that frequently */
01138 #if 0
01139          dsp->busymaybe = 1;
01140 #endif
01141       }
01142       dsp->totalnoise = 0;
01143       res = 1;
01144    } else {
01145       /* Not silent */
01146       dsp->totalnoise += len / 8;
01147       if (dsp->totalsilence) {
01148          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01149          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01150          /* Move and save history */
01151          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
01152          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01153          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01154          if (silence1 < silence2) {
01155             if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
01156                dsp->busymaybe = 1;
01157             } else {
01158                dsp->busymaybe = 0;
01159             }
01160          } else {
01161             if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
01162                dsp->busymaybe = 1;
01163             } else {
01164                dsp->busymaybe = 0;
01165             }
01166          }
01167       }
01168       dsp->totalsilence = 0;
01169    }
01170    if (totalsilence) {
01171       *totalsilence = dsp->totalsilence;
01172    }
01173    if (totalnoise) {
01174       *totalnoise = dsp->totalnoise;
01175    }
01176    return res;
01177 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1677 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_variable_retrieve(), ast_verb, CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, THRESHOLD_SILENCE, and value.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01678 {
01679    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01680    struct ast_config *cfg;
01681 
01682    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01683    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01684       ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD);
01685       thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01686       return 0;
01687    }
01688 
01689    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01690       return 0;
01691    }
01692 
01693    if (cfg) {
01694       const char *value;
01695 
01696       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01697       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01698          ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01699          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01700       } else if (!value) {
01701          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01702       }
01703 
01704       ast_config_destroy(cfg);
01705    }
01706    return 0;
01707 }

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 1179 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, and ast_dsp::historicsilence.

Referenced by ast_dsp_process().

01180 {
01181    int res = 0, x;
01182 #ifndef BUSYDETECT_TONEONLY
01183    int avgsilence = 0, hitsilence = 0;
01184 #endif
01185    int avgtone = 0, hittone = 0;
01186    if (!dsp->busymaybe) {
01187       return res;
01188    }
01189    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01190 #ifndef BUSYDETECT_TONEONLY
01191       avgsilence += dsp->historicsilence[x];
01192 #endif
01193       avgtone += dsp->historicnoise[x];
01194    }
01195 #ifndef BUSYDETECT_TONEONLY
01196    avgsilence /= dsp->busycount;
01197 #endif
01198    avgtone /= dsp->busycount;
01199    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01200 #ifndef BUSYDETECT_TONEONLY
01201       if (avgsilence > dsp->historicsilence[x]) {
01202          if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
01203             hitsilence++;
01204          }
01205       } else {
01206          if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
01207             hitsilence++;
01208          }
01209       }
01210 #endif
01211       if (avgtone > dsp->historicnoise[x]) {
01212          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01213             hittone++;
01214          }
01215       } else {
01216          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01217             hittone++;
01218          }
01219       }
01220    }
01221 #ifndef BUSYDETECT_TONEONLY
01222    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01223        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01224        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01225 #else
01226    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01227 #endif
01228 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01229       if (avgtone > avgsilence) {
01230          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
01231             res = 1;
01232          }
01233       } else {
01234          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
01235             res = 1;
01236          }
01237       }
01238 #else
01239       res = 1;
01240 #endif
01241    }
01242    /* If we know the expected busy tone length, check we are in the range */
01243    if (res && (dsp->busy_tonelength > 0)) {
01244       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01245 #ifdef BUSYDETECT_DEBUG
01246          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01247             avgtone, dsp->busy_tonelength);
01248 #endif
01249          res = 0;
01250       }
01251    }
01252 #ifndef BUSYDETECT_TONEONLY
01253    /* If we know the expected busy tone silent-period length, check we are in the range */
01254    if (res && (dsp->busy_quietlength > 0)) {
01255       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01256 #ifdef BUSYDETECT_DEBUG
01257       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01258          avgsilence, dsp->busy_quietlength);
01259 #endif
01260          res = 0;
01261       }
01262    }
01263 #endif
01264 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01265    if (res) {
01266       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01267    } else {
01268       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01269    }
01270 #endif
01271    return res;
01272 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1103 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.

01104 {
01105    if (inf->frametype != AST_FRAME_VOICE) {
01106       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01107       return 0;
01108    }
01109    if (inf->subclass.codec != AST_FORMAT_SLINEAR) {
01110       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01111       return 0;
01112    }
01113    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01114 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1579 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().

01580 {
01581    int i;
01582    
01583    dsp->dtmf_began = 0;
01584    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01585       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01586       /* Reinitialise the detector for the next block */
01587       for (i = 0;  i < 6;  i++) {
01588          goertzel_reset(&s->tone_out[i]);
01589       }
01590       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01591       s->current_sample = 0;
01592    } else {
01593       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01594       /* Reinitialise the detector for the next block */
01595       for (i = 0;  i < 4;  i++) {
01596          goertzel_reset(&s->row_out[i]);
01597          goertzel_reset(&s->col_out[i]);
01598       }
01599       s->lasthit = s->current_hit = 0;
01600       s->energy = 0.0;
01601       s->current_sample = 0;
01602       s->hits = 0;
01603       s->misses = 0;
01604    }
01605 
01606    dsp->digit_state.digits[0] = '\0';
01607    dsp->digit_state.current_digits = 0;
01608 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1672 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01673 {
01674    return dsp->tcount;
01675 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1709 of file dsp.c.

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

01710 {
01711    return thresholds[which];
01712 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1667 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01668 {
01669    return dsp->tstate;
01670 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1714 of file dsp.c.

References _dsp_init().

Referenced by main().

01715 {
01716    return _dsp_init(0);
01717 }

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 1292 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().

01293 {
01294        short *s;
01295        int len;
01296 
01297        if (f->frametype != AST_FRAME_VOICE) {
01298                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01299                return 0;
01300        }
01301        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01302                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01303                return 0;
01304        }
01305        s = f->data.ptr;
01306        len = f->datalen/2;
01307        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01308 }

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 1311 of file dsp.c.

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), ast_channel::_softhangup, AST_ALAW, 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_channel::name, 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(), sip_rtp_read(), and usbradio_read().

01312 {
01313    int silence;
01314    int res;
01315    int digit = 0, fax_digit = 0;
01316    int x;
01317    short *shortdata;
01318    unsigned char *odata;
01319    int len;
01320    struct ast_frame *outf = NULL;
01321 
01322    if (!af) {
01323       return NULL;
01324    }
01325    if (af->frametype != AST_FRAME_VOICE) {
01326       return af;
01327    }
01328 
01329    odata = af->data.ptr;
01330    len = af->datalen;
01331    /* Make sure we have short data */
01332    switch (af->subclass.codec) {
01333    case AST_FORMAT_SLINEAR:
01334       shortdata = af->data.ptr;
01335       len = af->datalen / 2;
01336       break;
01337    case AST_FORMAT_ULAW:
01338    case AST_FORMAT_TESTLAW:
01339       shortdata = alloca(af->datalen * 2);
01340       for (x = 0;x < len; x++) {
01341          shortdata[x] = AST_MULAW(odata[x]);
01342       }
01343       break;
01344    case AST_FORMAT_ALAW:
01345       shortdata = alloca(af->datalen * 2);
01346       for (x = 0; x < len; x++) {
01347          shortdata[x] = AST_ALAW(odata[x]);
01348       }
01349       break;
01350    default:
01351       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01352       if (dsp->display_inband_dtmf_warning)
01353          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec));
01354       dsp->display_inband_dtmf_warning = 0;
01355       return af;
01356    }
01357 
01358    /* Initially we do not want to mute anything */
01359    dsp->mute_fragments = 0;
01360 
01361    /* Need to run the silence detection stuff for silence suppression and busy detection */
01362    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01363       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01364    }
01365 
01366    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01367       memset(&dsp->f, 0, sizeof(dsp->f));
01368       dsp->f.frametype = AST_FRAME_NULL;
01369       ast_frfree(af);
01370       return ast_frisolate(&dsp->f);
01371    }
01372    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01373       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01374       memset(&dsp->f, 0, sizeof(dsp->f));
01375       dsp->f.frametype = AST_FRAME_CONTROL;
01376       dsp->f.subclass.integer = AST_CONTROL_BUSY;
01377       ast_frfree(af);
01378       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01379       return ast_frisolate(&dsp->f);
01380    }
01381 
01382    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01383       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01384          fax_digit = 'f';
01385       }
01386 
01387       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01388          fax_digit = 'e';
01389       }
01390    }
01391 
01392    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01393       if (dsp->digitmode & DSP_DIGITMODE_MF)
01394          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01395       else
01396          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01397 
01398       if (dsp->digit_state.current_digits) {
01399          int event = 0, event_len = 0;
01400          char event_digit = 0;
01401 
01402          if (!dsp->dtmf_began) {
01403             /* We have not reported DTMF_BEGIN for anything yet */
01404 
01405             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01406                event = AST_FRAME_DTMF_BEGIN;
01407                event_digit = dsp->digit_state.digits[0];
01408             }
01409             dsp->dtmf_began = 1;
01410 
01411          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01412             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01413             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01414                event = AST_FRAME_DTMF_END;
01415                event_digit = dsp->digit_state.digits[0];
01416                event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE;
01417             }
01418             memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
01419             memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
01420             dsp->digit_state.current_digits--;
01421             dsp->dtmf_began = 0;
01422 
01423             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01424                /* Reset Busy Detector as we have some confirmed activity */ 
01425                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01426                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01427                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01428             }
01429          }
01430 
01431          if (event) {
01432             memset(&dsp->f, 0, sizeof(dsp->f));
01433             dsp->f.frametype = event;
01434             dsp->f.subclass.integer = event_digit;
01435             dsp->f.len = event_len;
01436             outf = &dsp->f;
01437             goto done;
01438          }
01439       }
01440    }
01441 
01442    if (fax_digit) {
01443       /* Fax was detected - digit is either 'f' or 'e' */
01444 
01445       memset(&dsp->f, 0, sizeof(dsp->f));
01446       dsp->f.frametype = AST_FRAME_DTMF;
01447       dsp->f.subclass.integer = fax_digit;
01448       outf = &dsp->f;
01449       goto done;
01450    }
01451 
01452    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01453       res = __ast_dsp_call_progress(dsp, shortdata, len);
01454       if (res) {
01455          switch (res) {
01456          case AST_CONTROL_ANSWER:
01457          case AST_CONTROL_BUSY:
01458          case AST_CONTROL_RINGING:
01459          case AST_CONTROL_CONGESTION:
01460          case AST_CONTROL_HANGUP:
01461             memset(&dsp->f, 0, sizeof(dsp->f));
01462             dsp->f.frametype = AST_FRAME_CONTROL;
01463             dsp->f.subclass.integer = res;
01464             dsp->f.src = "dsp_progress";
01465             if (chan) 
01466                ast_queue_frame(chan, &dsp->f);
01467             break;
01468          default:
01469             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01470          }
01471       }
01472    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01473       res = __ast_dsp_call_progress(dsp, shortdata, len);
01474    }
01475 
01476 done:
01477    /* Mute fragment of the frame */
01478    for (x = 0; x < dsp->mute_fragments; x++) {
01479       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01480    }
01481 
01482    switch (af->subclass.codec) {
01483    case AST_FORMAT_SLINEAR:
01484       break;
01485    case AST_FORMAT_ULAW:
01486       for (x = 0; x < len; x++) {
01487          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01488       }
01489       break;
01490    case AST_FORMAT_ALAW:
01491       for (x = 0; x < len; x++) {
01492          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01493       }
01494       break;
01495    }
01496 
01497    if (outf) {
01498       if (chan) {
01499          ast_queue_frame(chan, af);
01500       }
01501       ast_frfree(af);
01502       return ast_frisolate(outf);
01503    } else {
01504       return af;
01505    }
01506 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1508 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().

01509 {
01510    int max = 0;
01511    int x;
01512    
01513    dsp->gsamp_size = modes[dsp->progmode].size;
01514    dsp->gsamps = 0;
01515    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01516       if (modes[dsp->progmode].freqs[x]) {
01517          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01518          max = x + 1;
01519       }
01520    }
01521    dsp->freqcount = max;
01522    dsp->ringtimeout= 0;
01523 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1719 of file dsp.c.

References _dsp_init().

01720 {
01721    return _dsp_init(1);
01722 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

Definition at line 1610 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().

01611 {
01612    int x;
01613    
01614    dsp->totalsilence = 0;
01615    dsp->gsamps = 0;
01616    for (x = 0; x < 4; x++) {
01617       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01618    }
01619    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01620    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01621    dsp->ringtimeout= 0;
01622 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1561 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01562 {
01563    if (cadences < 4) {
01564       cadences = 4;
01565    }
01566    if (cadences > DSP_HISTORY) {
01567       cadences = DSP_HISTORY;
01568    }
01569    dsp->busycount = cadences;
01570 }

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

Set expected lengths of the busy tone.

Definition at line 1572 of file dsp.c.

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

Referenced by dahdi_new().

01573 {
01574    dsp->busy_tonelength = tonelength;
01575    dsp->busy_quietlength = quietlength;
01576    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01577 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1648 of file dsp.c.

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

Referenced by dahdi_new().

01649 {
01650    int x;
01651    
01652    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01653       if (!strcasecmp(aliases[x].name, zone)) {
01654          dsp->progmode = aliases[x].mode;
01655          ast_dsp_prog_reset(dsp);
01656          return 0;
01657       }
01658    }
01659    return -1;
01660 }

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 1624 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(), my_dsp_set_digitmode(), and store_config().

01625 {
01626    int new;
01627    int old;
01628    
01629    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01630    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01631    if (old != new) {
01632       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01633       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01634    }
01635    dsp->digitmode = digitmode;
01636    return 0;
01637 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1639 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01640 {
01641    if (dsp->faxmode != faxmode) {
01642       ast_fax_detect_init(dsp);
01643    }
01644    dsp->faxmode = faxmode;
01645    return 0;
01646 }

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 1556 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().

01557 {
01558    dsp->threshold = threshold;
01559 }

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 1274 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().

01275 {
01276    short *s;
01277    int len;
01278    
01279    if (f->frametype != AST_FRAME_VOICE) {
01280       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01281       return 0;
01282    }
01283    if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01284       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01285       return 0;
01286    }
01287    s = f->data.ptr;
01288    len = f->datalen/2;
01289    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01290 }

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 1662 of file dsp.c.

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01663 {
01664    return (dsp->mute_fragments > 0);
01665 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

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 499 of file dsp.c.

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

Referenced by ast_digit_detect_init().

00500 {
00501    int i;
00502    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00503    for (i = 0;  i < 6;  i++) {
00504       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00505    }
00506    s->current_sample = 0;
00507    s->current_hit = 0;
00508 }

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

Definition at line 414 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().

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

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 641 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_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, 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::hits_to_begin, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, dtmf_detect_state_t::misses_to_end, 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().

00642 {
00643    float row_energy[4];
00644    float col_energy[4];
00645    float famp;
00646    int i;
00647    int j;
00648    int sample;
00649    int best_row;
00650    int best_col;
00651    int hit;
00652    int limit;
00653    fragment_t mute = {0, 0};
00654 
00655    if (squelch && s->td.dtmf.mute_samples > 0) {
00656       mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
00657       s->td.dtmf.mute_samples -= mute.end;
00658    }
00659 
00660    hit = 0;
00661    for (sample = 0; sample < samples; sample = limit) {
00662       /* DTMF_GSIZE is optimised to meet the DTMF specs. */
00663       if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
00664          limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
00665       } else {
00666          limit = samples;
00667       }
00668       /* The following unrolled loop takes only 35% (rough estimate) of the 
00669          time of a rolled loop on the machine on which it was developed */
00670       for (j = sample; j < limit; j++) {
00671          famp = amp[j];
00672          s->td.dtmf.energy += famp*famp;
00673          /* With GCC 2.95, the following unrolled code seems to take about 35%
00674             (rough estimate) as long as a neat little 0-3 loop */
00675          goertzel_sample(s->td.dtmf.row_out, amp[j]);
00676          goertzel_sample(s->td.dtmf.col_out, amp[j]);
00677          goertzel_sample(s->td.dtmf.row_out + 1, amp[j]);
00678          goertzel_sample(s->td.dtmf.col_out + 1, amp[j]);
00679          goertzel_sample(s->td.dtmf.row_out + 2, amp[j]);
00680          goertzel_sample(s->td.dtmf.col_out + 2, amp[j]);
00681          goertzel_sample(s->td.dtmf.row_out + 3, amp[j]);
00682          goertzel_sample(s->td.dtmf.col_out + 3, amp[j]);
00683       }
00684       s->td.dtmf.current_sample += (limit - sample);
00685       if (s->td.dtmf.current_sample < DTMF_GSIZE) {
00686          continue;
00687       }
00688       /* We are at the end of a DTMF detection block */
00689       /* Find the peak row and the peak column */
00690       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00691       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00692 
00693       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00694          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00695          if (row_energy[i] > row_energy[best_row]) {
00696             best_row = i;
00697          }
00698          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00699          if (col_energy[i] > col_energy[best_col]) {
00700             best_col = i;
00701          }
00702       }
00703       hit = 0;
00704       /* Basic signal level test and the twist test */
00705       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00706           col_energy[best_col] >= DTMF_THRESHOLD &&
00707           col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST &&
00708           col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) {
00709          /* Relative peak test */
00710          for (i = 0;  i < 4;  i++) {
00711             if ((i != best_col &&
00712                 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00713                 (i != best_row 
00714                  && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00715                break;
00716             }
00717          }
00718          /* ... and fraction of total energy test */
00719          if (i >= 4 &&
00720              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
00721             /* Got a hit */
00722             hit = dtmf_positions[(best_row << 2) + best_col];
00723          }
00724       } 
00725 
00726       if (s->td.dtmf.current_hit) {
00727          /* We are in the middle of a digit already */
00728          if (hit != s->td.dtmf.current_hit) {
00729             s->td.dtmf.misses++;
00730             if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
00731                /* There were enough misses to consider digit ended */
00732                s->td.dtmf.current_hit = 0;
00733             }
00734          } else {
00735             s->td.dtmf.misses = 0;
00736             /* Current hit was same as last, so increment digit duration (of last digit) */
00737             s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
00738          }
00739       }
00740 
00741       /* Look for a start of a new digit no matter if we are already in the middle of some
00742          digit or not. This is because hits_to_begin may be smaller than misses_to_end
00743          and we may find begin of new digit before we consider last one ended. */
00744       if (hit) {
00745          if (hit == s->td.dtmf.lasthit) {
00746             s->td.dtmf.hits++;
00747          } else {
00748             s->td.dtmf.hits = 1;
00749          }
00750 
00751          if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin && hit != s->td.dtmf.current_hit) {
00752             store_digit(s, hit);
00753             s->td.dtmf.current_hit = hit;
00754             s->td.dtmf.misses = 0;
00755          }
00756       } else {
00757          s->td.dtmf.hits = 0;
00758       }
00759 
00760       s->td.dtmf.lasthit = hit;
00761 
00762       /* If we had a hit in this block, include it into mute fragment */
00763       if (squelch && hit) {
00764          if (mute.end < sample - DTMF_GSIZE) {
00765             /* There is a gap between fragments */
00766             mute_fragment(dsp, &mute);
00767             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00768          }
00769          mute.end = limit + DTMF_GSIZE;
00770       }
00771 
00772       /* Reinitialise the detector for the next block */
00773       for (i = 0; i < 4; i++) {
00774          goertzel_reset(&s->td.dtmf.row_out[i]);
00775          goertzel_reset(&s->td.dtmf.col_out[i]);
00776       }
00777       s->td.dtmf.energy = 0.0;
00778       s->td.dtmf.current_sample = 0;
00779    }
00780 
00781    if (squelch && mute.end) {
00782       if (mute.end > samples) {
00783          s->td.dtmf.mute_samples = mute.end - samples;
00784          mute.end = samples;
00785       }
00786       mute_fragment(dsp, &mute);
00787    }
00788 
00789    return (s->td.dtmf.current_hit); /* return the debounced hit */
00790 }

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

Definition at line 342 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().

00343 {
00344    s->v2 = s->v3 = s->chunky = 0.0;
00345    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00346    s->samples = samples;
00347 }

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

Definition at line 349 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().

00350 {
00351    s->v2 = s->v3 = s->chunky = 0.0;
00352 }

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

Definition at line 333 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().

00334 {
00335    goertzel_result_t r;
00336    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00337    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00338    r.power = s->chunky * 2;
00339    return (float)r.value * (float)(1 << r.power);
00340 }

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

Definition at line 306 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().

00307 {
00308    int v1;
00309    
00310    v1 = s->v2;
00311    s->v2 = s->v3;
00312    
00313    s->v3 = (s->fac * s->v2) >> 15;
00314    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00315    if (abs(s->v3) > 32768) {
00316       s->chunky++;
00317       s->v3 = s->v3 >> 1;
00318       s->v2 = s->v2 >> 1;
00319       v1 = v1 >> 1;
00320    }
00321 }

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

Definition at line 323 of file dsp.c.

References goertzel_sample().

00324 {
00325    int i;
00326    
00327    for (i = 0; i < count; i++) {
00328       goertzel_sample(s, samps[i]);
00329    }
00330 }

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 792 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, DTMF_GSIZE, 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().

00794 {
00795    float energy[6];
00796    int best;
00797    int second_best;
00798    float famp;
00799    int i;
00800    int j;
00801    int sample;
00802    int hit;
00803    int limit;
00804    fragment_t mute = {0, 0};
00805 
00806    if (squelch && s->td.mf.mute_samples > 0) {
00807       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00808       s->td.mf.mute_samples -= mute.end;
00809    }
00810 
00811    hit = 0;
00812    for (sample = 0;  sample < samples;  sample = limit) {
00813       /* 80 is optimised to meet the MF specs. */
00814       /* XXX So then why is MF_GSIZE defined as 120? */
00815       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00816          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00817       } else {
00818          limit = samples;
00819       }
00820       /* The following unrolled loop takes only 35% (rough estimate) of the 
00821          time of a rolled loop on the machine on which it was developed */
00822       for (j = sample;  j < limit;  j++) {
00823          famp = amp[j];
00824          /* With GCC 2.95, the following unrolled code seems to take about 35%
00825             (rough estimate) as long as a neat little 0-3 loop */
00826          goertzel_sample(s->td.mf.tone_out, amp[j]);
00827          goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
00828          goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
00829          goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
00830          goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
00831          goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
00832       }
00833       s->td.mf.current_sample += (limit - sample);
00834       if (s->td.mf.current_sample < MF_GSIZE) {
00835          continue;
00836       }
00837       /* We're at the end of an MF detection block.  */
00838       /* Find the two highest energies. The spec says to look for
00839          two tones and two tones only. Taking this literally -ie
00840          only two tones pass the minimum threshold - doesn't work
00841          well. The sinc function mess, due to rectangular windowing
00842          ensure that! Find the two highest energies and ensure they
00843          are considerably stronger than any of the others. */
00844       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00845       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00846       if (energy[0] > energy[1]) {
00847          best = 0;
00848          second_best = 1;
00849       } else {
00850          best = 1;
00851          second_best = 0;
00852       }
00853       /*endif*/
00854       for (i = 2; i < 6; i++) {
00855          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00856          if (energy[i] >= energy[best]) {
00857             second_best = best;
00858             best = i;
00859          } else if (energy[i] >= energy[second_best]) {
00860             second_best = i;
00861          }
00862       }
00863       /* Basic signal level and twist tests */
00864       hit = 0;
00865       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00866                && energy[best] < energy[second_best]*BELL_MF_TWIST
00867                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00868          /* Relative peak test */
00869          hit = -1;
00870          for (i = 0; i < 6; i++) {
00871             if (i != best && i != second_best) {
00872                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00873                   /* The best two are not clearly the best */
00874                   hit = 0;
00875                   break;
00876                }
00877             }
00878          }
00879       }
00880       if (hit) {
00881          /* Get the values into ascending order */
00882          if (second_best < best) {
00883             i = best;
00884             best = second_best;
00885             second_best = i;
00886          }
00887          best = best * 5 + second_best - 1;
00888          hit = bell_mf_positions[best];
00889          /* Look for two successive similar results */
00890          /* The logic in the next test is:
00891             For KP we need 4 successive identical clean detects, with
00892             two blocks of something different preceeding it. For anything
00893             else we need two successive identical clean detects, with
00894             two blocks of something different preceeding it. */
00895          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00896             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00897              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00898              hit != s->td.mf.hits[0]))) {
00899             store_digit(s, hit);
00900          }
00901       }
00902 
00903 
00904       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00905          /* Two successive block without a hit terminate current digit */
00906          s->td.mf.current_hit = 0;
00907       }
00908 
00909       s->td.mf.hits[0] = s->td.mf.hits[1];
00910       s->td.mf.hits[1] = s->td.mf.hits[2];
00911       s->td.mf.hits[2] = s->td.mf.hits[3];
00912       s->td.mf.hits[3] = s->td.mf.hits[4];
00913       s->td.mf.hits[4] = hit;
00914 
00915       /* If we had a hit in this block, include it into mute fragment */
00916       if (squelch && hit) {
00917          if (mute.end < sample - MF_GSIZE) {
00918             /* There is a gap between fragments */
00919             mute_fragment(dsp, &mute);
00920             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00921          }
00922          mute.end = limit + DTMF_GSIZE;
00923       }
00924 
00925       /* Reinitialise the detector for the next block */
00926       for (i = 0;  i < 6;  i++)
00927          goertzel_reset(&s->td.mf.tone_out[i]);
00928       s->td.mf.current_sample = 0;
00929    }
00930 
00931    if (squelch && mute.end) {
00932       if (mute.end > samples) {
00933          s->td.mf.mute_samples = mute.end - samples;
00934          mute.end = samples;
00935       }
00936       mute_fragment(dsp, &mute);
00937    }
00938 
00939    return (s->td.mf.current_hit); /* return the debounced hit */
00940 }

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

Definition at line 404 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().

00405 {
00406    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00407       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00408       return;
00409    }
00410 
00411    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00412 }

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

Definition at line 942 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

00943 {
00944    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00945    /* Make sure absolute levels are high enough */
00946    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
00947       return 0;
00948    }
00949    /* Amplify ignored stuff */
00950    i2 *= TONE_THRESH;
00951    i1 *= TONE_THRESH;
00952    e *= TONE_THRESH;
00953    /* Check first tone */
00954    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
00955       return 0;
00956    }
00957    /* And second */
00958    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
00959       return 0;
00960    }
00961    /* Guess it's there... */
00962    return 1;
00963 }

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

Definition at line 628 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().

00629 {
00630    s->detected_digits++;
00631    if (s->current_digits < MAX_DTMF_DIGITS) {
00632       s->digitlen[s->current_digits] = 0;
00633       s->digits[s->current_digits++] = digit;
00634       s->digits[s->current_digits] = '\0';
00635    } else {
00636       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00637       s->lost_digits++;
00638    }
00639 }

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

Definition at line 524 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().

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


Variable Documentation

struct progalias aliases[] [static]

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

Definition at line 303 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 220 of file dsp.c.

const float dtmf_col[] [static]

Initial value:

 {
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 296 of file dsp.c.

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

Definition at line 302 of file dsp.c.

const float dtmf_row[] [static]

Initial value:

 {
   697.0,  770.0,  852.0,  941.0
}

Definition at line 293 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 299 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().

int thresholds[THRESHOLD_MAX] [static]

Definition at line 304 of file dsp.c.


Generated on Thu Sep 9 06:28:08 2010 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6