Sat Aug 6 00:39:55 2011

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

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

Go to the source code of this file.

Data Structures

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

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#define BUSYDETECT_MARTIN
#define DEFAULT_THRESHOLD   512
#define DSP_HISTORY   15
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_DETECT
#define FAX_THRESHOLD   8.0e7
#define FIX_INF(inf)
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0

Enumerations

enum  busy_detect {
  BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150,
  BUSY_MAX = 600
}
enum  freq_index {
  HZ_350 = 0, HZ_440, HZ_480, HZ_620,
  HZ_950, HZ_1400, HZ_1800, HZ_425 = 0,
  HZ_400 = 0
}
enum  gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 }
enum  gsamp_thresh {
  THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4,
  THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300
}
enum  prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK }

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static int __ast_dsp_digitdetect (struct ast_dsp *dsp, short *s, int len, int *writeback)
static int __ast_dsp_silence (struct ast_dsp *dsp, short *s, int len, int *totalsilence)
int ast_dsp_busydetect (struct ast_dsp *dsp)
 Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
 Scans for progress indication in audio.
int ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *inf)
 Return non-zero if DTMF hit was found.
int ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector.
void ast_dsp_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
 Get pending DTMF/MF digits.
ast_dspast_dsp_new (void)
ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
void ast_dsp_set_busy_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
 Set expected lengths of the busy tones.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set.
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set threshold value for silence.
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect)
static void goertzel_init (goertzel_state_t *s, float freq, int samples)
static void goertzel_reset (goertzel_state_t *s)
static float goertzel_result (goertzel_state_t *s)
static void goertzel_sample (goertzel_state_t *s, short sample)
static void goertzel_update (goertzel_state_t *s, short *samps, int count)
static int mf_detect (mf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback)
static int pair_there (float p1, float p2, float i1, float i2, float e)

Variables

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


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 187 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 185 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 186 of file dsp.c.

#define BUSYDETECT_MARTIN

Definition at line 191 of file dsp.c.

#define DEFAULT_THRESHOLD   512

Definition at line 114 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 125 of file dsp.c.

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

#define DTMF_NORMAL_TWIST   6.3

Definition at line 168 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 171 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

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

Definition at line 169 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 172 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 159 of file dsp.c.

#define FAX_DETECT

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

Definition at line 128 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 158 of file dsp.c.

#define FIX_INF ( inf   ) 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128

Definition at line 143 of file dsp.c.

Referenced by dtmf_detect(), and mf_detect().

#define MF_GSIZE   120

Definition at line 714 of file dsp.c.

Referenced by mf_detect().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 131 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 130 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

enum busy_detect

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

Definition at line 116 of file dsp.c.

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

enum freq_index

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

Definition at line 77 of file dsp.c.

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

enum gsamp_size

Number of goertzels for progress detect

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

Definition at line 65 of file dsp.c.

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

enum gsamp_thresh

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

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

Definition at line 134 of file dsp.c.

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

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 71 of file dsp.c.

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


Function Documentation

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

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

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

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

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

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

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

Definition at line 1236 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

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

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

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

Referenced by ast_dsp_process().

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

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01224 {
01225    if (inf->frametype != AST_FRAME_VOICE) {
01226       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01227       return 0;
01228    }
01229    if (inf->subclass != AST_FORMAT_SLINEAR) {
01230       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01231       return 0;
01232    }
01233    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01234 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

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

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1805 of file dsp.c.

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

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1742 of file dsp.c.

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

Referenced by ss_thread().

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

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1700 of file dsp.c.

References free.

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

01701 {
01702    free(dsp);
01703 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1842 of file dsp.c.

References ast_dsp::tcount.

01843 {
01844    return dsp->tcount;
01845 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1837 of file dsp.c.

References ast_dsp::tstate.

01838 {
01839    return dsp->tstate;
01840 }

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

Get pending DTMF/MF digits.

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

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

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1664 of file dsp.c.

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

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

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

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 1454 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_frisolate(), 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, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len(), LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01648 {
01649    int max = 0;
01650    int x;
01651    
01652    dsp->gsamp_size = modes[dsp->progmode].size;
01653    dsp->gsamps = 0;
01654    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01655       if (modes[dsp->progmode].freqs[x]) {
01656          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01657          max = x + 1;
01658       }
01659    }
01660    dsp->freqcount = max;
01661    dsp->ringtimeout= 0;
01662 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

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

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

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

Definition at line 1722 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

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

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1713 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

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

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

Set expected lengths of the busy tones.

Definition at line 1730 of file dsp.c.

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

Referenced by dahdi_new().

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

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1823 of file dsp.c.

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

Referenced by dahdi_new().

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

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1695 of file dsp.c.

References ast_dsp::features.

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

01696 {
01697    dsp->features = features;
01698 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1705 of file dsp.c.

References ast_dsp::threshold.

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

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

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

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

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

01437 {
01438    short *s;
01439    int len;
01440    
01441    if (f->frametype != AST_FRAME_VOICE) {
01442       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01443       return 0;
01444    }
01445    if (f->subclass != AST_FORMAT_SLINEAR) {
01446       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01447       return 0;
01448    }
01449    s = f->data;
01450    len = f->datalen/2;
01451    return __ast_dsp_silence(dsp, s, len, totalsilence);
01452 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 368 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

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

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 407 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode().

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

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

Definition at line 432 of file dsp.c.

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

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 321 of file dsp.c.

References s.

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

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

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

Definition at line 330 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

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

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

Definition at line 316 of file dsp.c.

References s.

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

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

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

Definition at line 297 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress(), and goertzel_update().

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

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

Definition at line 307 of file dsp.c.

References goertzel_sample(), and s.

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

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

Definition at line 717 of file dsp.c.

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

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 1030 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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


Variable Documentation

struct progalias aliases[] [static]

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 294 of file dsp.c.

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 268 of file dsp.c.

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

Definition at line 282 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 264 of file dsp.c.

float fax_freq = 1100.0 [static]

Definition at line 279 of file dsp.c.

float mf_tones[] [static]

Initial value:

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

Definition at line 273 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().


Generated on Sat Aug 6 00:39:55 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7