Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:30 2007

Asterisk developer's documentation :: Codename Pineapple


dsp.c File Reference


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.

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

Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6
 

Definition at line 181 of file dsp.c.

#define BELL_MF_THRESHOLD   1.6e9
 

Definition at line 179 of file dsp.c.

#define BELL_MF_TWIST   4.0
 

Definition at line 180 of file dsp.c.

#define BUSYDETECT_MARTIN
 

Definition at line 185 of file dsp.c.

#define DEFAULT_THRESHOLD   512
 

Definition at line 114 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15
 

Remember last 15 units

Definition at line 125 of file dsp.c.

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

#define DTMF_2ND_HARMONIC_COL   63.1
 

Definition at line 169 of file dsp.c.

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

Definition at line 168 of file dsp.c.

#define DTMF_NORMAL_TWIST   6.3
 

Definition at line 160 of file dsp.c.

#define DTMF_RELATIVE_PEAK_COL   6.3
 

Definition at line 167 of file dsp.c.

#define DTMF_RELATIVE_PEAK_ROW   6.3
 

Definition at line 166 of file dsp.c.

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

Definition at line 164 of file dsp.c.

#define DTMF_THRESHOLD   8.0e7
 

Definition at line 157 of file dsp.c.

#define DTMF_TO_TOTAL_ENERGY   42.0
 

Definition at line 170 of file dsp.c.

#define FAX_2ND_HARMONIC   2.0
 

Definition at line 159 of file dsp.c.

#define FAX_DETECT
 

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

Definition at line 128 of file dsp.c.

#define FAX_THRESHOLD   8.0e7
 

Definition at line 158 of file dsp.c.

#define FIX_INF inf   ) 
 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128
 

Definition at line 143 of file dsp.c.

#define MF_GSIZE   120
 

Definition at line 690 of file dsp.c.

Referenced by mf_detect().

#define TONE_MIN_THRESH   1e8
 

How much tone there should be at least to attempt

Definition at line 131 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0
 

How much louder the tone should be than channel energy

Definition at line 130 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

enum busy_detect
 

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

Definition at line 116 of file dsp.c.

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

enum freq_index
 

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

Definition at line 77 of file dsp.c.

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

enum gsamp_size
 

Number of goertzels for progress detect

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

Definition at line 65 of file dsp.c.

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

enum gsamp_thresh
 

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

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

Definition at line 134 of file dsp.c.

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

enum prog_mode
 

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 71 of file dsp.c.

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


Function Documentation

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

Definition at line 1051 of file dsp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_NOTICE, LOG_WARNING, pair_there(), PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

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

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

Definition at line 976 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, ast_dsp::dtmf, dtmf_detect(), ast_dsp::features, ast_dsp::mf, mf_detect(), and ast_dsp::td.

Referenced by ast_dsp_digitdetect(), and ast_dsp_process().

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

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

Definition at line 1201 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

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

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

References ast_dsp_busydetect(), ast_log(), BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, BUSY_THRESHOLD, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, LOG_NOTICE, and option_debug.

Referenced by ast_dsp_busydetect(), and ast_dsp_process().

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

int ast_dsp_call_progress struct ast_dsp dsp,
struct ast_frame inf
 

Scans for progress indication in audio.

Definition at line 1188 of file dsp.c.

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

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

int ast_dsp_digitdetect struct ast_dsp dsp,
struct ast_frame inf
 

Return non-zero if DTMF hit was found.

Definition at line 987 of file dsp.c.

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

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

int ast_dsp_digitmode struct ast_dsp dsp,
int  digitmode
 

Set digit mode.

Definition at line 1729 of file dsp.c.

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

Referenced by mgcp_new(), sip_new(), ss_thread(), zt_hangup(), and zt_setoption().

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

void ast_dsp_digitreset struct ast_dsp dsp  ) 
 

Reset DTMF detector.

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

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

void ast_dsp_free struct ast_dsp dsp  ) 
 

Definition at line 1639 of file dsp.c.

References free.

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

01640 {
01641    free(dsp);
01642 }

int ast_dsp_get_tcount struct ast_dsp dsp  ) 
 

Get tcount (Threshold counter).

Definition at line 1766 of file dsp.c.

References ast_dsp::tcount.

01767 {
01768    return dsp->tcount;
01769 }

int ast_dsp_get_tstate struct ast_dsp dsp  ) 
 

Get tstate (Tone State).

Definition at line 1761 of file dsp.c.

References ast_dsp::tstate.

01762 {
01763    return dsp->tstate;
01764 }

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

Get pending DTMF/MF digits.

Definition at line 1026 of file dsp.c.

References mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

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

struct ast_dsp* ast_dsp_new void   ) 
 

Definition at line 1618 of file dsp.c.

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

Referenced by __oh323_new(), handle_recordfile(), mgcp_new(), read_config(), sip_dtmfmode(), and sip_new().

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

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

References __ast_dsp_call_progress(), __ast_dsp_digitdetect(), __ast_dsp_silence(), ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, option_debug, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

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

static void ast_dsp_prog_reset struct ast_dsp dsp  )  [static]
 

Definition at line 1601 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

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

void ast_dsp_reset struct ast_dsp dsp  ) 
 

Reset total silence count.

Definition at line 1716 of file dsp.c.

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

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

void ast_dsp_set_busy_count struct ast_dsp dsp,
int  cadences
 

Set number of required cadences for busy.

Definition at line 1649 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

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

void ast_dsp_set_busy_pattern struct ast_dsp dsp,
int  tonelength,
int  quietlength
 

Set expected lengths of the busy tone.

Definition at line 1658 of file dsp.c.

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

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

int ast_dsp_set_call_progress_zone struct ast_dsp dsp,
char *  zone
 

Set zone for doing progress detection.

Definition at line 1747 of file dsp.c.

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

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

void ast_dsp_set_features struct ast_dsp dsp,
int  features
 

Select feature set.

Definition at line 1634 of file dsp.c.

References ast_dsp::features.

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

01635 {
01636    dsp->features = features;
01637 }

void ast_dsp_set_threshold struct ast_dsp dsp,
int  threshold
 

Set threshold value for silence.

Definition at line 1644 of file dsp.c.

References ast_dsp::threshold.

Referenced by handle_recordfile().

01645 {
01646    dsp->threshold = threshold;
01647 }

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

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

Referenced by handle_recordfile().

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

static void ast_dtmf_detect_init dtmf_detect_state_t s  )  [static]
 

Definition at line 358 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

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

static void ast_mf_detect_init mf_detect_state_t s  )  [static]
 

Definition at line 397 of file dsp.c.

References goertzel_init(), mf_tones, and s.

Referenced by ast_dsp_digitmode().

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

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

Definition at line 422 of file dsp.c.

References s, and warning().

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 315 of file dsp.c.

References s.

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

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

static void goertzel_reset goertzel_state_t s  )  [inline, static]
 

Definition at line 324 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

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

static float goertzel_result goertzel_state_t s  )  [inline, static]
 

Definition at line 310 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress().

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

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

Definition at line 291 of file dsp.c.

References s.

Referenced by __ast_dsp_call_progress(), and goertzel_update().

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

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

Definition at line 301 of file dsp.c.

References goertzel_sample(), and s.

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

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

Definition at line 693 of file dsp.c.

References MF_GSIZE, s, and warning().

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 1006 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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


Variable Documentation

struct progalias aliases[] [static]
 

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 288 of file dsp.c.

float dtmf_col[] [static]
 

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 262 of file dsp.c.

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

Definition at line 276 of file dsp.c.

float dtmf_row[] [static]
 

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 258 of file dsp.c.

float fax_freq = 1100.0 [static]
 

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

Referenced by ast_mf_detect_init().

struct progress modes[] [static]
 

Referenced by ast_dsp_prog_reset().


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen