Mon Oct 8 12:39:21 2012

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"

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   4
#define DTMF_MISSES_TO_END   4
#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 = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150,
  BUSY_MAX = 600
}
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.
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.
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_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
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, int fuzzy)
 Set expected lengths of the busy tones.
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 178 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 176 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 177 of file dsp.c.

#define CONFIG_FILE_NAME   "dsp.conf"

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

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 172 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 213 of file dsp.c.

Referenced by ast_dtmf_detect_init(), and dtmf_detect().

#define DTMF_HITS_TO_BEGIN   4

Definition at line 216 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_MISSES_TO_END   4

Definition at line 218 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_NORMAL_TWIST   6.3

Definition at line 164 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 171 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)

Definition at line 168 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 174 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 197 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 196 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 195 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 189 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 188 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

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

Referenced by mf_detect().

#define SAMPLE_RATE   8000

Definition at line 199 of file dsp.c.

#define SAMPLES_IN_FRAME   160

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


Enumeration Type Documentation

enum busy_detect

Enumerator:
BUSY_PERCENT  The percentage difference between the two last tone 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 150 ms in half-cadence
BUSY_MAX  Busy can't be longer than 600 ms in half-cadence

Definition at line 123 of file dsp.c.

00123                  {
00124    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last tone periods */
00125    BUSY_PAT_PERCENT = 8,   /*!< 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 = 150,       /*!< Busy must be at least 150 ms in half-cadence */
00128    BUSY_MAX = 600          /*!< Busy can't be longer than 600 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 };

enum gsamp_thresh

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

References DSP_TONE_STATE_BUSY, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_350, HZ_440, HZ_480, HZ_620, pair_there(), pass, PROG_MODE_NA, and ast_dsp::progmode.

Referenced by ast_dsp_call_progress().

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

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

Definition at line 1120 of file dsp.c.

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

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

01121 {
01122    int accum;
01123    int x;
01124    int res = 0;
01125 
01126    if (!len) {
01127       return 0;
01128    }
01129    accum = 0;
01130    for (x = 0; x < len; x++) {
01131       accum += abs(s[x]);
01132    }
01133    accum /= len;
01134    if (accum < dsp->threshold) {
01135       /* Silent */
01136       dsp->totalsilence += len / 8;
01137 #ifdef DEBUG_DSP_BUSYDETECT
01138       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01139 #endif
01140       if (dsp->totalnoise) {
01141          /* Move and save history */
01142          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0]));
01143          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01144          /* check if previous tone differs BUSY_PERCENT from the one before it */
01145          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01146          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01147          if (tone1 < tone2) {
01148            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01149                dsp->busymaybe = 1;
01150            else
01151                dsp->busymaybe = 0;
01152          } else {
01153            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01154                dsp->busymaybe = 1;
01155             else
01156                dsp->busymaybe = 0;
01157          }
01158       }
01159       dsp->totalnoise = 0;
01160       res = 1;
01161    } else {
01162       /* Not silent */
01163       dsp->totalnoise += len / 8;
01164 #ifdef DEBUG_DSP_BUSYDETECT
01165       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01166 #endif     
01167       if (dsp->totalsilence) {
01168          /* Move and save history */
01169          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0]));
01170          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01171       }
01172       dsp->totalsilence = 0;
01173    }
01174    if (totalsilence) {
01175       *totalsilence = dsp->totalsilence;
01176    }
01177    if (totalnoise) {
01178       *totalnoise = dsp->totalnoise;
01179    }
01180    return res;
01181 }

static int _dsp_init ( int  reload  )  [static]

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

01726 {
01727    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01728    struct ast_config *cfg;
01729 
01730    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01731    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01732       ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD);
01733       thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01734       return 0;
01735    }
01736 
01737    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01738       return 0;
01739    }
01740 
01741    if (cfg) {
01742       const char *value;
01743 
01744       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01745       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01746          ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01747          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01748       } else if (!value) {
01749          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01750       }
01751 
01752       ast_config_destroy(cfg);
01753    }
01754    return 0;
01755 }

static void ast_digit_detect_init ( digit_detect_state_t s,
int  mf 
) [static]

Definition at line 517 of file dsp.c.

References ast_dtmf_detect_init(), ast_mf_detect_init(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, digit_detect_state_t::dtmf, digit_detect_state_t::lost_digits, digit_detect_state_t::mf, and digit_detect_state_t::td.

Referenced by ast_dsp_new(), and ast_dsp_set_digitmode().

00518 {
00519    s->current_digits = 0;
00520    s->detected_digits = 0;
00521    s->lost_digits = 0;
00522    s->digits[0] = '\0';
00523 
00524    if (mf) {
00525       ast_mf_detect_init(&s->td.mf);
00526    } else {
00527       ast_dtmf_detect_init(&s->td.dtmf);
00528    }
00529 }

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

References ast_debug, ast_log(), BUSY_MAX, BUSY_MIN, ast_dsp::busy_pattern_fuzzy, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busymaybe, ast_dsp::busytoneonly, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_ERROR, LOG_NOTICE, MAX, and option_debug.

01184 {
01185    int res = 0, x;
01186    int avgsilence = 0, hitsilence = 0;
01187    int avgtone = 0, hittone = 0;
01188 #ifdef DEBUG_DSP_BUSYDETECT
01189    char buf[16];
01190    char silence_list[64]="", tone_list[64]="";
01191 #endif
01192    
01193    if (!dsp->busymaybe) {
01194       return res;
01195    }
01196    dsp->busymaybe = 0;
01197 
01198    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01199       avgsilence += dsp->historicsilence[x];
01200       avgtone += dsp->historicnoise[x];
01201    }
01202    avgsilence /= dsp->busycount;
01203    avgtone /= dsp->busycount;
01204 #ifdef DEBUG_DSP_BUSYDETECT
01205    sprintf(silence_list,"Silences: ");
01206    sprintf(tone_list,"Tones:    ");
01207 #endif
01208    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01209 #ifdef DEBUG_DSP_BUSYDETECT
01210       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01211       strcat(silence_list, buf);
01212       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01213       strcat(tone_list, buf); 
01214 #endif
01215       if (!dsp->busytoneonly) {
01216          if (avgsilence > dsp->historicsilence[x]) {
01217             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01218                hitsilence++;
01219          } else {
01220             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01221                hitsilence++;
01222          }
01223       }
01224       if (avgtone > dsp->historicnoise[x]) {
01225          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01226             hittone++;
01227          }
01228       } else {
01229          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01230             hittone++;
01231          }
01232       }
01233    }
01234 #ifdef DEBUG_DSP_BUSYDETECT
01235    fprintf(stderr, "BUSY DETECTOR\n");   
01236    fprintf(stderr, "%s\n", tone_list);
01237    fprintf(stderr, "%s\n", silence_list)
01238 #endif
01239    if ((dsp->busytoneonly || 
01240        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01241       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01242       if (dsp->busycompare) {
01243            if (dsp->busytoneonly) {
01244              res = 1;
01245             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01246          } else {
01247               if (avgtone > avgsilence) {
01248                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01249                     res = 1;
01250             } else {
01251                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01252                    res = 1;
01253             }
01254          }
01255       } else {
01256          res = 1;
01257       }
01258    }
01259    /* If we know the expected busy tone length, check we are in the range */
01260    if (res && (dsp->busy_tonelength > 0)) {
01261       if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) {
01262 #ifdef BUSYDETECT_DEBUG
01263          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01264             avgtone, dsp->busy_tonelength);
01265 #endif
01266          res = 0;
01267       }
01268    }
01269    /* If we know the expected busy tone silent-period length, check we are in the range */
01270    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01271       if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) {
01272 #ifdef BUSYDETECT_DEBUG
01273       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01274          avgsilence, dsp->busy_quietlength);
01275 #endif
01276          res = 0;
01277       }
01278    }
01279    if (res) {
01280       if (option_debug)
01281          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01282    } else {
01283       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01284    }
01285    return res;
01286 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

01628 {
01629    int i;
01630    
01631    dsp->dtmf_began = 0;
01632    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01633       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01634       /* Reinitialise the detector for the next block */
01635       for (i = 0;  i < 6;  i++) {
01636          goertzel_reset(&s->tone_out[i]);
01637       }
01638       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01639       s->current_sample = 0;
01640    } else {
01641       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01642       /* Reinitialise the detector for the next block */
01643       for (i = 0;  i < 4;  i++) {
01644          goertzel_reset(&s->row_out[i]);
01645          goertzel_reset(&s->col_out[i]);
01646       }
01647       s->lasthit = s->current_hit = 0;
01648       s->energy = 0.0;
01649       s->current_sample = 0;
01650       s->hits = 0;
01651       s->misses = 0;
01652    }
01653 
01654    dsp->digit_state.digits[0] = '\0';
01655    dsp->digit_state.current_digits = 0;
01656 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1583 of file dsp.c.

References ast_free.

Referenced by __ast_play_and_record(), __oh323_destroy(), analog_ss_thread(), background_detect_exec(), chan_list_destructor(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_session(), disable_dsp_detect(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), my_all_subchannels_hungup(), my_dsp_set_digitmode(), and sip_rtp_read().

01584 {
01585    ast_free(dsp);
01586 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1720 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01721 {
01722    return dsp->tcount;
01723 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1757 of file dsp.c.

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

01758 {
01759    return thresholds[which];
01760 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1715 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01716 {
01717    return dsp->tstate;
01718 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1762 of file dsp.c.

References _dsp_init().

Referenced by main().

01763 {
01764    return _dsp_init(0);
01765 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1540 of file dsp.c.

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_HISTORY, and ast_dsp::threshold.

Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), enable_dsp_detect(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), my_dsp_set_digitmode(), and read_config().

01541 {
01542    struct ast_dsp *dsp;
01543    
01544    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01545       dsp->threshold = DEFAULT_THRESHOLD;
01546       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01547       dsp->busycount = DSP_HISTORY;
01548       dsp->digitmode = DSP_DIGITMODE_DTMF;
01549       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01550       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01551 #ifdef BUSYDETECT_TONEONLY
01552       dsp->busytoneonly = 1;
01553 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01554 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01555 #endif
01556 #else
01557    dsp->busytoneonly = 0;
01558 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01559    dsp->busycompare = 1;
01560 #else
01561    dsp->busycompare = 0;
01562 #endif
01563 #endif
01564       /* Initialize digit detector */
01565       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01566       dsp->display_inband_dtmf_warning = 1;
01567       /* Initialize initial DSP progress detect parameters */
01568       ast_dsp_prog_reset(dsp);
01569       /* Initialize fax detector */
01570       ast_fax_detect_init(dsp);
01571    }
01572    return dsp;
01573 }

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

References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len(), and LOG_WARNING.

Referenced by do_waiting().

01307 {
01308        short *s;
01309        int len;
01310 
01311        if (f->frametype != AST_FRAME_VOICE) {
01312                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01313                return 0;
01314        }
01315        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01316                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01317                return 0;
01318        }
01319        s = f->data.ptr;
01320        len = f->datalen/2;
01321        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01322 }

struct ast_frame* ast_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.

Definition at line 1325 of file dsp.c.

References __ast_dsp_silence_noise(), AST_ALAW, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_getformatname(), ast_log(), AST_MULAW, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::features, ast_frame::frametype, len(), LOG_WARNING, ast_dsp::mute_fragments, ast_frame::ptr, and ast_frame::subclass.

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1523 of file dsp.c.

References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::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().

01524 {
01525    int max = 0;
01526    int x;
01527    
01528    dsp->gsamp_size = modes[dsp->progmode].size;
01529    dsp->gsamps = 0;
01530    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01531       if (modes[dsp->progmode].freqs[x]) {
01532          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01533          max = x + 1;
01534       }
01535    }
01536    dsp->freqcount = max;
01537    dsp->ringtimeout= 0;
01538 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1767 of file dsp.c.

References _dsp_init().

01768 {
01769    return _dsp_init(1);
01770 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01659 {
01660    int x;
01661    
01662    dsp->totalsilence = 0;
01663    dsp->gsamps = 0;
01664    for (x = 0; x < 4; x++) {
01665       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01666    }
01667    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01668    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01669    dsp->ringtimeout= 0;
01670 }

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

Set if silence and noice lengths must be compared for busy.

Definition at line 1607 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

01608 {
01609   if (compare > 0)
01610       dsp->busycompare = 1;
01611   else
01612       dsp->busycompare = 0;
01613 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1596 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01597 {
01598    if (cadences < 4) {
01599       cadences = 4;
01600    }
01601    if (cadences > DSP_HISTORY) {
01602       cadences = DSP_HISTORY;
01603    }
01604    dsp->busycount = cadences;
01605 }

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

Set expected lengths of the busy tones.

Definition at line 1615 of file dsp.c.

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

Referenced by dahdi_new().

01616 {
01617    dsp->busy_tonelength = tonelength;
01618    if (quietlength > 0)
01619       dsp->busy_quietlength = quietlength;
01620    else 
01621      dsp->busytoneonly = 1;
01622    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01623    if( fuzzy > 0 && fuzzy < 50 ) 
01624       dsp->busy_pattern_fuzzy = fuzzy;
01625 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1696 of file dsp.c.

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

Referenced by dahdi_new().

01697 {
01698    int x;
01699    
01700    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01701       if (!strcasecmp(aliases[x].name, zone)) {
01702          dsp->progmode = aliases[x].mode;
01703          ast_dsp_prog_reset(dsp);
01704          return 0;
01705       }
01706    }
01707    return -1;
01708 }

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

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

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

01673 {
01674    int new;
01675    int old;
01676    
01677    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01678    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01679    if (old != new) {
01680       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01681       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01682    }
01683    dsp->digitmode = digitmode;
01684    return 0;
01685 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1687 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01688 {
01689    if (dsp->faxmode != faxmode) {
01690       ast_fax_detect_init(dsp);
01691    }
01692    dsp->faxmode = faxmode;
01693    return 0;
01694 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1575 of file dsp.c.

References ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_DIGIT_DETECT, and ast_dsp::features.

Referenced by __oh323_new(), dahdi_handle_dtmf(), dahdi_new(), dahdi_read(), dahdi_setoption(), disable_dtmf_detect(), enable_dsp_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), my_handle_dtmf(), my_pri_ss7_open_media(), read_config(), and sip_rtp_read().

01576 {
01577    dsp->features = features;
01578    if (!(features & DSP_FEATURE_DIGIT_DETECT)) {
01579       dsp->display_inband_dtmf_warning = 0;
01580    }
01581 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1588 of file dsp.c.

References ast_dsp::threshold.

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

01589 {
01590    if (threshold < 256)
01591      dsp->threshold = 256;
01592    else
01593      dsp->threshold = threshold;
01594 }

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

References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len(), and LOG_WARNING.

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

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

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01711 {
01712    return (dsp->mute_fragments > 0);
01713 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 487 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_HITS_TO_BEGIN, DTMF_MISSES_TO_END, dtmf_detect_state_t::energy, goertzel_init(), 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, and dtmf_detect_state_t::row_out.

Referenced by ast_digit_detect_init().

00488 {
00489    int i;
00490 
00491    s->lasthit = 0;
00492    s->current_hit = 0;
00493    for (i = 0;  i < 4;  i++) {
00494       goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE);
00495       goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE);
00496       s->energy = 0.0;
00497    }
00498    s->current_sample = 0;
00499    s->hits = 0;
00500    s->misses = 0;
00501 
00502    s->hits_to_begin = DTMF_HITS_TO_BEGIN;
00503    s->misses_to_end = DTMF_MISSES_TO_END;
00504 }

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

Definition at line 481 of file dsp.c.

References ast_tone_detect_init(), ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, and FAX_TONE_CNG_FREQ.

Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

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

00507 {
00508    int i;
00509    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00510    for (i = 0;  i < 6;  i++) {
00511       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00512    }
00513    s->current_sample = 0;
00514    s->current_hit = 0;
00515 }

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

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

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

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

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_sample, 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, dtmf_detect_state_t::energy, goertzel_result(), goertzel_sample(), mute, dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, and digit_detect_state_t::td.

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

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

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

00347 {
00348    s->v2 = s->v3 = s->chunky = 0.0;
00349    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00350    s->samples = samples;
00351 }

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

Definition at line 353 of file dsp.c.

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

Referenced by ast_dsp_digitreset().

00354 {
00355    s->v2 = s->v3 = s->chunky = 0.0;
00356 }

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

Definition at line 337 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(), and dtmf_detect().

00338 {
00339    goertzel_result_t r;
00340    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00341    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00342    r.power = s->chunky * 2;
00343    return (float)r.value * (float)(1 << r.power);
00344 }

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

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

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

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

Definition at line 327 of file dsp.c.

References goertzel_sample().

00328 {
00329    int i;
00330    
00331    for (i = 0; i < count; i++) {
00332       goertzel_sample(s, samps[i]);
00333    }
00334 }

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

References mf_detect_state_t::current_sample, goertzel_sample(), digit_detect_state_t::mf, MF_GSIZE, mute, mf_detect_state_t::mute_samples, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

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

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

Definition at line 411 of file dsp.c.

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

00412 {
00413    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00414       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00415       return;
00416    }
00417 
00418    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00419 }

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

Definition at line 946 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

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

00636 {
00637    s->detected_digits++;
00638    if (s->current_digits < MAX_DTMF_DIGITS) {
00639       s->digitlen[s->current_digits] = 0;
00640       s->digits[s->current_digits++] = digit;
00641       s->digits[s->current_digits] = '\0';
00642    } else {
00643       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00644       s->lost_digits++;
00645    }
00646 }

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

Definition at line 531 of file dsp.c.

References tone_detect_state_t::energy, goertzel_sample(), mute, tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, and tone_detect_state_t::tone.

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


Variable Documentation

struct progalias aliases[] [static]

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

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

const float dtmf_col[] [static]

Initial value:

 {
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 300 of file dsp.c.

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

Definition at line 306 of file dsp.c.

const float dtmf_row[] [static]

Initial value:

 {
   697.0,  770.0,  852.0,  941.0
}

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

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().

int thresholds[THRESHOLD_MAX] [static]

Definition at line 308 of file dsp.c.


Generated on Mon Oct 8 12:39:21 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7