Thu Oct 8 00:59:37 2009

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 "asterisk/options.h"

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 = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150,
  BUSY_MAX = 600
}
enum  freq_index {
  HZ_350 = 0, HZ_440, HZ_480, HZ_620,
  HZ_950, HZ_1400, HZ_1800, HZ_425 = 0,
  HZ_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_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
 Set expected lengths of the busy tones.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
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 187 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 185 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 186 of file dsp.c.

#define BUSYDETECT_MARTIN

Definition at line 191 of file dsp.c.

#define DEFAULT_THRESHOLD   512

Definition at line 114 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

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

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 171 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

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

Definition at line 169 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 172 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 159 of file dsp.c.

#define FAX_DETECT

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

Definition at line 128 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 158 of file dsp.c.

#define FIX_INF ( inf   ) 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128

Definition at line 143 of file dsp.c.

Referenced by dtmf_detect(), and mf_detect().

#define MF_GSIZE   120

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

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 130 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

enum busy_detect

Enumerator:
BUSY_PERCENT  The percentage difference between the two last tone periods
BUSY_PAT_PERCENT  The percentage difference between measured and actual pattern
BUSY_THRESHOLD  Max number of ms difference between max and min times in busy
BUSY_MIN  Busy must be at least 150 ms in half-cadence
BUSY_MAX  Busy can't be longer than 600 ms in half-cadence

Definition at line 116 of file dsp.c.

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

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

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

enum gsamp_size

Number of goertzels for progress detect

Enumerator:
GSAMP_SIZE_NA  North America - 350, 440, 480, 620, 950, 1400, 1800 Hz
GSAMP_SIZE_CR  Costa Rica, Brazil - Only care about 425 Hz
GSAMP_SIZE_UK  UK disconnect goertzel feed - should trigger 400hz

Definition at line 65 of file dsp.c.

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

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

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

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 71 of file dsp.c.

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


Function Documentation

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

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

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

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

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

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

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

Definition at line 1224 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

01225 {
01226    int accum;
01227    int x;
01228    int res = 0;
01229 
01230    if (!len)
01231       return 0;
01232    accum = 0;
01233    for (x=0;x<len; x++) 
01234       accum += abs(s[x]);
01235    accum /= len;
01236    if (accum < dsp->threshold) {
01237       /* Silent */
01238       dsp->totalsilence += len/8;
01239 #ifdef DEBUG_DSP_BUSYDETECT
01240       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01241 #endif
01242       if (dsp->totalnoise) {
01243          /* Move and save history */
01244          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicnoise[0]));
01245          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01246          /* check if previous tone differs BUSY_PERCENT from the one before it */
01247          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01248          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01249          if (tone1 < tone2) {
01250            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01251                dsp->busymaybe = 1;
01252            else
01253                dsp->busymaybe = 0;
01254          } else {
01255            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01256                dsp->busymaybe = 1;
01257             else
01258                dsp->busymaybe = 0;
01259          }
01260       }
01261       dsp->totalnoise = 0;
01262       res = 1;
01263    } else {
01264       /* Not silent */
01265       dsp->totalnoise += len/8;
01266 #ifdef DEBUG_DSP_BUSYDETECT
01267       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01268 #endif     
01269       if (dsp->totalsilence) {
01270          /* Move and save history */
01271          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicsilence[0]));
01272          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01273       }
01274       dsp->totalsilence = 0;
01275    }
01276    if (totalsilence)
01277       *totalsilence = dsp->totalsilence;
01278    return res;
01279 }

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

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

Referenced by ast_dsp_process().

01283 {
01284    int res = 0, x;
01285    int avgsilence = 0, hitsilence = 0;
01286    int avgtone = 0, hittone = 0;
01287 #ifdef DEBUG_DSP_BUSYDETECT
01288    char buf[16];
01289    char silence_list[64]="", tone_list[64]="";
01290 #endif
01291    
01292    if (!dsp->busymaybe)
01293       return res;
01294    dsp->busymaybe = 0;
01295 
01296    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01297       avgsilence += dsp->historicsilence[x];
01298       avgtone += dsp->historicnoise[x];
01299    }
01300    avgsilence /= dsp->busycount;
01301    avgtone /= dsp->busycount;
01302 #ifdef DEBUG_DSP_BUSYDETECT
01303    sprintf(silence_list,"Silences: ");
01304    sprintf(tone_list,"Tones:    ");
01305 #endif
01306    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01307 #ifdef DEBUG_DSP_BUSYDETECT
01308       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01309       strcat(silence_list, buf);
01310       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01311       strcat(tone_list, buf); 
01312 #endif
01313       if (!dsp->busytoneonly) {
01314          if (avgsilence > dsp->historicsilence[x]) {
01315             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01316                hitsilence++;
01317          } else {
01318             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01319                hitsilence++;
01320          }
01321       }
01322       if (avgtone > dsp->historicnoise[x]) {
01323          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01324             hittone++;
01325       } else {
01326          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01327             hittone++;
01328       }
01329    }
01330 #ifdef DEBUG_DSP_BUSYDETECT
01331    fprintf(stderr, "BUSY DETECTOR\n");   
01332    fprintf(stderr, "%s\n", tone_list);
01333    fprintf(stderr, "%s\n", silence_list)
01334 #endif
01335    if ((dsp->busytoneonly || 
01336        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01337       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01338       if (dsp->busycompare) {
01339            if (dsp->busytoneonly) {
01340              res = 1;
01341             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01342          } else {
01343               if (avgtone > avgsilence) {
01344                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01345                     res = 1;
01346             } else {
01347                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01348                    res = 1;
01349             }
01350          }
01351       } else {
01352          res = 1;
01353       }
01354    }
01355    /* If we know the expected busy tone length, check we are in the range */
01356    if (res && (dsp->busy_tonelength > 0)) {
01357       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01358          if(option_debug) {
01359             ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength);
01360          }
01361          res = 0;
01362       }
01363    }
01364    /* If we know the expected busy tone silent-period length, check we are in the range */
01365    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01366       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01367          if(option_debug) {
01368             ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength);
01369          }
01370          res = 0;
01371       }
01372    }
01373    if (res && option_debug)
01374       ast_log(LOG_NOTICE, "Detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01375    return res;
01376 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

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

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

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

01808 {
01809    int new;
01810    int old;
01811    
01812    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01813    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01814    if (old != new) {
01815       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01816       if (new & DSP_DIGITMODE_MF)
01817          ast_mf_detect_init(&dsp->td.mf);
01818       else
01819          ast_dtmf_detect_init(&dsp->td.dtmf);
01820    }
01821    dsp->digitmode = digitmode;
01822    return 0;
01823 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1744 of file dsp.c.

References dtmf_detect_state_t::col_out, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_sample, dtmf_detect_state_t::current_sample, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_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, mf_detect_state_t::mhit, dtmf_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().

01745 {
01746    int i;
01747    
01748    dsp->thinkdigit = 0;
01749    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01750       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01751       dsp->td.mf.current_digits = 0;
01752       /* Reinitialise the detector for the next block */
01753       for (i = 0;  i < 6;  i++) {
01754          goertzel_reset(&dsp->td.mf.tone_out[i]);
01755 #ifdef OLD_DSP_ROUTINES
01756          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01757 #endif         
01758       }
01759 #ifdef OLD_DSP_ROUTINES
01760       dsp->td.mf.energy = 0.0;
01761       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01762 #else
01763       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;
01764 #endif      
01765       dsp->td.mf.current_sample = 0;
01766    } else {
01767       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01768       dsp->td.dtmf.current_digits = 0;
01769       /* Reinitialise the detector for the next block */
01770       for (i = 0;  i < 4;  i++) {
01771          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01772          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01773 #ifdef OLD_DSP_ROUTINES
01774          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01775          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01776 #endif         
01777       }
01778 #ifdef FAX_DETECT
01779       goertzel_reset (&dsp->td.dtmf.fax_tone);
01780 #endif
01781 #ifdef OLD_DSP_ROUTINES
01782 #ifdef FAX_DETECT
01783       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01784 #endif
01785       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01786 #else
01787       dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
01788 #endif      
01789       dsp->td.dtmf.energy = 0.0;
01790       dsp->td.dtmf.current_sample = 0;
01791    }
01792 }

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

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

Referenced by __frame_free().

01850 {
01851    struct ast_dsp *dsp;
01852 
01853    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01854 
01855    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01856 
01857    if (dsp->freqcount != -1)
01858       return;
01859    
01860    ast_dsp_free(dsp);
01861 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1691 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(), dahdi_hangup(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), and ss_thread().

01692 {
01693    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01694       /* If this flag is still set, that means that the dsp's destruction 
01695        * been torn down, while we still have a frame out there being used.
01696        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01697        * will get destroyed, too. */
01698 
01699       /* Set the magic hint that this has been requested to be destroyed. */
01700       dsp->freqcount = -1;
01701 
01702       return;
01703    }
01704    free(dsp);
01705 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1844 of file dsp.c.

References ast_dsp::tcount.

01845 {
01846    return dsp->tcount;
01847 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1839 of file dsp.c.

References ast_dsp::tstate.

01840 {
01841    return dsp->tstate;
01842 }

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

Get pending DTMF/MF digits.

Definition at line 1049 of file dsp.c.

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

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

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1656 of file dsp.c.

References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and ast_dsp::threshold.

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

01657 {
01658    struct ast_dsp *dsp;
01659    
01660    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01661       dsp->threshold = DEFAULT_THRESHOLD;
01662       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01663       dsp->busycount = DSP_HISTORY;
01664       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01665 #ifdef BUSYDETECT_TONEONLY
01666       dsp->busytoneonly = 1;
01667 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01668 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01669 #endif
01670 #else
01671    dsp->busytoneonly = 0;
01672 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01673    dsp->busycompare = 1;
01674 #else
01675    dsp->busycompare = 0;
01676 #endif
01677 #endif
01678       /* Initialize DTMF detector */
01679       ast_dtmf_detect_init(&dsp->td.dtmf);
01680       /* Initialize initial DSP progress detect parameters */
01681       ast_dsp_prog_reset(dsp);
01682    }
01683    return dsp;
01684 }

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

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

Definition at line 1442 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, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_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 dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01640 {
01641    int max = 0;
01642    int x;
01643    
01644    dsp->gsamp_size = modes[dsp->progmode].size;
01645    dsp->gsamps = 0;
01646    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01647       if (modes[dsp->progmode].freqs[x]) {
01648          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01649          max = x + 1;
01650       }
01651    }
01652    dsp->freqcount = max;
01653    dsp->ringtimeout= 0;
01654 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01795 {
01796    int x;
01797    
01798    dsp->totalsilence = 0;
01799    dsp->gsamps = 0;
01800    for (x=0;x<4;x++)
01801       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01802    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01803    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01804    dsp->ringtimeout= 0;
01805 }

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

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

Definition at line 1724 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

01725 {
01726   if (compare > 0)
01727       dsp->busycompare = 1;
01728   else
01729       dsp->busycompare = 0;
01730 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1715 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01716 {
01717    if (cadences < 4)
01718       cadences = 4;
01719    if (cadences > DSP_HISTORY)
01720       cadences = DSP_HISTORY;
01721    dsp->busycount = cadences;
01722 }

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

Set expected lengths of the busy tones.

Definition at line 1732 of file dsp.c.

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

Referenced by dahdi_new().

01733 {
01734    dsp->busy_tonelength = tonelength;
01735    if (quietlength > 0)
01736       dsp->busy_quietlength = quietlength;
01737    else 
01738      dsp->busytoneonly = 1;
01739    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01740    if( fuzzy > 0 && fuzzy < 50 ) 
01741       dsp->busy_pattern_fuzzy = fuzzy;
01742 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1825 of file dsp.c.

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

Referenced by dahdi_new().

01826 {
01827    int x;
01828    
01829    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01830       if (!strcasecmp(aliases[x].name, zone)) {
01831          dsp->progmode = aliases[x].mode;
01832          ast_dsp_prog_reset(dsp);
01833          return 0;
01834       }
01835    }
01836    return -1;
01837 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1686 of file dsp.c.

References ast_dsp::features.

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

01687 {
01688    dsp->features = features;
01689 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1707 of file dsp.c.

References ast_dsp::threshold.

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

01708 {
01709    if (threshold < 256)
01710      dsp->threshold = 256;
01711    else
01712      dsp->threshold = threshold;
01713 }

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

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

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

01425 {
01426    short *s;
01427    int len;
01428    
01429    if (f->frametype != AST_FRAME_VOICE) {
01430       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01431       return 0;
01432    }
01433    if (f->subclass != AST_FORMAT_SLINEAR) {
01434       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01435       return 0;
01436    }
01437    s = f->data;
01438    len = f->datalen/2;
01439    return __ast_dsp_silence(dsp, s, len, totalsilence);
01440 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 367 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

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

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 406 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode().

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

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

Definition at line 431 of file dsp.c.

References DSP_DIGITMODE_NOQUELCH, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, goertzel_result(), MAX_DTMF_DIGITS, and s.

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 321 of file dsp.c.

References s.

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

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

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

Definition at line 330 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

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

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

Definition at line 316 of file dsp.c.

References s.

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

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

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

Definition at line 297 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress(), and goertzel_update().

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

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

Definition at line 307 of file dsp.c.

References goertzel_sample(), and s.

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

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

Definition at line 716 of file dsp.c.

References DSP_DIGITMODE_NOQUELCH, goertzel_result(), MAX_DTMF_DIGITS, MF_GSIZE, and s.

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 1029 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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


Variable Documentation

struct progalias aliases[] [static]

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 294 of file dsp.c.

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 268 of file dsp.c.

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

Definition at line 282 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 264 of file dsp.c.

float fax_freq = 1100.0 [static]

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

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().


Generated on Thu Oct 8 00:59:37 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7