Sat Nov 25 00:46:04 2006

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk.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"

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 BUSY_MAX   3100
#define BUSY_MIN   75
#define BUSY_PAT_PERCENT   7
#define BUSY_PERCENT   10
#define BUSY_THRESHOLD   100
#define BUSYDETECT_MARTIN
#define COUNT_THRESH   3
#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 GSAMP_SIZE_CR   188
#define GSAMP_SIZE_NA   183
#define GSAMP_SIZE_UK   160
#define HZ_1400   5
#define HZ_1800   6
#define HZ_350   0
#define HZ_400   0
#define HZ_425   0
#define HZ_440   1
#define HZ_480   2
#define HZ_620   3
#define HZ_950   4
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define PROG_MODE_CR   1
#define PROG_MODE_NA   0
#define PROG_MODE_UK   2
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0
#define UK_HANGUP_THRESH   60

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.

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6
 

Definition at line 162 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9
 

Definition at line 160 of file dsp.c.

#define BELL_MF_TWIST   4.0
 

Definition at line 161 of file dsp.c.

#define BUSY_MAX   3100
 

Definition at line 110 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_MIN   75
 

Definition at line 109 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_PAT_PERCENT   7
 

Definition at line 107 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_PERCENT   10
 

Definition at line 106 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_THRESHOLD   100
 

Definition at line 108 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSYDETECT_MARTIN
 

Definition at line 166 of file dsp.c.

#define COUNT_THRESH   3
 

Definition at line 120 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define DEFAULT_THRESHOLD   512
 

Definition at line 104 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15
 

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

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

Definition at line 149 of file dsp.c.

#define DTMF_NORMAL_TWIST   6.3
 

Definition at line 141 of file dsp.c.

#define DTMF_RELATIVE_PEAK_COL   6.3
 

Definition at line 148 of file dsp.c.

#define DTMF_RELATIVE_PEAK_ROW   6.3
 

Definition at line 147 of file dsp.c.

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

Definition at line 145 of file dsp.c.

#define DTMF_THRESHOLD   8.0e7
 

Definition at line 138 of file dsp.c.

#define DTMF_TO_TOTAL_ENERGY   42.0
 

Definition at line 151 of file dsp.c.

#define FAX_2ND_HARMONIC   2.0
 

Definition at line 140 of file dsp.c.

#define FAX_DETECT
 

Definition at line 116 of file dsp.c.

#define FAX_THRESHOLD   8.0e7
 

Definition at line 139 of file dsp.c.

#define FIX_INF inf   ) 
 

Referenced by ast_dsp_process().

#define GSAMP_SIZE_CR   188
 

Definition at line 62 of file dsp.c.

#define GSAMP_SIZE_NA   183
 

Definition at line 61 of file dsp.c.

#define GSAMP_SIZE_UK   160
 

Definition at line 63 of file dsp.c.

#define HZ_1400   5
 

Definition at line 75 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_1800   6
 

Definition at line 76 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_350   0
 

Definition at line 70 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_400   0
 

Definition at line 82 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_425   0
 

Definition at line 79 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_440   1
 

Definition at line 71 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_480   2
 

Definition at line 72 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_620   3
 

Definition at line 73 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_950   4
 

Definition at line 74 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define MAX_DTMF_DIGITS   128
 

Definition at line 124 of file dsp.c.

#define MF_GSIZE   120
 

Definition at line 670 of file dsp.c.

Referenced by mf_detect().

#define PROG_MODE_CR   1
 

Definition at line 66 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define PROG_MODE_NA   0
 

Definition at line 65 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define PROG_MODE_UK   2
 

Definition at line 67 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define TONE_MIN_THRESH   1e8
 

Definition at line 119 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0
 

Definition at line 118 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define UK_HANGUP_THRESH   60
 

Definition at line 121 of file dsp.c.

Referenced by __ast_dsp_call_progress().


Function Documentation

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

Definition at line 1031 of file dsp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), COUNT_THRESH, dsp, 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_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::tcount, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, UK_HANGUP_THRESH, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

01032 {
01033    int x;
01034    int y;
01035    int pass;
01036    int newstate = DSP_TONE_STATE_SILENCE;
01037    int res = 0;
01038    int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH;
01039    while(len) {
01040       /* Take the lesser of the number of samples we need and what we have */
01041       pass = len;
01042       if (pass > dsp->gsamp_size - dsp->gsamps) 
01043          pass = dsp->gsamp_size - dsp->gsamps;
01044       for (x=0;x<pass;x++) {
01045          for (y=0;y<dsp->freqcount;y++) 
01046             goertzel_sample(&dsp->freqs[y], s[x]);
01047          dsp->genergy += s[x] * s[x];
01048       }
01049       s += pass;
01050       dsp->gsamps += pass;
01051       len -= pass;
01052       if (dsp->gsamps == dsp->gsamp_size) {
01053          float hz[7];
01054          for (y=0;y<7;y++)
01055             hz[y] = goertzel_result(&dsp->freqs[y]);
01056 #if 0
01057          printf("\n350:     425:     440:     480:     620:     950:     1400:    1800:    Energy:   \n");
01058          printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 
01059             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);
01060 #endif
01061          switch(dsp->progmode) {
01062          case PROG_MODE_NA:
01063             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
01064                newstate = DSP_TONE_STATE_BUSY;
01065             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
01066                newstate = DSP_TONE_STATE_RINGING;
01067             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
01068                newstate = DSP_TONE_STATE_DIALTONE;
01069             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
01070                newstate = DSP_TONE_STATE_SPECIAL1;
01071             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01072                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
01073                   newstate = DSP_TONE_STATE_SPECIAL2;
01074             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01075                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
01076                   newstate = DSP_TONE_STATE_SPECIAL3;
01077             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01078                newstate = DSP_TONE_STATE_TALKING;
01079             } else
01080                newstate = DSP_TONE_STATE_SILENCE;
01081             break;
01082          case PROG_MODE_CR:
01083             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01084                newstate = DSP_TONE_STATE_RINGING;
01085             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01086                newstate = DSP_TONE_STATE_TALKING;
01087             } else
01088                newstate = DSP_TONE_STATE_SILENCE;
01089             break;
01090          case PROG_MODE_UK:
01091             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
01092                newstate = DSP_TONE_STATE_HUNGUP;
01093             }
01094             break;
01095          default:
01096             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01097          }
01098          if (newstate == dsp->tstate) {
01099             dsp->tcount++;
01100             if (dsp->tcount == thresh) {
01101                if ((dsp->features & DSP_PROGRESS_BUSY) && 
01102                    dsp->tstate == DSP_TONE_STATE_BUSY) {
01103                   res = AST_CONTROL_BUSY;
01104                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01105                } else if ((dsp->features & DSP_PROGRESS_TALK) && 
01106                      dsp->tstate == DSP_TONE_STATE_TALKING) {
01107                   res = AST_CONTROL_ANSWER;
01108                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01109                } else if ((dsp->features & DSP_PROGRESS_RINGING) && 
01110                      dsp->tstate == DSP_TONE_STATE_RINGING)
01111                   res = AST_CONTROL_RINGING;
01112                else if ((dsp->features & DSP_PROGRESS_CONGESTION) && 
01113                    dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
01114                   res = AST_CONTROL_CONGESTION;
01115                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01116                } else if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01117                   dsp->tstate == DSP_TONE_STATE_HUNGUP) {
01118                   res = AST_CONTROL_HANGUP;
01119                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01120                }
01121             }
01122          } else {
01123 #if 0
01124             printf("Newstate: %d\n", newstate);
01125 #endif
01126             dsp->tstate = newstate;
01127             dsp->tcount = 1;
01128          }
01129          
01130          /* Reset goertzel */                
01131          for (x=0;x<7;x++)
01132             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01133          dsp->gsamps = 0;
01134          dsp->genergy = 0.0;
01135       }
01136    }
01137 #if 0
01138    if (res)
01139       printf("Returning %d\n", res);
01140 #endif      
01141    return res;
01142 }

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

Definition at line 956 of file dsp.c.

References ast_dsp::digitmode, dsp, 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().

00957 {
00958    int res;
00959    
00960    if (dsp->digitmode & DSP_DIGITMODE_MF)
00961       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00962    else
00963       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
00964    return res;
00965 }

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

Definition at line 1157 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

01158 {
01159    int accum;
01160    int x;
01161    int res = 0;
01162 
01163    if (!len)
01164       return 0;
01165    accum = 0;
01166    for (x=0;x<len; x++) 
01167       accum += abs(s[x]);
01168    accum /= len;
01169    if (accum < dsp->threshold) {
01170       /* Silent */
01171       dsp->totalsilence += len/8;
01172       if (dsp->totalnoise) {
01173          /* Move and save history */
01174          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01175          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01176 /* we don't want to check for busydetect that frequently */
01177 #if 0
01178          dsp->busymaybe = 1;
01179 #endif
01180       }
01181       dsp->totalnoise = 0;
01182       res = 1;
01183    } else {
01184       /* Not silent */
01185       dsp->totalnoise += len/8;
01186       if (dsp->totalsilence) {
01187          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01188          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01189          /* Move and save history */
01190          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01191          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01192          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01193          if (silence1 < silence2) {
01194             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01195                dsp->busymaybe = 1;
01196             else 
01197                dsp->busymaybe = 0;
01198          } else {
01199             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01200                dsp->busymaybe = 1;
01201             else 
01202                dsp->busymaybe = 0;
01203          }
01204       }
01205       dsp->totalsilence = 0;
01206    }
01207    if (totalsilence)
01208       *totalsilence = dsp->totalsilence;
01209    return res;
01210 }

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 1213 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, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, and LOG_NOTICE.

Referenced by ast_dsp_busydetect(), and ast_dsp_process().

01214 {
01215    int res = 0, x;
01216 #ifndef BUSYDETECT_TONEONLY
01217    int avgsilence = 0, hitsilence = 0;
01218 #endif
01219    int avgtone = 0, hittone = 0;
01220    if (!dsp->busymaybe)
01221       return res;
01222    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01223 #ifndef BUSYDETECT_TONEONLY
01224       avgsilence += dsp->historicsilence[x];
01225 #endif
01226       avgtone += dsp->historicnoise[x];
01227    }
01228 #ifndef BUSYDETECT_TONEONLY
01229    avgsilence /= dsp->busycount;
01230 #endif
01231    avgtone /= dsp->busycount;
01232    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01233 #ifndef BUSYDETECT_TONEONLY
01234       if (avgsilence > dsp->historicsilence[x]) {
01235          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01236             hitsilence++;
01237       } else {
01238          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01239             hitsilence++;
01240       }
01241 #endif
01242       if (avgtone > dsp->historicnoise[x]) {
01243          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01244             hittone++;
01245       } else {
01246          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01247             hittone++;
01248       }
01249    }
01250 #ifndef BUSYDETECT_TONEONLY
01251    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01252        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01253        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01254 #else
01255    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01256 #endif
01257 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01258 #ifdef BUSYDETECT_TONEONLY
01259 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
01260 #endif
01261       if (avgtone > avgsilence) {
01262          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01263             res = 1;
01264       } else {
01265          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01266             res = 1;
01267       }
01268 #else
01269       res = 1;
01270 #endif
01271    }
01272    /* If we know the expected busy tone length, check we are in the range */
01273    if (res && (dsp->busy_tonelength > 0)) {
01274       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01275 #if 0
01276          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
01277                   avgtone, dsp->busy_tonelength);
01278 #endif
01279          res = 0;
01280       }
01281    }
01282 #ifndef BUSYDETECT_TONEONLY
01283    /* If we know the expected busy tone silent-period length, check we are in the range */
01284    if (res && (dsp->busy_quietlength > 0)) {
01285       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01286 #if 0
01287          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01288                   avgsilence, dsp->busy_quietlength);
01289 #endif
01290          res = 0;
01291       }
01292    }
01293 #endif
01294 #if 1
01295    if (res)
01296       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01297 #endif
01298    return res;
01299 }

int ast_dsp_call_progress struct ast_dsp dsp,
struct ast_frame inf
 

Scans for progress indication in audio.

Definition at line 1144 of file dsp.c.

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

01145 {
01146    if (inf->frametype != AST_FRAME_VOICE) {
01147       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01148       return 0;
01149    }
01150    if (inf->subclass != AST_FORMAT_SLINEAR) {
01151       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01152       return 0;
01153    }
01154    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01155 }

int ast_dsp_digitdetect struct ast_dsp dsp,
struct ast_frame inf
 

Return non-zero if DTMF hit was found.

Definition at line 967 of file dsp.c.

References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.

00968 {
00969    short *s;
00970    int len;
00971    int ign=0;
00972 
00973    if (inf->frametype != AST_FRAME_VOICE) {
00974       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
00975       return 0;
00976    }
00977    if (inf->subclass != AST_FORMAT_SLINEAR) {
00978       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
00979       return 0;
00980    }
00981    s = inf->data;
00982    len = inf->datalen / 2;
00983    return __ast_dsp_digitdetect(dsp, s, len, &ign);
00984 }

int ast_dsp_digitmode struct ast_dsp dsp,
int  digitmode
 

Set digit mode.

Definition at line 1686 of file dsp.c.

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

Referenced by i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

01687 {
01688    int new;
01689    int old;
01690    
01691    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01692    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01693    if (old != new) {
01694       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01695       if (new & DSP_DIGITMODE_MF)
01696          ast_mf_detect_init(&dsp->td.mf);
01697       else
01698          ast_dtmf_detect_init(&dsp->td.dtmf);
01699    }
01700    dsp->digitmode = digitmode;
01701    return 0;
01702 }

void ast_dsp_digitreset struct ast_dsp dsp  ) 
 

Reset DTMF detector.

Definition at line 1624 of file dsp.c.

References mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, ast_dsp::digitmode, mf_detect_state_t::digits, dsp, DSP_DIGITMODE_MF, goertzel_reset(), mf_detect_state_t::hits, ast_dsp::mf, mf_detect_state_t::mhit, ast_dsp::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out.

Referenced by ss_thread().

01625 {
01626    int i;
01627    
01628    dsp->thinkdigit = 0;
01629    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01630       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01631       dsp->td.mf.current_digits = 0;
01632       /* Reinitialise the detector for the next block */
01633       for (i = 0;  i < 6;  i++) {
01634          goertzel_reset(&dsp->td.mf.tone_out[i]);
01635 #ifdef OLD_DSP_ROUTINES
01636          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01637 #endif         
01638       }
01639 #ifdef OLD_DSP_ROUTINES
01640       dsp->td.mf.energy = 0.0;
01641       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01642 #else
01643       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;
01644 #endif      
01645       dsp->td.mf.current_sample = 0;
01646    } else {
01647       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01648       dsp->td.dtmf.current_digits = 0;
01649       /* Reinitialise the detector for the next block */
01650       for (i = 0;  i < 4;  i++) {
01651          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01652          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01653 #ifdef OLD_DSP_ROUTINES
01654          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01655          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01656 #endif         
01657       }
01658 #ifdef FAX_DETECT
01659       goertzel_reset (&dsp->td.dtmf.fax_tone);
01660 #endif
01661 #ifdef OLD_DSP_ROUTINES
01662 #ifdef FAX_DETECT
01663       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01664 #endif
01665       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01666 #else
01667       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01668 #endif      
01669       dsp->td.dtmf.energy = 0.0;
01670       dsp->td.dtmf.current_sample = 0;
01671    }
01672 }

void ast_dsp_free struct ast_dsp dsp  ) 
 

Definition at line 1598 of file dsp.c.

References dsp, and free.

Referenced by __oh323_destroy(), ast_app_getvoice(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), handle_recordfile(), i4l_hangup(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), ss_thread(), vpb_hangup(), and zt_hangup().

01599 {
01600    free(dsp);
01601 }

int ast_dsp_get_tcount struct ast_dsp dsp  ) 
 

Get tcount (Threshold counter).

Definition at line 1723 of file dsp.c.

References dsp, and ast_dsp::tcount.

01724 {
01725    return dsp->tcount;
01726 }

int ast_dsp_get_tstate struct ast_dsp dsp  ) 
 

Get tstate (Tone State).

Definition at line 1718 of file dsp.c.

References dsp, and ast_dsp::tstate.

01719 {
01720    return dsp->tstate;
01721 }

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

Get pending DTMF/MF digits.

Definition at line 1006 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, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

01007 {
01008    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01009       if (max > dsp->td.mf.current_digits)
01010          max = dsp->td.mf.current_digits;
01011       if (max > 0) {
01012          memcpy(buf, dsp->td.mf.digits, max);
01013          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01014          dsp->td.mf.current_digits -= max;
01015       }
01016       buf[max] = '\0';
01017       return  max;
01018    } else {
01019       if (max > dsp->td.dtmf.current_digits)
01020          max = dsp->td.dtmf.current_digits;
01021       if (max > 0) {
01022          memcpy (buf, dsp->td.dtmf.digits, max);
01023          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01024          dsp->td.dtmf.current_digits -= max;
01025       }
01026       buf[max] = '\0';
01027       return  max;
01028    }
01029 }

struct ast_dsp* ast_dsp_new void   ) 
 

Definition at line 1575 of file dsp.c.

References ast_dsp_prog_reset(), ast_dtmf_detect_init(), DEFAULT_THRESHOLD, dsp, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and malloc.

Referenced by __oh323_new(), ast_app_getvoice(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_dtmfmode(), sip_new(), and zt_new().

01576 {
01577    struct ast_dsp *dsp;
01578 
01579    dsp = malloc(sizeof(struct ast_dsp));
01580    if (dsp) {
01581       memset(dsp, 0, sizeof(struct ast_dsp));
01582       dsp->threshold = DEFAULT_THRESHOLD;
01583       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01584       dsp->busycount = DSP_HISTORY;
01585       /* Initialize DTMF detector */
01586       ast_dtmf_detect_init(&dsp->td.dtmf);
01587       /* Initialize initial DSP progress detect parameters */
01588       ast_dsp_prog_reset(dsp);
01589    }
01590    return dsp;
01591 }

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 1365 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_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, 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, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, ast_channel::name, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

01366 {
01367    int silence;
01368    int res;
01369    int digit;
01370    int x;
01371    short *shortdata;
01372    unsigned char *odata;
01373    int len;
01374    int writeback = 0;
01375 
01376 #define FIX_INF(inf) do { \
01377       if (writeback) { \
01378          switch(inf->subclass) { \
01379          case AST_FORMAT_SLINEAR: \
01380             break; \
01381          case AST_FORMAT_ULAW: \
01382             for (x=0;x<len;x++) \
01383                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01384             break; \
01385          case AST_FORMAT_ALAW: \
01386             for (x=0;x<len;x++) \
01387                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01388             break; \
01389          } \
01390       } \
01391    } while(0) 
01392 
01393    if (!af)
01394       return NULL;
01395    if (af->frametype != AST_FRAME_VOICE)
01396       return af;
01397    odata = af->data;
01398    len = af->datalen;
01399    /* Make sure we have short data */
01400    switch(af->subclass) {
01401    case AST_FORMAT_SLINEAR:
01402       shortdata = af->data;
01403       len = af->datalen / 2;
01404       break;
01405    case AST_FORMAT_ULAW:
01406       shortdata = alloca(af->datalen * 2);
01407       if (!shortdata) {
01408          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01409          return af;
01410       }
01411       for (x=0;x<len;x++) 
01412          shortdata[x] = AST_MULAW(odata[x]);
01413       break;
01414    case AST_FORMAT_ALAW:
01415       shortdata = alloca(af->datalen * 2);
01416       if (!shortdata) {
01417          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01418          return af;
01419       }
01420       for (x=0;x<len;x++) 
01421          shortdata[x] = AST_ALAW(odata[x]);
01422       break;
01423    default:
01424       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01425       return af;
01426    }
01427    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01428    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01429       memset(&dsp->f, 0, sizeof(dsp->f));
01430       dsp->f.frametype = AST_FRAME_NULL;
01431       return &dsp->f;
01432    }
01433    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01434       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01435       memset(&dsp->f, 0, sizeof(dsp->f));
01436       dsp->f.frametype = AST_FRAME_CONTROL;
01437       dsp->f.subclass = AST_CONTROL_BUSY;
01438       ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01439       return &dsp->f;
01440    }
01441    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01442       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01443 #if 0
01444       if (digit)
01445          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01446 #endif         
01447       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01448          if (!dsp->thinkdigit) {
01449             if (digit) {
01450                /* Looks like we might have something.  
01451                 * Request a conference mute for the moment */
01452                memset(&dsp->f, 0, sizeof(dsp->f));
01453                dsp->f.frametype = AST_FRAME_DTMF;
01454                dsp->f.subclass = 'm';
01455                dsp->thinkdigit = 'x';
01456                FIX_INF(af);
01457                if (chan)
01458                   ast_queue_frame(chan, af);
01459                ast_frfree(af);
01460                return &dsp->f;
01461             }
01462          } else {
01463             if (digit) {
01464                /* Thought we saw one last time.  Pretty sure we really have now */
01465                if (dsp->thinkdigit) {
01466                   if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01467                      /* If we found a digit, and we're changing digits, go
01468                         ahead and send this one, but DON'T stop confmute because
01469                         we're detecting something else, too... */
01470                      memset(&dsp->f, 0, sizeof(dsp->f));
01471                      dsp->f.frametype = AST_FRAME_DTMF;
01472                      dsp->f.subclass = dsp->thinkdigit;
01473                      FIX_INF(af);
01474                      if (chan)
01475                         ast_queue_frame(chan, af);
01476                      ast_frfree(af);
01477                   }
01478                   dsp->thinkdigit = digit;
01479                   return &dsp->f;
01480                }
01481                dsp->thinkdigit = digit;
01482             } else {
01483                if (dsp->thinkdigit) {
01484                   memset(&dsp->f, 0, sizeof(dsp->f));
01485                   if (dsp->thinkdigit != 'x') {
01486                      /* If we found a digit, send it now */
01487                      dsp->f.frametype = AST_FRAME_DTMF;
01488                      dsp->f.subclass = dsp->thinkdigit;
01489                      dsp->thinkdigit = 0;
01490                   } else {
01491                      dsp->f.frametype = AST_FRAME_DTMF;
01492                      dsp->f.subclass = 'u';
01493                      dsp->thinkdigit = 0;
01494                   }
01495                   FIX_INF(af);
01496                   if (chan)
01497                      ast_queue_frame(chan, af);
01498                   ast_frfree(af);
01499                   return &dsp->f;
01500                }
01501             }
01502          }
01503       } else if (!digit) {
01504          /* Only check when there is *not* a hit... */
01505          if (dsp->digitmode & DSP_DIGITMODE_MF) {
01506             if (dsp->td.mf.current_digits) {
01507                memset(&dsp->f, 0, sizeof(dsp->f));
01508                dsp->f.frametype = AST_FRAME_DTMF;
01509                dsp->f.subclass = dsp->td.mf.digits[0];
01510                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01511                dsp->td.mf.current_digits--;
01512                FIX_INF(af);
01513                if (chan)
01514                   ast_queue_frame(chan, af);
01515                ast_frfree(af);
01516                return &dsp->f;
01517             }
01518          } else {
01519             if (dsp->td.dtmf.current_digits) {
01520                memset(&dsp->f, 0, sizeof(dsp->f));
01521                dsp->f.frametype = AST_FRAME_DTMF;
01522                dsp->f.subclass = dsp->td.dtmf.digits[0];
01523                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01524                dsp->td.dtmf.current_digits--;
01525                FIX_INF(af);
01526                if (chan)
01527                   ast_queue_frame(chan, af);
01528                ast_frfree(af);
01529                return &dsp->f;
01530             }
01531          }
01532       }
01533    }
01534    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01535       res = __ast_dsp_call_progress(dsp, shortdata, len);
01536       if (res) {
01537          switch(res) {
01538          case AST_CONTROL_ANSWER:
01539          case AST_CONTROL_BUSY:
01540          case AST_CONTROL_RINGING:
01541          case AST_CONTROL_CONGESTION:
01542          case AST_CONTROL_HANGUP:
01543             memset(&dsp->f, 0, sizeof(dsp->f));
01544             dsp->f.frametype = AST_FRAME_CONTROL;
01545             dsp->f.subclass = res;
01546             dsp->f.src = "dsp_progress";
01547             if (chan) 
01548                ast_queue_frame(chan, &dsp->f);
01549             break;
01550          default:
01551             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01552          }
01553       }
01554    }
01555    FIX_INF(af);
01556    return af;
01557 }

static void ast_dsp_prog_reset struct ast_dsp dsp  )  [static]
 

Definition at line 1559 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01560 {
01561    int max = 0;
01562    int x;
01563    
01564    dsp->gsamp_size = modes[dsp->progmode].size;
01565    dsp->gsamps = 0;
01566    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
01567       if (modes[dsp->progmode].freqs[x]) {
01568          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01569          max = x + 1;
01570       }
01571    }
01572    dsp->freqcount = max;
01573 }

void ast_dsp_reset struct ast_dsp dsp  ) 
 

Reset total silence count.

Definition at line 1674 of file dsp.c.

References dsp, ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

01675 {
01676    int x;
01677    
01678    dsp->totalsilence = 0;
01679    dsp->gsamps = 0;
01680    for (x=0;x<4;x++)
01681       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01682    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01683    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01684 }

void ast_dsp_set_busy_count struct ast_dsp dsp,
int  cadences
 

Set number of required cadences for busy.

Definition at line 1608 of file dsp.c.

References ast_dsp::busycount, dsp, and DSP_HISTORY.

Referenced by zt_new().

01609 {
01610    if (cadences < 4)
01611       cadences = 4;
01612    if (cadences > DSP_HISTORY)
01613       cadences = DSP_HISTORY;
01614    dsp->busycount = cadences;
01615 }

void ast_dsp_set_busy_pattern struct ast_dsp dsp,
int  tonelength,
int  quietlength
 

Set expected lengths of the busy tone.

Definition at line 1617 of file dsp.c.

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

Referenced by zt_new().

01618 {
01619    dsp->busy_tonelength = tonelength;
01620    dsp->busy_quietlength = quietlength;
01621    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01622 }

int ast_dsp_set_call_progress_zone struct ast_dsp dsp,
char *  zone
 

Set zone for doing progress detection.

Definition at line 1704 of file dsp.c.

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

Referenced by zt_new().

01705 {
01706    int x;
01707    
01708    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01709       if (!strcasecmp(aliases[x].name, zone)) {
01710          dsp->progmode = aliases[x].mode;
01711          ast_dsp_prog_reset(dsp);
01712          return 0;
01713       }
01714    }
01715    return -1;
01716 }

void ast_dsp_set_features struct ast_dsp dsp,
int  features
 

Select feature set.

Definition at line 1593 of file dsp.c.

References dsp, and ast_dsp::features.

Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_dtmfmode(), sip_new(), and zt_new().

01594 {
01595    dsp->features = features;
01596 }

void ast_dsp_set_threshold struct ast_dsp dsp,
int  threshold
 

Set threshold value for silence.

Definition at line 1603 of file dsp.c.

References dsp, and ast_dsp::threshold.

Referenced by do_waiting(), and handle_recordfile().

01604 {
01605    dsp->threshold = threshold;
01606 }

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

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

Referenced by background_detect_exec(), and handle_recordfile().

01348 {
01349    short *s;
01350    int len;
01351    
01352    if (f->frametype != AST_FRAME_VOICE) {
01353       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01354       return 0;
01355    }
01356    if (f->subclass != AST_FORMAT_SLINEAR) {
01357       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01358       return 0;
01359    }
01360    s = f->data;
01361    len = f->datalen/2;
01362    return __ast_dsp_silence(dsp, s, len, totalsilence);
01363 }

static void ast_dtmf_detect_init dtmf_detect_state_t s  )  [static]
 

Definition at line 338 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

00339 {
00340    int i;
00341 
00342 #ifdef OLD_DSP_ROUTINES
00343    s->hit1 = 
00344    s->mhit = 
00345    s->hit3 =
00346    s->hit4 = 
00347    s->hit2 = 0;
00348 #else
00349    s->hits[0] = s->hits[1] = s->hits[2] = 0;
00350 #endif
00351    for (i = 0;  i < 4;  i++) {
00352       goertzel_init (&s->row_out[i], dtmf_row[i], 102);
00353       goertzel_init (&s->col_out[i], dtmf_col[i], 102);
00354 #ifdef OLD_DSP_ROUTINES
00355       goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
00356       goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
00357 #endif   
00358       s->energy = 0.0;
00359    }
00360 #ifdef FAX_DETECT
00361    /* Same for the fax dector */
00362    goertzel_init (&s->fax_tone, fax_freq, 102);
00363 
00364 #ifdef OLD_DSP_ROUTINES
00365    /* Same for the fax dector 2nd harmonic */
00366    goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
00367 #endif   
00368 #endif /* FAX_DETECT */
00369    s->current_sample = 0;
00370    s->detected_digits = 0;
00371    s->current_digits = 0;
00372    memset(&s->digits, 0, sizeof(s->digits));
00373    s->lost_digits = 0;
00374    s->digits[0] = '\0';
00375 }

static void ast_mf_detect_init mf_detect_state_t s  )  [static]
 

Definition at line 377 of file dsp.c.

References goertzel_init(), mf_tones, and s.

Referenced by ast_dsp_digitmode().

00378 {
00379    int i;
00380 #ifdef OLD_DSP_ROUTINES
00381    s->hit1 = 
00382    s->hit2 = 0;
00383 #else 
00384    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00385 #endif
00386    for (i = 0;  i < 6;  i++) {
00387       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00388 #ifdef OLD_DSP_ROUTINES
00389       goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
00390       s->energy = 0.0;
00391 #endif
00392    }
00393    s->current_digits = 0;
00394    memset(&s->digits, 0, sizeof(s->digits));
00395    s->current_sample = 0;
00396    s->detected_digits = 0;
00397    s->lost_digits = 0;
00398    s->digits[0] = '\0';
00399    s->mhit = 0;
00400 }

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

Definition at line 402 of file dsp.c.

References s, and warning().

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 296 of file dsp.c.

References s.

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

00297 {
00298    s->v2 = s->v3 = 0.0;
00299    s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
00300 #ifndef OLD_DSP_ROUTINES
00301    s->samples = samples;
00302 #endif
00303 }

static void goertzel_reset goertzel_state_t s  )  [inline, static]
 

Definition at line 305 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

00306 {
00307    s->v2 = s->v3 = 0.0;
00308 }

static float goertzel_result goertzel_state_t s  )  [inline, static]
 

Definition at line 291 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress().

00292 {
00293    return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
00294 }

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

Definition at line 272 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress(), and goertzel_update().

00273 {
00274    float v1;
00275    float fsamp  = sample;
00276    
00277    v1 = s->v2;
00278    s->v2 = s->v3;
00279    s->v3 = s->fac * s->v2 - v1 + fsamp;
00280 }

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

Definition at line 282 of file dsp.c.

References goertzel_sample(), and s.

00283 {
00284    int i;
00285    
00286    for (i=0;i<count;i++) 
00287       goertzel_sample(s, samps[i]);
00288 }

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

Definition at line 673 of file dsp.c.

References MF_GSIZE, s, and warning().

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 986 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

00987 {
00988    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00989    /* Make sure absolute levels are high enough */
00990    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
00991       return 0;
00992    /* Amplify ignored stuff */
00993    i2 *= TONE_THRESH;
00994    i1 *= TONE_THRESH;
00995    e *= TONE_THRESH;
00996    /* Check first tone */
00997    if ((p1 < i1) || (p1 < i2) || (p1 < e))
00998       return 0;
00999    /* And second */
01000    if ((p2 < i1) || (p2 < i2) || (p2 < e))
01001       return 0;
01002    /* Guess it's there... */
01003    return 1;
01004 }


Variable Documentation

struct progalias aliases[] [static]
 

Referenced by add_header(), ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 269 of file dsp.c.

float dtmf_col[] [static]
 

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 243 of file dsp.c.

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

Definition at line 257 of file dsp.c.

float dtmf_row[] [static]
 

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 239 of file dsp.c.

float fax_freq = 1100.0 [static]
 

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

Referenced by ast_mf_detect_init().

struct progress modes[] [static]
 

Referenced by ast_dsp_prog_reset().


Generated on Sat Nov 25 00:46:04 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6