Sat Nov 1 06:29:02 2008

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"

Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

struct  ast_dsp
struct  dtmf_detect_state_t
struct  goertzel_state_t
struct  mf_detect_state_t
struct  progalias
struct  progress

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#define BUSYDETECT_MARTIN
#define DEFAULT_THRESHOLD   512
#define DSP_HISTORY   15
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_DETECT
#define FAX_THRESHOLD   8.0e7
#define FIX_INF(inf)
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#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_400 = 0
}
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_digitdetect (struct ast_dsp *dsp, short *s, int len, int *writeback)
static int __ast_dsp_silence (struct ast_dsp *dsp, short *s, int len, int *totalsilence)
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.
int ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *inf)
 Return non-zero if DTMF hit was found.
int ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector.
void ast_dsp_frame_freed (struct ast_frame *fr)
 Hint that a frame from a dsp was freed.
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_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
 Get pending DTMF/MF digits.
ast_dspast_dsp_new (void)
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)
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.
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.
static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect)
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 (mf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback)
static int pair_there (float p1, float p2, float i1, float i2, float e)

Variables

static struct progalias aliases []
static char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static float dtmf_col []
static char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_row []
static float fax_freq = 1100.0
static float mf_tones []
static struct progress modes []


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

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 184 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 185 of file dsp.c.

#define BUSYDETECT_MARTIN

Definition at line 190 of file dsp.c.

#define DEFAULT_THRESHOLD   512

Definition at line 113 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 124 of file dsp.c.

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

#define DTMF_NORMAL_TWIST   6.3

Definition at line 167 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 169 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST   ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)

Definition at line 168 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 156 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 171 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 158 of file dsp.c.

#define FAX_DETECT

Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE

Definition at line 127 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

#define FIX_INF ( inf   ) 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128

Definition at line 142 of file dsp.c.

Referenced by dtmf_detect(), and mf_detect().

#define MF_GSIZE   120

Definition at line 709 of file dsp.c.

Referenced by mf_detect().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

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

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

enum busy_detect

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

00115                  {
00116    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last silence periods */
00117    BUSY_PAT_PERCENT = 7,   /*!< The percentage difference between measured and actual pattern */
00118    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00119    BUSY_MIN = 75,          /*!< Busy must be at least 80 ms in half-cadence */
00120    BUSY_MAX =3100          /*!< Busy can't be longer than 3100 ms in half-cadence */
00121 };

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_400  For UK mode

Definition at line 76 of file dsp.c.

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

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

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

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

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

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 70 of file dsp.c.

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


Function Documentation

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

Definition at line 1070 of file dsp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, 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_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_NOTICE, LOG_WARNING, pair_there(), 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().

01071 {
01072    int x;
01073    int y;
01074    int pass;
01075    int newstate = DSP_TONE_STATE_SILENCE;
01076    int res = 0;
01077    while(len) {
01078       /* Take the lesser of the number of samples we need and what we have */
01079       pass = len;
01080       if (pass > dsp->gsamp_size - dsp->gsamps) 
01081          pass = dsp->gsamp_size - dsp->gsamps;
01082       for (x=0;x<pass;x++) {
01083          for (y=0;y<dsp->freqcount;y++) 
01084             goertzel_sample(&dsp->freqs[y], s[x]);
01085          dsp->genergy += s[x] * s[x];
01086       }
01087       s += pass;
01088       dsp->gsamps += pass;
01089       len -= pass;
01090       if (dsp->gsamps == dsp->gsamp_size) {
01091          float hz[7];
01092          for (y=0;y<7;y++)
01093             hz[y] = goertzel_result(&dsp->freqs[y]);
01094 #if 0
01095          printf("\n350:     425:     440:     480:     620:     950:     1400:    1800:    Energy:   \n");
01096          printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 
01097             hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy);
01098 #endif
01099          switch(dsp->progmode) {
01100          case PROG_MODE_NA:
01101             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
01102                newstate = DSP_TONE_STATE_BUSY;
01103             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01104                newstate = DSP_TONE_STATE_RINGING;
01105             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01106                newstate = DSP_TONE_STATE_DIALTONE;
01107             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01108                newstate = DSP_TONE_STATE_SPECIAL1;
01109             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01110                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
01111                   newstate = DSP_TONE_STATE_SPECIAL2;
01112             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01113                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
01114                   newstate = DSP_TONE_STATE_SPECIAL3;
01115             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01116                newstate = DSP_TONE_STATE_TALKING;
01117             } else
01118                newstate = DSP_TONE_STATE_SILENCE;
01119             break;
01120          case PROG_MODE_CR:
01121             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01122                newstate = DSP_TONE_STATE_RINGING;
01123             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01124                newstate = DSP_TONE_STATE_TALKING;
01125             } else
01126                newstate = DSP_TONE_STATE_SILENCE;
01127             break;
01128          case PROG_MODE_UK:
01129             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
01130                newstate = DSP_TONE_STATE_HUNGUP;
01131             }
01132             break;
01133          default:
01134             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01135          }
01136          if (newstate == dsp->tstate) {
01137             dsp->tcount++;
01138             if (dsp->ringtimeout)
01139                dsp->ringtimeout++;
01140             switch (dsp->tstate) {
01141                case DSP_TONE_STATE_RINGING:
01142                   if ((dsp->features & DSP_PROGRESS_RINGING) &&
01143                       (dsp->tcount==THRESH_RING)) {
01144                      res = AST_CONTROL_RINGING;
01145                      dsp->ringtimeout= 1;
01146                   }
01147                   break;
01148                case DSP_TONE_STATE_BUSY:
01149                   if ((dsp->features & DSP_PROGRESS_BUSY) &&
01150                       (dsp->tcount==THRESH_BUSY)) {
01151                      res = AST_CONTROL_BUSY;
01152                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01153                   }
01154                   break;
01155                case DSP_TONE_STATE_TALKING:
01156                   if ((dsp->features & DSP_PROGRESS_TALK) &&
01157                       (dsp->tcount==THRESH_TALK)) {
01158                      res = AST_CONTROL_ANSWER;
01159                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01160                   }
01161                   break;
01162                case DSP_TONE_STATE_SPECIAL3:
01163                   if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01164                       (dsp->tcount==THRESH_CONGESTION)) {
01165                      res = AST_CONTROL_CONGESTION;
01166                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01167                   }
01168                   break;
01169                case DSP_TONE_STATE_HUNGUP:
01170                   if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01171                       (dsp->tcount==THRESH_HANGUP)) {
01172                      res = AST_CONTROL_HANGUP;
01173                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01174                   }
01175                   break;
01176             }
01177             if (dsp->ringtimeout==THRESH_RING2ANSWER) {
01178 #if 0
01179                ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n");
01180 #endif
01181                res = AST_CONTROL_ANSWER;
01182                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01183             }
01184          } else {
01185 #if 0
01186             ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01187             ast_log(LOG_NOTICE, "Start state %d\n", newstate);
01188 #endif
01189             dsp->tstate = newstate;
01190             dsp->tcount = 1;
01191          }
01192          
01193          /* Reset goertzel */                
01194          for (x=0;x<7;x++)
01195             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01196          dsp->gsamps = 0;
01197          dsp->genergy = 0.0;
01198       }
01199    }
01200 #if 0
01201    if (res)
01202       printf("Returning %d\n", res);
01203 #endif      
01204    return res;
01205 }

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

Definition at line 995 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, ast_dsp::dtmf, dtmf_detect(), ast_dsp::features, ast_dsp::mf, mf_detect(), and ast_dsp::td.

Referenced by ast_dsp_digitdetect(), and ast_dsp_process().

00996 {
00997    int res;
00998    
00999    if (dsp->digitmode & DSP_DIGITMODE_MF)
01000       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
01001    else
01002       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
01003    return res;
01004 }

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

Definition at line 1220 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

01221 {
01222    int accum;
01223    int x;
01224    int res = 0;
01225 
01226    if (!len)
01227       return 0;
01228    accum = 0;
01229    for (x=0;x<len; x++) 
01230       accum += abs(s[x]);
01231    accum /= len;
01232    if (accum < dsp->threshold) {
01233       /* Silent */
01234       dsp->totalsilence += len/8;
01235       if (dsp->totalnoise) {
01236          /* Move and save history */
01237          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01238          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01239 /* we don't want to check for busydetect that frequently */
01240 #if 0
01241          dsp->busymaybe = 1;
01242 #endif
01243       }
01244       dsp->totalnoise = 0;
01245       res = 1;
01246    } else {
01247       /* Not silent */
01248       dsp->totalnoise += len/8;
01249       if (dsp->totalsilence) {
01250          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01251          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01252          /* Move and save history */
01253          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01254          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01255          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01256          if (silence1 < silence2) {
01257             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01258                dsp->busymaybe = 1;
01259             else 
01260                dsp->busymaybe = 0;
01261          } else {
01262             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01263                dsp->busymaybe = 1;
01264             else 
01265                dsp->busymaybe = 0;
01266          }
01267       }
01268       dsp->totalsilence = 0;
01269    }
01270    if (totalsilence)
01271       *totalsilence = dsp->totalsilence;
01272    return res;
01273 }

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

References ast_dsp_busydetect(), ast_log(), BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, BUSY_THRESHOLD, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, and LOG_NOTICE.

Referenced by ast_dsp_busydetect(), and ast_dsp_process().

01277 {
01278    int res = 0, x;
01279 #ifndef BUSYDETECT_TONEONLY
01280    int avgsilence = 0, hitsilence = 0;
01281 #endif
01282    int avgtone = 0, hittone = 0;
01283    if (!dsp->busymaybe)
01284       return res;
01285    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01286 #ifndef BUSYDETECT_TONEONLY
01287       avgsilence += dsp->historicsilence[x];
01288 #endif
01289       avgtone += dsp->historicnoise[x];
01290    }
01291 #ifndef BUSYDETECT_TONEONLY
01292    avgsilence /= dsp->busycount;
01293 #endif
01294    avgtone /= dsp->busycount;
01295    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01296 #ifndef BUSYDETECT_TONEONLY
01297       if (avgsilence > dsp->historicsilence[x]) {
01298          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01299             hitsilence++;
01300       } else {
01301          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01302             hitsilence++;
01303       }
01304 #endif
01305       if (avgtone > dsp->historicnoise[x]) {
01306          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01307             hittone++;
01308       } else {
01309          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01310             hittone++;
01311       }
01312    }
01313 #ifndef BUSYDETECT_TONEONLY
01314    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01315        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01316        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01317 #else
01318    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01319 #endif
01320 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01321 #ifdef BUSYDETECT_TONEONLY
01322 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
01323 #endif
01324       if (avgtone > avgsilence) {
01325          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01326             res = 1;
01327       } else {
01328          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01329             res = 1;
01330       }
01331 #else
01332       res = 1;
01333 #endif
01334    }
01335    /* If we know the expected busy tone length, check we are in the range */
01336    if (res && (dsp->busy_tonelength > 0)) {
01337       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01338 #if 0
01339          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
01340                   avgtone, dsp->busy_tonelength);
01341 #endif
01342          res = 0;
01343       }
01344    }
01345 #ifndef BUSYDETECT_TONEONLY
01346    /* If we know the expected busy tone silent-period length, check we are in the range */
01347    if (res && (dsp->busy_quietlength > 0)) {
01348       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01349 #if 0
01350          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01351                   avgsilence, dsp->busy_quietlength);
01352 #endif
01353          res = 0;
01354       }
01355    }
01356 #endif
01357 #ifndef BUSYDETECT_TONEONLY
01358 #if 1
01359    if (res)
01360       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01361 #endif
01362 #endif
01363    return res;
01364 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1207 of file dsp.c.

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

01208 {
01209    if (inf->frametype != AST_FRAME_VOICE) {
01210       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01211       return 0;
01212    }
01213    if (inf->subclass != AST_FORMAT_SLINEAR) {
01214       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01215       return 0;
01216    }
01217    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01218 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

Definition at line 1006 of file dsp.c.

References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len, LOG_WARNING, s, and ast_frame::subclass.

01007 {
01008    short *s;
01009    int len;
01010    int ign=0;
01011 
01012    if (inf->frametype != AST_FRAME_VOICE) {
01013       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01014       return 0;
01015    }
01016    if (inf->subclass != AST_FORMAT_SLINEAR) {
01017       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01018       return 0;
01019    }
01020    s = inf->data;
01021    len = inf->datalen / 2;
01022    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01023 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1765 of file dsp.c.

References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

Referenced by dahdi_hangup(), dahdi_new(), dahdi_setoption(), mgcp_new(), sip_new(), and ss_thread().