Fri May 26 01:48:25 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"

Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

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

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#define 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    /* If we know the expected busy tone silent-period length, check we are in the range */
01283    if (res && (dsp->busy_quietlength > 0)) {
01284       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01285 #if 0
01286          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01287                   avgsilence, dsp->busy_quietlength);
01288 #endif
01289          res = 0;
01290       }
01291    }
01292 #if 1
01293    if (res)
01294       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01295 #endif
01296    return res;
01297 }

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

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

void ast_dsp_digitreset struct ast_dsp dsp  ) 
 

Reset DTMF detector.

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

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

void ast_dsp_free struct ast_dsp dsp  ) 
 

Definition at line 1596 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(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), vpb_hangup(), and zt_hangup().

01597 {
01598    free(dsp);
01599 }

int ast_dsp_get_tcount struct ast_dsp dsp  ) 
 

Get tcount (Threshold counter).

Definition at line 1721 of file dsp.c.

References dsp, and ast_dsp::tcount.

01722 {
01723    return dsp->tcount;
01724 }

int ast_dsp_get_tstate struct ast_dsp dsp  ) 
 

Get tstate (Tone State).

Definition at line 1716 of file dsp.c.

References dsp, and ast_dsp::tstate.

01717 {
01718    return dsp->tstate;
01719 }

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 1573 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(), record_exec(), sip_dtmfmode(), sip_new(), and zt_new().

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

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 1363 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(), misdn_tx2ast_frm(), oh323_rtp_read(), sip_rtp_read(), and zt_read().

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

static void ast_dsp_prog_reset struct ast_dsp dsp  )  [static]
 

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

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

void ast_dsp_reset struct ast_dsp dsp  ) 
 

Reset total silence count.

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

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

void ast_dsp_set_busy_count struct ast_dsp dsp,
int  cadences
 

Set number of required cadences for busy.

Definition at line 1606 of file dsp.c.

References ast_dsp::busycount, dsp, and DSP_HISTORY.

Referenced by zt_new().

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

void ast_dsp_set_busy_pattern struct ast_dsp dsp,
int  tonelength,
int  quietlength
 

Set expected lengths of the busy tone.

Definition at line 1615 of file dsp.c.

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

Referenced by zt_new().

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

int ast_dsp_set_call_progress_zone struct ast_dsp dsp,
char *  zone
 

Set zone for doing progress detection.

Definition at line 1702 of file dsp.c.

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

Referenced by zt_new().

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

void ast_dsp_set_features struct ast_dsp dsp,
int  features
 

Select feature set.

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

01592 {
01593    dsp->features = features;
01594 }

void ast_dsp_set_threshold struct ast_dsp dsp,
int  threshold
 

Set threshold value for silence.

Definition at line 1601 of file dsp.c.

References dsp, and ast_dsp::threshold.

Referenced by do_waiting(), handle_recordfile(), and record_exec().

01602 {
01603    dsp->threshold = threshold;
01604 }

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 1345 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(), handle_recordfile(), and record_exec().

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

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 Fri May 26 01:48:26 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6