Sun Dec 18 20:55:50 2011

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.
struct ast_dspast_dsp_new (void)
struct ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
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.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 184 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 185 of file dsp.c.

Referenced by mf_detect().

#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.

Referenced by dtmf_detect().

#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

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

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 BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalnoise, and ast_dsp::totalsilence.

Referenced by ast_dsp_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, 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 mgcp_new(), mkintf(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

01766 {
01767    int new;
01768    int old;
01769    
01770    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01771    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01772    if (old != new) {
01773       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01774       if (new & DSP_DIGITMODE_MF)
01775          ast_mf_detect_init(&dsp->td.mf);
01776       else
01777          ast_dtmf_detect_init(&dsp->td.dtmf);
01778    }
01779    dsp->digitmode = digitmode;
01780    return 0;
01781 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1702 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, dtmf_detect_state_t::energy, dtmf_detect_state_t::fax_tone, goertzel_reset(), mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, ast_dsp::mf, dtmf_detect_state_t::mhit, mf_detect_state_t::mhit, dtmf_detect_state_t::row_out, ast_dsp::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out.

Referenced by ss_thread().

01703 {
01704    int i;
01705    
01706    dsp->thinkdigit = 0;
01707    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01708       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01709       dsp->td.mf.current_digits = 0;
01710       /* Reinitialise the detector for the next block */
01711       for (i = 0;  i < 6;  i++) {
01712          goertzel_reset(&dsp->td.mf.tone_out[i]);
01713 #ifdef OLD_DSP_ROUTINES
01714          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01715 #endif         
01716       }
01717 #ifdef OLD_DSP_ROUTINES
01718       dsp->td.mf.energy = 0.0;
01719       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01720 #else
01721       dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0;
01722 #endif      
01723       dsp->td.mf.current_sample = 0;
01724    } else {
01725       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01726       dsp->td.dtmf.current_digits = 0;
01727       /* Reinitialise the detector for the next block */
01728       for (i = 0;  i < 4;  i++) {
01729          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01730          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01731 #ifdef OLD_DSP_ROUTINES
01732          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01733          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01734 #endif         
01735       }
01736 #ifdef FAX_DETECT
01737       goertzel_reset (&dsp->td.dtmf.fax_tone);
01738 #endif
01739 #ifdef OLD_DSP_ROUTINES
01740 #ifdef FAX_DETECT
01741       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01742 #endif
01743       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01744 #else
01745       dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
01746 #endif      
01747       dsp->td.dtmf.energy = 0.0;
01748       dsp->td.dtmf.current_sample = 0;
01749    }
01750 }

void ast_dsp_frame_freed ( struct ast_frame fr  ) 

Hint that a frame from a dsp was freed.

This is called from ast_frame_free if AST_FRFLAG_FROM_DSP is set. This occurs because it is possible for the dsp to be freed while someone still holds a reference to the frame that is in that dsp. This has been known to happen when the dsp on a Zap channel detects a busy signal. The channel is hung up, and the application that read the frame to begin with still has a reference to the frame.

Returns:
nothing

Definition at line 1807 of file dsp.c.

References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, f, and ast_dsp::freqcount.

Referenced by ast_frame_free().

01808 {
01809    struct ast_dsp *dsp;
01810 
01811    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01812 
01813    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01814 
01815    if (dsp->freqcount != -1)
01816       return;
01817    
01818    ast_dsp_free(dsp);
01819 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1665 of file dsp.c.

References AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::f, free, and ast_dsp::freqcount.

Referenced by __ast_play_and_record(), __oh323_destroy(), ast_dsp_frame_freed(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), destroy_endpoint(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), and zt_hangup().

01666 {
01667    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01668       /* If this flag is still set, that means that the dsp's destruction 
01669        * been torn down, while we still have a frame out there being used.
01670        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01671        * will get destroyed, too. */
01672 
01673       /* Set the magic hint that this has been requested to be destroyed. */
01674       dsp->freqcount = -1;
01675 
01676       return;
01677    }
01678    free(dsp);
01679 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1802 of file dsp.c.

References ast_dsp::tcount.

01803 {
01804    return dsp->tcount;
01805 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1797 of file dsp.c.

References ast_dsp::tstate.

01798 {
01799    return dsp->tstate;
01800 }

int ast_dsp_getdigits ( struct ast_dsp dsp,
char *  buf,
int  max 
)

Get pending DTMF/MF digits.

Definition at line 1045 of file dsp.c.

References dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

01046 {
01047    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01048       if (max > dsp->td.mf.current_digits)
01049          max = dsp->td.mf.current_digits;
01050       if (max > 0) {
01051          memcpy(buf, dsp->td.mf.digits, max);
01052          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01053          dsp->td.mf.current_digits -= max;
01054       }
01055       buf[max] = '\0';
01056       return  max;
01057    } else {
01058       if (max > dsp->td.dtmf.current_digits)
01059          max = dsp->td.dtmf.current_digits;
01060       if (max > 0) {
01061          memcpy (buf, dsp->td.dtmf.digits, max);
01062          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01063          dsp->td.dtmf.current_digits -= max;
01064       }
01065       buf[max] = '\0';
01066       return  max;
01067    }
01068 }

struct ast_dsp* ast_dsp_new ( void   )  [read]

Definition at line 1644 of file dsp.c.

References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::dtmf, ast_dsp::features, ast_dsp::td, and ast_dsp::threshold.

Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), record_exec(), sip_dtmfmode(), sip_new(), and zt_new().

01645 {
01646    struct ast_dsp *dsp;
01647    
01648    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01649       dsp->threshold = DEFAULT_THRESHOLD;
01650       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01651       dsp->busycount = DSP_HISTORY;
01652       /* Initialize DTMF detector */
01653       ast_dtmf_detect_init(&dsp->td.dtmf);
01654       /* Initialize initial DSP progress detect parameters */
01655       ast_dsp_prog_reset(dsp);
01656    }
01657    return dsp;
01658 }

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

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

Definition at line 1430 of file dsp.c.

References __ast_dsp_call_progress(), __ast_dsp_digitdetect(), __ast_dsp_silence(), ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRFLAG_FROM_DSP, ast_frfree, ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len, LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

01431 {
01432    int silence;
01433    int res;
01434    int digit;
01435    int x;
01436    short *shortdata;
01437    unsigned char *odata;
01438    int len;
01439    int writeback = 0;
01440 
01441 #define FIX_INF(inf) do { \
01442       if (writeback) { \
01443          switch(inf->subclass) { \
01444          case AST_FORMAT_SLINEAR: \
01445             break; \
01446          case AST_FORMAT_ULAW: \
01447             for (x=0;x<len;x++) \
01448                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01449             break; \
01450          case AST_FORMAT_ALAW: \
01451             for (x=0;x<len;x++) \
01452                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01453             break; \
01454          } \
01455       } \
01456    } while(0) 
01457 
01458    if (!af)
01459       return NULL;
01460    if (af->frametype != AST_FRAME_VOICE)
01461       return af;
01462    odata = af->data;
01463    len = af->datalen;
01464    /* Make sure we have short data */
01465    switch(af->subclass) {
01466    case AST_FORMAT_SLINEAR:
01467       shortdata = af->data;
01468       len = af->datalen / 2;
01469       break;
01470    case AST_FORMAT_ULAW:
01471       shortdata = alloca(af->datalen * 2);
01472       for (x = 0;x < len; x++) 
01473          shortdata[x] = AST_MULAW(odata[x]);
01474       break;
01475    case AST_FORMAT_ALAW:
01476       shortdata = alloca(af->datalen * 2);
01477       for (x = 0; x < len; x++) 
01478          shortdata[x] = AST_ALAW(odata[x]);
01479       break;
01480    default:
01481       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01482       return af;
01483    }
01484    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01485    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01486       memset(&dsp->f, 0, sizeof(dsp->f));
01487       dsp->f.frametype = AST_FRAME_NULL;
01488       ast_frfree(af);
01489       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01490       return &dsp->f;
01491    }
01492    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01493       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01494       memset(&dsp->f, 0, sizeof(dsp->f));
01495       dsp->f.frametype = AST_FRAME_CONTROL;
01496       dsp->f.subclass = AST_CONTROL_BUSY;
01497       ast_frfree(af);
01498       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01499       return &dsp->f;
01500    }
01501    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01502       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01503 #if 0
01504       if (digit)
01505          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01506 #endif         
01507       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01508          if (!dsp->thinkdigit) {
01509             if (digit) {
01510                /* Looks like we might have something.  
01511                 * Request a conference mute for the moment */
01512                memset(&dsp->f, 0, sizeof(dsp->f));
01513                dsp->f.frametype = AST_FRAME_DTMF;
01514                dsp->f.subclass = 'm';
01515                dsp->thinkdigit = 'x';
01516                FIX_INF(af);
01517                if (chan)
01518                   ast_queue_frame(chan, af);
01519                ast_frfree(af);
01520                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01521                return &dsp->f;
01522             }
01523          } else {
01524             if (digit) {
01525                /* Thought we saw one last time.  Pretty sure we really have now */
01526                if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01527                   /* If we found a digit, and we're changing digits, go
01528                      ahead and send this one, but DON'T stop confmute because
01529                      we're detecting something else, too... */
01530                   memset(&dsp->f, 0, sizeof(dsp->f));
01531                   dsp->f.frametype = AST_FRAME_DTMF_END;
01532                   dsp->f.subclass = dsp->thinkdigit;
01533                   FIX_INF(af);
01534                   if (chan)
01535                      ast_queue_frame(chan, af);
01536                   ast_frfree(af);
01537                } else {
01538                   dsp->thinkdigit = digit;
01539                   memset(&dsp->f, 0, sizeof(dsp->f));
01540                   dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
01541                   dsp->f.subclass = dsp->thinkdigit;
01542                   FIX_INF(af);
01543                   if (chan)
01544                      ast_queue_frame(chan, af);
01545                   ast_frfree(af);
01546                }
01547                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01548                return &dsp->f;
01549             } else {
01550                memset(&dsp->f, 0, sizeof(dsp->f));
01551                if (dsp->thinkdigit != 'x') {
01552                   /* If we found a digit, send it now */
01553                   dsp->f.frametype = AST_FRAME_DTMF_END;
01554                   dsp->f.subclass = dsp->thinkdigit;
01555                   dsp->thinkdigit = 0;
01556                } else {
01557                   dsp->f.frametype = AST_FRAME_DTMF;
01558                   dsp->f.subclass = 'u';
01559                   dsp->thinkdigit = 0;
01560                }
01561                FIX_INF(af);
01562                if (chan)
01563                   ast_queue_frame(chan, af);
01564                ast_frfree(af);
01565                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01566                return &dsp->f;
01567             }
01568          }
01569       } else if (!digit) {
01570          /* Only check when there is *not* a hit... */
01571          if (dsp->digitmode & DSP_DIGITMODE_MF) {
01572             if (dsp->td.mf.current_digits) {
01573                memset(&dsp->f, 0, sizeof(dsp->f));
01574                dsp->f.frametype = AST_FRAME_DTMF;
01575                dsp->f.subclass = dsp->td.mf.digits[0];
01576                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01577                dsp->td.mf.current_digits--;
01578                FIX_INF(af);
01579                if (chan)
01580                   ast_queue_frame(chan, af);
01581                ast_frfree(af);
01582                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01583                return &dsp->f;
01584             }
01585          } else {
01586             if (dsp->td.dtmf.current_digits) {
01587                memset(&dsp->f, 0, sizeof(dsp->f));
01588                dsp->f.frametype = AST_FRAME_DTMF_END;
01589                dsp->f.subclass = dsp->td.dtmf.digits[0];
01590                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01591                dsp->td.dtmf.current_digits--;
01592                FIX_INF(af);
01593                if (chan)
01594                   ast_queue_frame(chan, af);
01595                ast_frfree(af);
01596                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01597                return &dsp->f;
01598             }
01599          }
01600       }
01601    }
01602    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01603       res = __ast_dsp_call_progress(dsp, shortdata, len);
01604       if (res) {
01605          switch(res) {
01606          case AST_CONTROL_ANSWER:
01607          case AST_CONTROL_BUSY:
01608          case AST_CONTROL_RINGING:
01609          case AST_CONTROL_CONGESTION:
01610          case AST_CONTROL_HANGUP:
01611             memset(&dsp->f, 0, sizeof(dsp->f));
01612             dsp->f.frametype = AST_FRAME_CONTROL;
01613             dsp->f.subclass = res;
01614             dsp->f.src = "dsp_progress";
01615             if (chan) 
01616                ast_queue_frame(chan, &dsp->f);
01617             break;
01618          default:
01619             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01620          }
01621       }
01622    }
01623    FIX_INF(af);
01624    return af;
01625 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1627 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01628 {
01629    int max = 0;
01630    int x;
01631    
01632    dsp->gsamp_size = modes[dsp->progmode].size;
01633    dsp->gsamps = 0;
01634    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01635       if (modes[dsp->progmode].freqs[x]) {
01636          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01637          max = x + 1;
01638       }
01639    }
01640    dsp->freqcount = max;
01641    dsp->ringtimeout= 0;
01642 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01753 {
01754    int x;
01755    
01756    dsp->totalsilence = 0;
01757    dsp->gsamps = 0;
01758    for (x=0;x<4;x++)
01759       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01760    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01761    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01762    dsp->ringtimeout= 0;
01763 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1686 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

01687 {
01688    if (cadences < 4)
01689       cadences = 4;
01690    if (cadences > DSP_HISTORY)
01691       cadences = DSP_HISTORY;
01692    dsp->busycount = cadences;
01693 }

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

Set expected lengths of the busy tone.

Definition at line 1695 of file dsp.c.

References ast_log(), ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and LOG_DEBUG.

Referenced by zt_new().

01696 {
01697    dsp->busy_tonelength = tonelength;
01698    dsp->busy_quietlength = quietlength;
01699    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01700 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1783 of file dsp.c.

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

Referenced by zt_new().

01784 {
01785    int x;
01786    
01787    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01788       if (!strcasecmp(aliases[x].name, zone)) {
01789          dsp->progmode = aliases[x].mode;
01790          ast_dsp_prog_reset(dsp);
01791          return 0;
01792       }
01793    }
01794    return -1;
01795 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1660 of file dsp.c.

References ast_dsp::features.

Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

01661 {
01662    dsp->features = features;
01663 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1681 of file dsp.c.

References ast_dsp::threshold.

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

01682 {
01683    dsp->threshold = threshold;
01684 }

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

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

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

01413 {
01414    short *s;
01415    int len;
01416    
01417    if (f->frametype != AST_FRAME_VOICE) {
01418       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01419       return 0;
01420    }
01421    if (f->subclass != AST_FORMAT_SLINEAR) {
01422       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01423       return 0;
01424    }
01425    s = f->data;
01426    len = f->datalen/2;
01427    return __ast_dsp_silence(dsp, s, len, totalsilence);
01428 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 363 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::detected_digits, dtmf_detect_state_t::digits, dtmf_detect_state_t::energy, dtmf_detect_state_t::fax_tone, goertzel_init(), dtmf_detect_state_t::lasthit, dtmf_detect_state_t::lost_digits, dtmf_detect_state_t::mhit, and dtmf_detect_state_t::row_out.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

00364 {
00365    int i;
00366 
00367 #ifdef OLD_DSP_ROUTINES
00368    s->hit1 = 
00369    s->mhit = 
00370    s->hit3 =
00371    s->hit4 = 
00372    s->hit2 = 0;
00373 #else
00374    s->lasthit = 0;
00375 #endif
00376    for (i = 0;  i < 4;  i++) {
00377       goertzel_init (&s->row_out[i], dtmf_row[i], 102);
00378       goertzel_init (&s->col_out[i], dtmf_col[i], 102);
00379 #ifdef OLD_DSP_ROUTINES
00380       goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
00381       goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
00382 #endif   
00383       s->energy = 0.0;
00384    }
00385 #ifdef FAX_DETECT
00386    /* Same for the fax dector */
00387    goertzel_init (&s->fax_tone, fax_freq, 102);
00388 
00389 #ifdef OLD_DSP_ROUTINES
00390    /* Same for the fax dector 2nd harmonic */
00391    goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
00392 #endif   
00393 #endif /* FAX_DETECT */
00394    s->current_sample = 0;
00395    s->detected_digits = 0;
00396    s->current_digits = 0;
00397    memset(&s->digits, 0, sizeof(s->digits));
00398    s->lost_digits = 0;
00399    s->digits[0] = '\0';
00400 }

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 402 of file dsp.c.

References mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, mf_detect_state_t::detected_digits, mf_detect_state_t::digits, goertzel_init(), mf_detect_state_t::hits, mf_detect_state_t::lost_digits, mf_detect_state_t::mhit, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_digitmode().

00403 {
00404    int i;
00405 #ifdef OLD_DSP_ROUTINES
00406    s->hit1 = 
00407    s->hit2 = 0;
00408 #else 
00409    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00410 #endif
00411    for (i = 0;  i < 6;  i++) {
00412       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00413 #ifdef OLD_DSP_ROUTINES
00414       goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
00415       s->energy = 0.0;
00416 #endif
00417    }
00418    s->current_digits = 0;
00419    memset(&s->digits, 0, sizeof(s->digits));
00420    s->current_sample = 0;
00421    s->detected_digits = 0;
00422    s->lost_digits = 0;
00423    s->digits[0] = '\0';
00424    s->mhit = 0;
00425 }

static int dtmf_detect ( dtmf_detect_state_t s,
int16_t  amp[],
int  samples,
int  digitmode,
int *  writeback,
int  faxdetect 
) [static]

Definition at line 427 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::detected_digits, dtmf_detect_state_t::digit_hits, dtmf_detect_state_t::digits, DSP_DIGITMODE_NOQUELCH, 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_state_t::fac, dtmf_detect_state_t::fax_hits, FAX_THRESHOLD, dtmf_detect_state_t::fax_tone, goertzel_reset(), goertzel_result(), dtmf_detect_state_t::lasthit, dtmf_detect_state_t::lost_digits, MAX_DTMF_DIGITS, dtmf_detect_state_t::mhit, dtmf_detect_state_t::row_out, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_digitdetect().

00429 {
00430    float row_energy[4];
00431    float col_energy[4];
00432 #ifdef FAX_DETECT
00433    float fax_energy;
00434 #ifdef OLD_DSP_ROUTINES
00435    float fax_energy_2nd;
00436 #endif   
00437 #endif /* FAX_DETECT */
00438    float famp;
00439    float v1;
00440    int i;
00441    int j;
00442    int sample;
00443    int best_row;
00444    int best_col;
00445    int hit;
00446    int limit;
00447 
00448    hit = 0;
00449    for (sample = 0;  sample < samples;  sample = limit) {
00450       /* 102 is optimised to meet the DTMF specs. */
00451       if ((samples - sample) >= (102 - s->current_sample))
00452          limit = sample + (102 - s->current_sample);
00453       else
00454          limit = samples;
00455 #if defined(USE_3DNOW)
00456       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00457       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00458 #ifdef OLD_DSP_ROUTINES
00459       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00460       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00461 #endif      
00462       /* XXX Need to fax detect for 3dnow too XXX */
00463       #warning "Fax Support Broken"
00464 #else
00465       /* The following unrolled loop takes only 35% (rough estimate) of the 
00466          time of a rolled loop on the machine on which it was developed */
00467       for (j=sample;j<limit;j++) {
00468          famp = amp[j];
00469          s->energy += famp*famp;
00470          /* With GCC 2.95, the following unrolled code seems to take about 35%
00471             (rough estimate) as long as a neat little 0-3 loop */
00472          v1 = s->row_out[0].v2;
00473          s->row_out[0].v2 = s->row_out[0].v3;
00474          s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
00475          v1 = s->col_out[0].v2;
00476          s->col_out[0].v2 = s->col_out[0].v3;
00477          s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
00478          v1 = s->row_out[1].v2;
00479          s->row_out[1].v2 = s->row_out[1].v3;
00480          s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
00481          v1 = s->col_out[1].v2;
00482          s->col_out[1].v2 = s->col_out[1].v3;
00483          s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
00484          v1 = s->row_out[2].v2;
00485          s->row_out[2].v2 = s->row_out[2].v3;
00486          s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
00487          v1 = s->col_out[2].v2;
00488          s->col_out[2].v2 = s->col_out[2].v3;
00489          s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
00490          v1 = s->row_out[3].v2;
00491          s->row_out[3].v2 = s->row_out[3].v3;
00492          s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
00493          v1 = s->col_out[3].v2;
00494          s->col_out[3].v2 = s->col_out[3].v3;
00495          s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
00496 #ifdef FAX_DETECT
00497          /* Update fax tone */
00498          v1 = s->fax_tone.v2;
00499          s->fax_tone.v2 = s->fax_tone.v3;
00500          s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
00501 #endif /* FAX_DETECT */
00502 #ifdef OLD_DSP_ROUTINES
00503          v1 = s->col_out2nd[0].v2;
00504          s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
00505          s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
00506          v1 = s->row_out2nd[0].v2;
00507          s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
00508          s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
00509          v1 = s->col_out2nd[1].v2;
00510          s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
00511          s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
00512          v1 = s->row_out2nd[1].v2;
00513          s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
00514          s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
00515          v1 = s->col_out2nd[2].v2;
00516          s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
00517          s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
00518          v1 = s->row_out2nd[2].v2;
00519          s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
00520          s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
00521          v1 = s->col_out2nd[3].v2;
00522          s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
00523          s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
00524          v1 = s->row_out2nd[3].v2;
00525          s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
00526          s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
00527 #ifdef FAX_DETECT
00528          /* Update fax tone */            
00529          v1 = s->fax_tone.v2;
00530          s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
00531          s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
00532 #endif /* FAX_DETECT */
00533 #endif
00534       }
00535 #endif
00536       s->current_sample += (limit - sample);
00537       if (s->current_sample < 102) {
00538          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00539             /* If we had a hit last time, go ahead and clear this out since likely it
00540                will be another hit */
00541             for (i=sample;i<limit;i++) 
00542                amp[i] = 0;
00543             *writeback = 1;
00544          }
00545          continue;
00546       }
00547 #ifdef FAX_DETECT
00548       /* Detect the fax energy, too */
00549       fax_energy = goertzel_result(&s->fax_tone);
00550 #endif
00551       /* We are at the end of a DTMF detection block */
00552       /* Find the peak row and the peak column */
00553       row_energy[0] = goertzel_result (&s->row_out[0]);
00554       col_energy[0] = goertzel_result (&s->col_out[0]);
00555 
00556       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00557          row_energy[i] = goertzel_result (&s->row_out[i]);
00558          if (row_energy[i] > row_energy[best_row])
00559             best_row = i;
00560          col_energy[i] = goertzel_result (&s->col_out[i]);
00561          if (col_energy[i] > col_energy[best_col])
00562             best_col = i;
00563       }
00564       hit = 0;
00565       /* Basic signal level test and the twist test */
00566       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00567           col_energy[best_col] >= DTMF_THRESHOLD &&
00568           col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
00569           col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
00570          /* Relative peak test */
00571          for (i = 0;  i < 4;  i++) {
00572             if ((i != best_col &&
00573                 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00574                 (i != best_row 
00575                  && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00576                break;
00577             }
00578          }
00579 #ifdef OLD_DSP_ROUTINES
00580          /* ... and second harmonic test */
00581          if (i >= 4 && 
00582              (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
00583                       goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
00584              && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
00585 #else
00586          /* ... and fraction of total energy test */
00587          if (i >= 4 &&
00588              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
00589 #endif
00590             /* Got a hit */
00591             hit = dtmf_positions[(best_row << 2) + best_col];
00592             if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00593                /* Zero out frame data if this is part DTMF */
00594                for (i=sample;i<limit;i++) 
00595                   amp[i] = 0;
00596                *writeback = 1;
00597             }
00598 #ifdef OLD_DSP_ROUTINES
00599             /* Look for two successive similar results */
00600             /* The logic in the next test is:
00601                We need two successive identical clean detects, with
00602                something different preceeding it. This can work with
00603                back to back differing digits. More importantly, it
00604                can work with nasty phones that give a very wobbly start
00605                to a digit */
00606             if (hit == s->hit3  &&  s->hit3 != s->hit2) {
00607                s->mhit = hit;
00608                s->digit_hits[(best_row << 2) + best_col]++;
00609                s->detected_digits++;
00610                if (s->current_digits < MAX_DTMF_DIGITS) {
00611                   s->digits[s->current_digits++] = hit;
00612                   s->digits[s->current_digits] = '\0';
00613                } else {
00614                   s->lost_digits++;
00615                }
00616             }
00617 #endif
00618          }
00619       } 
00620 
00621 #ifndef OLD_DSP_ROUTINES
00622       /* Look for two successive similar results */
00623       /* The logic in the next test is:
00624          We need two successive identical clean detects, with
00625          something different preceeding it. This can work with
00626          back to back differing digits. More importantly, it
00627          can work with nasty phones that give a very wobbly start
00628          to a digit */
00629       if (hit == s->lasthit  &&  hit != s->mhit) {
00630          if (hit) {
00631             s->digit_hits[(best_row << 2) + best_col]++;
00632             s->detected_digits++;
00633             if (s->current_digits < MAX_DTMF_DIGITS) {
00634                s->digits[s->current_digits++] = hit;
00635                s->digits[s->current_digits] = '\0';
00636             } else {
00637                s->lost_digits++;
00638             }
00639          }
00640          s->mhit = hit;
00641       }
00642 #endif
00643 
00644 #ifdef FAX_DETECT
00645       if (!hit && (fax_energy >= FAX_THRESHOLD) && 
00646          (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
00647          (faxdetect)) {
00648 #if 0
00649          printf("Fax energy/Second Harmonic: %f\n", fax_energy);
00650 #endif               
00651          /* XXX Probably need better checking than just this the energy XXX */
00652          hit = 'f';
00653          s->fax_hits++;
00654       } else {
00655          if (s->fax_hits > 5) {
00656             hit = 'f';
00657             s->mhit = 'f';
00658             s->detected_digits++;
00659             if (s->current_digits < MAX_DTMF_DIGITS) {
00660                s->digits[s->current_digits++] = hit;
00661                s->digits[s->current_digits] = '\0';
00662             } else {
00663                s->lost_digits++;
00664             }
00665          }
00666          s->fax_hits = 0;
00667       }
00668 #endif /* FAX_DETECT */
00669 #ifdef OLD_DSP_ROUTINES
00670       s->hit1 = s->hit2;
00671       s->hit2 = s->hit3;
00672       s->hit3 = hit;
00673 #else
00674       s->lasthit = hit;
00675 #endif      
00676       /* Reinitialise the detector for the next block */
00677       for (i = 0;  i < 4;  i++) {
00678          goertzel_reset(&s->row_out[i]);
00679          goertzel_reset(&s->col_out[i]);
00680 #ifdef OLD_DSP_ROUTINES
00681          goertzel_reset(&s->row_out2nd[i]);
00682          goertzel_reset(&s->col_out2nd[i]);
00683 #endif         
00684       }
00685 #ifdef FAX_DETECT
00686       goertzel_reset (&s->fax_tone);
00687 #ifdef OLD_DSP_ROUTINES
00688       goertzel_reset (&s->fax_tone2nd);
00689 #endif         
00690 #endif
00691       s->energy = 0.0;
00692       s->current_sample = 0;
00693    }
00694 #ifdef OLD_DSP_ROUTINES
00695    if ((!s->mhit) || (s->mhit != hit)) {
00696       s->mhit = 0;
00697       return(0);
00698    }
00699    return (hit);
00700 #else
00701    return (s->mhit); /* return the debounced hit */
00702 #endif
00703 }

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

Definition at line 320 of file dsp.c.

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

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

00321 {
00322    s->v2 = s->v3 = 0.0;
00323    s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
00324 #ifndef OLD_DSP_ROUTINES
00325    s->samples = samples;
00326 #endif
00327 }

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

Definition at line 329 of file dsp.c.

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

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

00330 {
00331    s->v2 = s->v3 = 0.0;
00332 }

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

Definition at line 315 of file dsp.c.

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

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

00316 {
00317    return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
00318 }

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

Definition at line 296 of file dsp.c.

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

Referenced by __ast_dsp_call_progress(), and goertzel_update().

00297 {
00298    float v1;
00299    float fsamp  = sample;
00300    
00301    v1 = s->v2;
00302    s->v2 = s->v3;
00303    s->v3 = s->fac * s->v2 - v1 + fsamp;
00304 }

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

Definition at line 306 of file dsp.c.

References goertzel_sample().

00307 {
00308    int i;
00309    
00310    for (i=0;i<count;i++) 
00311       goertzel_sample(s, samps[i]);
00312 }

static int mf_detect ( mf_detect_state_t s,
int16_t  amp[],
int  samples,
int  digitmode,
int *  writeback 
) [static]

Definition at line 712 of file dsp.c.

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, mf_detect_state_t::detected_digits, mf_detect_state_t::digits, DSP_DIGITMODE_NOQUELCH, goertzel_state_t::fac, goertzel_reset(), goertzel_result(), mf_detect_state_t::hits, mf_detect_state_t::lost_digits, MAX_DTMF_DIGITS, MF_GSIZE, mf_detect_state_t::mhit, mf_detect_state_t::tone_out, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_digitdetect().

00714 {
00715 #ifdef OLD_DSP_ROUTINES
00716    float tone_energy[6];
00717    int best1;
00718    int best2;
00719    float max;
00720    int sofarsogood;
00721 #else
00722    float energy[6];
00723    int best;
00724    int second_best;
00725 #endif
00726    float famp;
00727    float v1;
00728    int i;
00729    int j;
00730    int sample;
00731    int hit;
00732    int limit;
00733 
00734    hit = 0;
00735    for (sample = 0;  sample < samples;  sample = limit) {
00736       /* 80 is optimised to meet the MF specs. */
00737       if ((samples - sample) >= (MF_GSIZE - s->current_sample))
00738          limit = sample + (MF_GSIZE - s->current_sample);
00739       else
00740          limit = samples;
00741 #if defined(USE_3DNOW)
00742       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
00743       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
00744 #ifdef OLD_DSP_ROUTINES
00745       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
00746       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
00747 #endif
00748       /* XXX Need to fax detect for 3dnow too XXX */
00749       #warning "Fax Support Broken"
00750 #else
00751       /* The following unrolled loop takes only 35% (rough estimate) of the 
00752          time of a rolled loop on the machine on which it was developed */
00753       for (j = sample;  j < limit;  j++) {
00754          famp = amp[j];
00755 #ifdef OLD_DSP_ROUTINES
00756          s->energy += famp*famp;
00757 #endif
00758          /* With GCC 2.95, the following unrolled code seems to take about 35%
00759             (rough estimate) as long as a neat little 0-3 loop */
00760          v1 = s->tone_out[0].v2;
00761          s->tone_out[0].v2 = s->tone_out[0].v3;
00762          s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
00763          v1 = s->tone_out[1].v2;
00764          s->tone_out[1].v2 = s->tone_out[1].v3;
00765          s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
00766          v1 = s->tone_out[2].v2;
00767          s->tone_out[2].v2 = s->tone_out[2].v3;
00768          s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
00769          v1 = s->tone_out[3].v2;
00770          s->tone_out[3].v2 = s->tone_out[3].v3;
00771          s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
00772          v1 = s->tone_out[4].v2;
00773          s->tone_out[4].v2 = s->tone_out[4].v3;
00774          s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
00775          v1 = s->tone_out[5].v2;
00776          s->tone_out[5].v2 = s->tone_out[5].v3;
00777          s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
00778 #ifdef OLD_DSP_ROUTINES
00779          v1 = s->tone_out2nd[0].v2;
00780          s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
00781          s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
00782          v1 = s->tone_out2nd[1].v2;
00783          s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
00784          s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
00785          v1 = s->tone_out2nd[2].v2;
00786          s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
00787          s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
00788          v1 = s->tone_out2nd[3].v2;
00789          s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
00790          s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
00791          v1 = s->tone_out2nd[4].v2;
00792          s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
00793          s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
00794          v1 = s->tone_out2nd[3].v2;
00795          s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
00796          s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
00797 #endif
00798       }
00799 #endif
00800       s->current_sample += (limit - sample);
00801       if (s->current_sample < MF_GSIZE) {
00802          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00803             /* If we had a hit last time, go ahead and clear this out since likely it
00804                will be another hit */
00805             for (i=sample;i<limit;i++) 
00806                amp[i] = 0;
00807             *writeback = 1;
00808          }
00809          continue;
00810       }
00811 #ifdef OLD_DSP_ROUTINES    
00812       /* We're at the end of an MF detection block.  Go ahead and calculate
00813          all the energies. */
00814       for (i=0;i<6;i++) {
00815          tone_energy[i] = goertzel_result(&s->tone_out[i]);
00816       }
00817       /* Find highest */
00818       best1 = 0;
00819       max = tone_energy[0];
00820       for (i=1;i<6;i++) {
00821          if (tone_energy[i] > max) {
00822             max = tone_energy[i];
00823             best1 = i;
00824          }
00825       }
00826 
00827       /* Find 2nd highest */
00828       if (best1) {
00829          max = tone_energy[0];
00830          best2 = 0;
00831       } else {
00832          max = tone_energy[1];
00833          best2 = 1;
00834       }
00835 
00836       for (i=0;i<6;i++) {
00837          if (i == best1) continue;
00838          if (tone_energy[i] > max) {
00839             max = tone_energy[i];
00840             best2 = i;
00841          }
00842       }
00843       hit = 0;
00844       if (best1 != best2) 
00845          sofarsogood=1;
00846       else 
00847          sofarsogood=0;
00848       /* Check for relative energies */
00849       for (i=0;i<6;i++) {
00850          if (i == best1) 
00851             continue;
00852          if (i == best2) 
00853             continue;
00854          if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
00855             sofarsogood = 0;
00856             break;
00857          }
00858          if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
00859             sofarsogood = 0;
00860             break;
00861          }
00862       }
00863       
00864       if (sofarsogood) {
00865          /* Check for 2nd harmonic */
00866          if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 
00867             sofarsogood = 0;
00868          else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
00869             sofarsogood = 0;
00870       }
00871       if (sofarsogood) {
00872          hit = mf_hit[best1][best2];
00873          if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00874             /* Zero out frame data if this is part DTMF */
00875             for (i=sample;i<limit;i++) 
00876                amp[i] = 0;
00877             *writeback = 1;
00878          }
00879          /* Look for two consecutive clean hits */
00880          if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
00881             s->mhit = hit;
00882             s->detected_digits++;
00883             if (s->current_digits < MAX_DTMF_DIGITS - 2) {
00884                s->digits[s->current_digits++] = hit;
00885                s->digits[s->current_digits] = '\0';
00886             } else {
00887                s->lost_digits++;
00888             }
00889          }
00890       }
00891       
00892       s->hit1 = s->hit2;
00893       s->hit2 = s->hit3;
00894       s->hit3 = hit;
00895       /* Reinitialise the detector for the next block */
00896       for (i = 0;  i < 6;  i++) {
00897          goertzel_reset(&s->tone_out[i]);
00898          goertzel_reset(&s->tone_out2nd[i]);
00899       }
00900       s->energy = 0.0;
00901       s->current_sample = 0;
00902    }
00903 #else
00904       /* We're at the end of an MF detection block.  */
00905       /* Find the two highest energies. The spec says to look for
00906          two tones and two tones only. Taking this literally -ie
00907          only two tones pass the minimum threshold - doesn't work
00908          well. The sinc function mess, due to rectangular windowing
00909          ensure that! Find the two highest energies and ensure they
00910          are considerably stronger than any of the others. */
00911       energy[0] = goertzel_result(&s->tone_out[0]);
00912       energy[1] = goertzel_result(&s->tone_out[1]);
00913       if (energy[0] > energy[1]) {
00914          best = 0;
00915          second_best = 1;
00916       } else {
00917          best = 1;
00918          second_best = 0;
00919       }
00920       /*endif*/
00921       for (i=2;i<6;i++) {
00922          energy[i] = goertzel_result(&s->tone_out[i]);
00923          if (energy[i] >= energy[best]) {
00924             second_best = best;
00925             best = i;
00926          } else if (energy[i] >= energy[second_best]) {
00927             second_best = i;
00928          }
00929       }
00930       /* Basic signal level and twist tests */
00931       hit = 0;
00932       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00933                && energy[best] < energy[second_best]*BELL_MF_TWIST
00934                && energy[best]*BELL_MF_TWIST > energy[second_best]) {
00935          /* Relative peak test */
00936          hit = -1;
00937          for (i=0;i<6;i++) {
00938             if (i != best && i != second_best) {
00939                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00940                   /* The best two are not clearly the best */
00941                   hit = 0;
00942                   break;
00943                }
00944             }
00945          }
00946       }
00947       if (hit) {
00948          /* Get the values into ascending order */
00949          if (second_best < best) {
00950             i = best;
00951             best = second_best;
00952             second_best = i;
00953          }
00954          best = best*5 + second_best - 1;
00955          hit = bell_mf_positions[best];
00956          /* Look for two successive similar results */
00957          /* The logic in the next test is:
00958             For KP we need 4 successive identical clean detects, with
00959             two blocks of something different preceeding it. For anything
00960             else we need two successive identical clean detects, with
00961             two blocks of something different preceeding it. */
00962          if (hit == s->hits[4] && hit == s->hits[3] &&
00963             ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
00964              (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 
00965              hit != s->hits[0]))) {
00966             s->detected_digits++;
00967             if (s->current_digits < MAX_DTMF_DIGITS) {
00968                s->digits[s->current_digits++] = hit;
00969                s->digits[s->current_digits] = '\0';
00970             } else {
00971                s->lost_digits++;
00972             }
00973          }
00974       } else {
00975          hit = 0;
00976       }
00977       s->hits[0] = s->hits[1];
00978       s->hits[1] = s->hits[2];
00979       s->hits[2] = s->hits[3];
00980       s->hits[3] = s->hits[4];
00981       s->hits[4] = hit;
00982       /* Reinitialise the detector for the next block */
00983       for (i = 0;  i < 6;  i++)
00984          goertzel_reset(&s->tone_out[i]);
00985       s->current_sample = 0;
00986    }
00987 #endif   
00988    if ((!s->mhit) || (s->mhit != hit)) {
00989       s->mhit = 0;
00990       return(0);
00991    }
00992    return (hit);
00993 }

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

Definition at line 1025 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

01026 {
01027    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
01028    /* Make sure absolute levels are high enough */
01029    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
01030       return 0;
01031    /* Amplify ignored stuff */
01032    i2 *= TONE_THRESH;
01033    i1 *= TONE_THRESH;
01034    e *= TONE_THRESH;
01035    /* Check first tone */
01036    if ((p1 < i1) || (p1 < i2) || (p1 < e))
01037       return 0;
01038    /* And second */
01039    if ((p2 < i1) || (p2 < i2) || (p2 < e))
01040       return 0;
01041    /* Guess it's there... */
01042    return 1;
01043 }


Variable Documentation

struct progalias aliases[] [static]

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

Definition at line 293 of file dsp.c.

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 267 of file dsp.c.

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

Definition at line 281 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 263 of file dsp.c.

float fax_freq = 1100.0 [static]

Definition at line 278 of file dsp.c.

float mf_tones[] [static]

Initial value:

{
   700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
}

Definition at line 272 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().


Generated on Sun Dec 18 20:55:50 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6