Mon May 14 04:48:25 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_2ND_HARMONIC_COL   63.1
#define DTMF_2ND_HARMONIC_ROW   ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)
#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 180 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 178 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 179 of file dsp.c.

#define BUSYDETECT_MARTIN

Definition at line 184 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_2ND_HARMONIC_COL   63.1

Definition at line 168 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_2ND_HARMONIC_ROW   ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)

Definition at line 167 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_NORMAL_TWIST   6.3

Definition at line 159 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 166 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 165 of file dsp.c.

Referenced by dtmf_detect().

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

Definition at line 163 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 169 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 689 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 1050 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().

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

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

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

00976 {
00977    int res;
00978    
00979    if (dsp->digitmode & DSP_DIGITMODE_MF)
00980       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00981    else
00982       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
00983    return res;
00984 }

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

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

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

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

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

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

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

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

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

void ast_dsp_free ( struct ast_dsp dsp  ) 

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

01638 {
01639    free(dsp);
01640 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1763 of file dsp.c.

References ast_dsp::tcount.

01764 {
01765    return dsp->tcount;
01766 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1758 of file dsp.c.

References ast_dsp::tstate.

01759 {
01760    return dsp->tstate;
01761 }

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

Get pending DTMF/MF digits.

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

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

struct ast_dsp* ast_dsp_new ( void   ) 

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

01617 {
01618    struct ast_dsp *dsp;
01619    
01620    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01621       dsp->threshold = DEFAULT_THRESHOLD;
01622       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01623       dsp->busycount = DSP_HISTORY;
01624       /* Initialize DTMF detector */
01625       ast_dtmf_detect_init(&dsp->td.dtmf);
01626       /* Initialize initial DSP progress detect parameters */
01627       ast_dsp_prog_reset(dsp);
01628    }
01629    return dsp;
01630 }

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01600 {
01601    int max = 0;
01602    int x;
01603    
01604    dsp->gsamp_size = modes[dsp->progmode].size;
01605    dsp->gsamps = 0;
01606    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01607       if (modes[dsp->progmode].freqs[x]) {
01608          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01609          max = x + 1;
01610       }
01611    }
01612    dsp->freqcount = max;
01613    dsp->ringtimeout= 0;
01614 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01714 {
01715    int x;
01716    
01717    dsp->totalsilence = 0;
01718    dsp->gsamps = 0;
01719    for (x=0;x<4;x++)
01720       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01721    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01722    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01723    dsp->ringtimeout= 0;
01724 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1647 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

01648 {
01649    if (cadences < 4)
01650       cadences = 4;
01651    if (cadences > DSP_HISTORY)
01652       cadences = DSP_HISTORY;
01653    dsp->busycount = cadences;
01654 }

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

Set expected lengths of the busy tone.

Definition at line 1656 of file dsp.c.

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

Referenced by zt_new().

01657 {
01658    dsp->busy_tonelength = tonelength;
01659    dsp->busy_quietlength = quietlength;
01660    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01661 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1744 of file dsp.c.

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

Referenced by zt_new().

01745 {
01746    int x;
01747    
01748    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01749       if (!strcasecmp(aliases[x].name, zone)) {
01750          dsp->progmode = aliases[x].mode;
01751          ast_dsp_prog_reset(dsp);
01752          return 0;
01753       }
01754    }
01755    return -1;
01756 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

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

01633 {
01634    dsp->features = features;
01635 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

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

01643 {
01644    dsp->threshold = threshold;
01645 }

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

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

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 357 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

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

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 396 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode().

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

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

Definition at line 421 of file dsp.c.

References DSP_DIGITMODE_NOQUELCH, DTMF_2ND_HARMONIC_COL, DTMF_2ND_HARMONIC_ROW, 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().

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

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

Definition at line 314 of file dsp.c.

References s.

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

00315 {
00316    s->v2 = s->v3 = 0.0;
00317    s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
00318 #ifndef OLD_DSP_ROUTINES
00319    s->samples = samples;
00320 #endif
00321 }

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

Definition at line 323 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

00324 {
00325    s->v2 = s->v3 = 0.0;
00326 }

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

Definition at line 309 of file dsp.c.

References s.

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

00310 {
00311    return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
00312 }

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

Definition at line 290 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress(), and goertzel_update().

00291 {
00292    float v1;
00293    float fsamp  = sample;
00294    
00295    v1 = s->v2;
00296    s->v2 = s->v3;
00297    s->v3 = s->fac * s->v2 - v1 + fsamp;
00298 }

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

Definition at line 300 of file dsp.c.

References goertzel_sample(), and s.

00301 {
00302    int i;
00303    
00304    for (i=0;i<count;i++) 
00305       goertzel_sample(s, samps[i]);
00306 }

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

Definition at line 692 of file dsp.c.

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

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 1005 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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


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

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 261 of file dsp.c.

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

Definition at line 275 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 257 of file dsp.c.

float fax_freq = 1100.0 [static]

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

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().


Generated on Mon May 14 04:48:26 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1