Fri Aug 24 02:25:12 2007

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_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
 Get pending DTMF/MF digits.
ast_dspast_dsp_new (void)
ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength)
 Set expected lengths of the busy tone.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set.
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set threshold value for silence.
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect)
static void goertzel_init (goertzel_state_t *s, float freq, int samples)
static void goertzel_reset (goertzel_state_t *s)
static float goertzel_result (goertzel_state_t *s)
static void goertzel_sample (goertzel_state_t *s, short sample)
static void goertzel_update (goertzel_state_t *s, short *samps, int count)
static int mf_detect (mf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback)
static int pair_there (float p1, float p2, float i1, float i2, float e)

Variables

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


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 186 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 184 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 185 of file dsp.c.

#define BUSYDETECT_MARTIN

Definition at line 190 of file dsp.c.

#define DEFAULT_THRESHOLD   512

Definition at line 113 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 124 of file dsp.c.

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

#define DTMF_NORMAL_TWIST   6.3

Definition at line 167 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 169 of file dsp.c.

Referenced by dtmf_detect().

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

Definition at line 168 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 156 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 171 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 158 of file dsp.c.

#define FAX_DETECT

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

Definition at line 127 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

#define FIX_INF ( inf   ) 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128

Definition at line 142 of file dsp.c.

Referenced by dtmf_detect(), and mf_detect().

#define MF_GSIZE   120

Definition at line 695 of file dsp.c.

Referenced by mf_detect().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 130 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 129 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

enum busy_detect

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

Definition at line 115 of file dsp.c.

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

enum freq_index

Enumerator:
HZ_350  For US modes {
HZ_440 
HZ_480 
HZ_620 
HZ_950 
HZ_1400 
HZ_1800  }
HZ_425  For CR/BR modes
HZ_400  For UK mode

Definition at line 76 of file dsp.c.

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

enum gsamp_size

Number of goertzels for progress detect

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

Definition at line 64 of file dsp.c.

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

enum gsamp_thresh

All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)

Enumerator:
THRESH_RING  Need at least 150ms ring to accept
THRESH_TALK  Talk detection does not work continuously
THRESH_BUSY  Need at least 80ms to accept
THRESH_CONGESTION  Need at least 80ms to accept
THRESH_HANGUP  Need at least 1300ms to accept hangup
THRESH_RING2ANSWER  Timeout from start of ring to answer (about 6600 ms)

Definition at line 133 of file dsp.c.

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

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 70 of file dsp.c.

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


Function Documentation

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

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

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

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

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

00982 {
00983    int res;
00984    
00985    if (dsp->digitmode & DSP_DIGITMODE_MF)
00986       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00987    else
00988       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
00989    return res;
00990 }

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

Definition at line 1206 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

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

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

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

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01194 {
01195    if (inf->frametype != AST_FRAME_VOICE) {
01196       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01197       return 0;
01198    }
01199    if (inf->subclass != AST_FORMAT_SLINEAR) {
01200       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01201       return 0;
01202    }
01203    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01204 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

00993 {
00994    short *s;
00995    int len;
00996    int ign=0;
00997 
00998    if (inf->frametype != AST_FRAME_VOICE) {
00999       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01000       return 0;
01001    }
01002    if (inf->subclass != AST_FORMAT_SLINEAR) {
01003       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01004       return 0;
01005    }
01006    s = inf->data;
01007    len = inf->datalen / 2;
01008    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01009 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1732 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(), nv_background_detect_exec(), nv_detectfax_exec(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

01733 {
01734    int new;
01735    int old;
01736    
01737    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01738    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01739    if (old != new) {
01740       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01741       if (new & DSP_DIGITMODE_MF)
01742          ast_mf_detect_init(&dsp->td.mf);
01743       else
01744          ast_dtmf_detect_init(&dsp->td.dtmf);
01745    }
01746    dsp->digitmode = digitmode;
01747    return 0;
01748 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1669 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::hits, 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().

01670 {
01671    int i;
01672    
01673    dsp->thinkdigit = 0;
01674    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01675       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01676       dsp->td.mf.current_digits = 0;
01677       /* Reinitialise the detector for the next block */
01678       for (i = 0;  i < 6;  i++) {
01679          goertzel_reset(&dsp->td.mf.tone_out[i]);
01680 #ifdef OLD_DSP_ROUTINES
01681          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01682 #endif         
01683       }
01684 #ifdef OLD_DSP_ROUTINES
01685       dsp->td.mf.energy = 0.0;
01686       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01687 #else
01688       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;
01689 #endif      
01690       dsp->td.mf.current_sample = 0;
01691    } else {
01692       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01693       dsp->td.dtmf.current_digits = 0;
01694       /* Reinitialise the detector for the next block */
01695       for (i = 0;  i < 4;  i++) {
01696          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01697          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01698 #ifdef OLD_DSP_ROUTINES
01699          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01700          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01701 #endif         
01702       }
01703 #ifdef FAX_DETECT
01704       goertzel_reset (&dsp->td.dtmf.fax_tone);
01705 #endif
01706 #ifdef OLD_DSP_ROUTINES
01707 #ifdef FAX_DETECT
01708       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01709 #endif
01710       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01711 #else
01712       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01713 #endif      
01714       dsp->td.dtmf.energy = 0.0;
01715       dsp->td.dtmf.current_sample = 0;
01716    }
01717 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1643 of file dsp.c.

References free.

Referenced by __ast_play_and_record(), __oh323_destroy(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), nv_background_detect_exec(), nv_detectfax_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), and zt_hangup().

01644 {
01645    free(dsp);
01646 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1769 of file dsp.c.

References ast_dsp::tcount.

01770 {
01771    return dsp->tcount;
01772 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1764 of file dsp.c.

References ast_dsp::tstate.

01765 {
01766    return dsp->tstate;
01767 }

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

Get pending DTMF/MF digits.

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

01032 {
01033    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01034       if (max > dsp->td.mf.current_digits)
01035          max = dsp->td.mf.current_digits;
01036       if (max > 0) {
01037          memcpy(buf, dsp->td.mf.digits, max);
01038          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01039          dsp->td.mf.current_digits -= max;
01040       }
01041       buf[max] = '\0';
01042       return  max;
01043    } else {
01044       if (max > dsp->td.dtmf.current_digits)
01045          max = dsp->td.dtmf.current_digits;
01046       if (max > 0) {
01047          memcpy (buf, dsp->td.dtmf.digits, max);
01048          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01049          dsp->td.dtmf.current_digits -= max;
01050       }
01051       buf[max] = '\0';
01052       return  max;
01053    }
01054 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1622 of file dsp.c.

References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), 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(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), nv_background_detect_exec(), nv_detectfax_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

01623 {
01624    struct ast_dsp *dsp;
01625    
01626    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01627       dsp->threshold = DEFAULT_THRESHOLD;
01628       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01629       dsp->busycount = DSP_HISTORY;
01630       /* Initialize DTMF detector */
01631       ast_dtmf_detect_init(&dsp->td.dtmf);
01632       /* Initialize initial DSP progress detect parameters */
01633       ast_dsp_prog_reset(dsp);
01634    }
01635    return dsp;
01636 }

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 1416 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_frfree(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), 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_DEBUG, LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01606 {
01607    int max = 0;
01608    int x;
01609    
01610    dsp->gsamp_size = modes[dsp->progmode].size;
01611    dsp->gsamps = 0;
01612    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01613       if (modes[dsp->progmode].freqs[x]) {
01614          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01615          max = x + 1;
01616       }
01617    }
01618    dsp->freqcount = max;
01619    dsp->ringtimeout= 0;
01620 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01720 {
01721    int x;
01722    
01723    dsp->totalsilence = 0;
01724    dsp->gsamps = 0;
01725    for (x=0;x<4;x++)
01726       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01727    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01728    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01729    dsp->ringtimeout= 0;
01730 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1653 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

01654 {
01655    if (cadences < 4)
01656       cadences = 4;
01657    if (cadences > DSP_HISTORY)
01658       cadences = DSP_HISTORY;
01659    dsp->busycount = cadences;
01660 }

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

Set expected lengths of the busy tone.

Definition at line 1662 of file dsp.c.

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

Referenced by zt_new().

01663 {
01664    dsp->busy_tonelength = tonelength;
01665    dsp->busy_quietlength = quietlength;
01666    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01667 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1750 of file dsp.c.

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

Referenced by zt_new().

01751 {
01752    int x;
01753    
01754    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01755       if (!strcasecmp(aliases[x].name, zone)) {
01756          dsp->progmode = aliases[x].mode;
01757          ast_dsp_prog_reset(dsp);
01758          return 0;
01759       }
01760    }
01761    return -1;
01762 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1638 of file dsp.c.

References ast_dsp::features.

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

01639 {
01640    dsp->features = features;
01641 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1648 of file dsp.c.

References ast_dsp::threshold.

Referenced by __ast_play_and_record(), do_waiting(), handle_recordfile(), isAnsweringMachine(), nv_background_detect_exec(), and nv_detectfax_exec().

01649 {
01650    dsp->threshold = threshold;
01651 }

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 1398 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(), isAnsweringMachine(), nv_background_detect_exec(), and nv_detectfax_exec().

01399 {
01400    short *s;
01401    int len;
01402    
01403    if (f->frametype != AST_FRAME_VOICE) {
01404       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01405       return 0;
01406    }
01407    if (f->subclass != AST_FORMAT_SLINEAR) {
01408       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01409       return 0;
01410    }
01411    s = f->data;
01412    len = f->datalen/2;
01413    return __ast_dsp_silence(dsp, s, len, totalsilence);
01414 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 363 of file dsp.c.

References goertzel_init(), and s.

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->hits[0] = s->hits[1] = s->hits[2] = 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 goertzel_init(), and s.

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 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, s, and warning().

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             /* Look for two successive similar results */
00599             /* The logic in the next test is:
00600                We need two successive identical clean detects, with
00601                something different preceeding it. This can work with
00602                back to back differing digits. More importantly, it
00603                can work with nasty phones that give a very wobbly start
00604                to a digit */
00605 #ifdef OLD_DSP_ROUTINES
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 #else          
00618             if (hit == s->hits[2]  &&  hit != s->hits[1]  &&  hit != s->hits[0]) {
00619                s->mhit = hit;
00620                s->digit_hits[(best_row << 2) + best_col]++;
00621                s->detected_digits++;
00622                if (s->current_digits < MAX_DTMF_DIGITS) {
00623                   s->digits[s->current_digits++] = hit;
00624                   s->digits[s->current_digits] = '\0';
00625                } else {
00626                   s->lost_digits++;
00627                }
00628             }
00629 #endif
00630          }
00631       } 
00632 #ifdef FAX_DETECT
00633       if (!hit && (fax_energy >= FAX_THRESHOLD) && 
00634          (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
00635          (faxdetect)) {
00636 #if 0
00637          printf("Fax energy/Second Harmonic: %f\n", fax_energy);
00638 #endif               
00639          /* XXX Probably need better checking than just this the energy XXX */
00640          hit = 'f';
00641          s->fax_hits++;
00642       } else {
00643          if (s->fax_hits > 5) {
00644             hit = 'f';
00645             s->mhit = 'f';
00646             s->detected_digits++;
00647             if (s->current_digits < MAX_DTMF_DIGITS) {
00648                s->digits[s->current_digits++] = hit;
00649                s->digits[s->current_digits] = '\0';
00650             } else {
00651                s->lost_digits++;
00652             }
00653          }
00654          s->fax_hits = 0;
00655       }
00656 #endif /* FAX_DETECT */
00657 #ifdef OLD_DSP_ROUTINES
00658       s->hit1 = s->hit2;
00659       s->hit2 = s->hit3;
00660       s->hit3 = hit;
00661 #else
00662       s->hits[0] = s->hits[1];
00663       s->hits[1] = s->hits[2];
00664       s->hits[2] = hit;
00665 #endif      
00666       /* Reinitialise the detector for the next block */
00667       for (i = 0;  i < 4;  i++) {
00668          goertzel_reset(&s->row_out[i]);
00669          goertzel_reset(&s->col_out[i]);
00670 #ifdef OLD_DSP_ROUTINES
00671          goertzel_reset(&s->row_out2nd[i]);
00672          goertzel_reset(&s->col_out2nd[i]);
00673 #endif         
00674       }
00675 #ifdef FAX_DETECT
00676       goertzel_reset (&s->fax_tone);
00677 #ifdef OLD_DSP_ROUTINES
00678       goertzel_reset (&s->fax_tone2nd);
00679 #endif         
00680 #endif
00681       s->energy = 0.0;
00682       s->current_sample = 0;
00683    }
00684    if ((!s->mhit) || (s->mhit != hit)) {
00685       s->mhit = 0;
00686       return(0);
00687    }
00688    return (hit);
00689 }

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

Definition at line 320 of file dsp.c.

References s.

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

Referenced by ast_dsp_digitreset().

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

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

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(), and s.

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

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

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 1011 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

01012 {
01013    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
01014    /* Make sure absolute levels are high enough */
01015    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
01016       return 0;
01017    /* Amplify ignored stuff */
01018    i2 *= TONE_THRESH;
01019    i1 *= TONE_THRESH;
01020    e *= TONE_THRESH;
01021    /* Check first tone */
01022    if ((p1 < i1) || (p1 < i2) || (p1 < e))
01023       return 0;
01024    /* And second */
01025    if ((p2 < i1) || (p2 < i2) || (p2 < e))
01026       return 0;
01027    /* Guess it's there... */
01028    return 1;
01029 }


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 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 Fri Aug 24 02:25:13 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1