Thu Jul 9 13:41:16 2009

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"

Go to the source code of this file.

Data Structures

struct  ast_dsp
struct  digit_detect_state_t
struct  dtmf_detect_state_t
struct  goertzel_result_t
struct  goertzel_state_t
struct  mf_detect_state_t
struct  progalias
struct  progress
struct  tone_detect_state_t

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#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_THRESHOLD   8.0e7
#define FAX_TONE_CED_DB   16
#define FAX_TONE_CED_DURATION   2600
#define FAX_TONE_CED_FREQ   2100
#define FAX_TONE_CNG_DB   16
#define FAX_TONE_CNG_DURATION   500
#define FAX_TONE_CNG_FREQ   1100
#define FIX_INF(inf)
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define SAMPLE_RATE   8000
#define SAMPLES_IN_FRAME   160
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0

Enumerations

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

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static int __ast_dsp_digitdetect (struct ast_dsp *dsp, short *s, int len, int *writeback)
static int __ast_dsp_silence (struct ast_dsp *dsp, short *s, int len, int *totalsilence)
static void ast_digit_detect_init (digit_detect_state_t *s, int mf)
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_frame_freed (struct ast_frame *fr)
 Hint that a frame from a dsp was freed.
void ast_dsp_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
 Get pending DTMF/MF digits.
ast_dspast_dsp_new (void)
ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
void ast_dsp_set_busy_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
 Set expected lengths of the busy tones.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode.
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_fax_detect_init (struct ast_dsp *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static void ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp)
static int dtmf_detect (digit_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback)
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 (digit_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)
static void store_digit (digit_detect_state_t *s, char digit)
static int tone_detect (tone_detect_state_t *s, int16_t *amp, int samples, int *writeback)

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 mf_tones []
static struct progress modes []


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 164 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 162 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 163 of file dsp.c.

Referenced by mf_detect().

#define DEFAULT_THRESHOLD   512

Definition at line 107 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

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

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

Definition at line 158 of file dsp.c.

#define DTMF_NORMAL_TWIST   6.3

Definition at line 150 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 157 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 156 of file dsp.c.

Referenced by dtmf_detect().

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

Definition at line 154 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 147 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 160 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 149 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 148 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 183 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 182 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 181 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 175 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 174 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 173 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FIX_INF ( inf   ) 

Referenced by ast_dsp_process().

#define MAX_DTMF_DIGITS   128

Definition at line 133 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 679 of file dsp.c.

Referenced by mf_detect().

#define SAMPLE_RATE   8000

Definition at line 185 of file dsp.c.

Referenced by ast_tone_detect_init(), goertzel_init(), and open_stream().

#define SAMPLES_IN_FRAME   160

Definition at line 193 of file dsp.c.

Referenced by ast_tone_detect_init().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 121 of file dsp.c.

Referenced by pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 120 of file dsp.c.

Referenced by pair_there().


Enumeration Type Documentation

enum busy_detect

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

Definition at line 109 of file dsp.c.

00109                  {
00110    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last tone periods */
00111    BUSY_PAT_PERCENT = 8,   /*!< The percentage difference between measured and actual pattern */
00112    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00113    BUSY_MIN = 150,       /*!< Busy must be at least 150 ms in half-cadence */
00114    BUSY_MAX = 600          /*!< Busy can't be longer than 600 ms in half-cadence */
00115 };

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

00070                 { 
00071    /*! For US modes { */
00072    HZ_350 = 0,
00073    HZ_440,
00074    HZ_480,
00075    HZ_620,
00076    HZ_950,
00077    HZ_1400,
00078    HZ_1800, /*!< } */
00079 
00080    /*! For CR/BR modes */
00081    HZ_425 = 0,
00082 
00083    /*! For UK mode */
00084    HZ_400 = 0
00085 };

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

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

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

00124                   {
00125    THRESH_RING = 8,           /*!< Need at least 150ms ring to accept */
00126    THRESH_TALK = 2,           /*!< Talk detection does not work continuously */
00127    THRESH_BUSY = 4,           /*!< Need at least 80ms to accept */
00128    THRESH_CONGESTION = 4,     /*!< Need at least 80ms to accept */
00129    THRESH_HANGUP = 60,        /*!< Need at least 1300ms to accept hangup */
00130    THRESH_RING2ANSWER = 300   /*!< Timeout from start of ring to answer (about 6600 ms) */
00131 };

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 64 of file dsp.c.

00064                {
00065    PROG_MODE_NA = 0,
00066    PROG_MODE_CR,
00067    PROG_MODE_UK
00068 };


Function Documentation

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

Definition at line 889 of file dsp.c.

References DSP_TONE_STATE_BUSY, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_350, HZ_440, HZ_480, HZ_620, pair_there(), pass, PROG_MODE_NA, and ast_dsp::progmode.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

00890 {
00891    int x;
00892    int y;
00893    int pass;
00894    int newstate = DSP_TONE_STATE_SILENCE;
00895    int res = 0;
00896    while (len) {
00897       /* Take the lesser of the number of samples we need and what we have */
00898       pass = len;
00899       if (pass > dsp->gsamp_size - dsp->gsamps) 
00900          pass = dsp->gsamp_size - dsp->gsamps;
00901       for (x=0;x<pass;x++) {
00902          for (y=0;y<dsp->freqcount;y++) 
00903             goertzel_sample(&dsp->freqs[y], s[x]);
00904          dsp->genergy += s[x] * s[x];
00905       }
00906       s += pass;
00907       dsp->gsamps += pass;
00908       len -= pass;
00909       if (dsp->gsamps == dsp->gsamp_size) {
00910          float hz[7];
00911          for (y=0;y<7;y++)
00912             hz[y] = goertzel_result(&dsp->freqs[y]);
00913          switch (dsp->progmode) {
00914          case PROG_MODE_NA:
00915             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
00916                newstate = DSP_TONE_STATE_BUSY;
00917             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
00918                newstate = DSP_TONE_STATE_RINGING;
00919             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
00920                newstate = DSP_TONE_STATE_DIALTONE;
00921             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
00922                newstate = DSP_TONE_STATE_SPECIAL1;
00923             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
00924                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
00925                   newstate = DSP_TONE_STATE_SPECIAL2;
00926             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
00927                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
00928                   newstate = DSP_TONE_STATE_SPECIAL3;
00929             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
00930                newstate = DSP_TONE_STATE_TALKING;
00931             } else
00932                newstate = DSP_TONE_STATE_SILENCE;
00933             break;
00934          case PROG_MODE_CR:
00935             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
00936                newstate = DSP_TONE_STATE_RINGING;
00937             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
00938                newstate = DSP_TONE_STATE_TALKING;
00939             } else
00940                newstate = DSP_TONE_STATE_SILENCE;
00941             break;
00942          case PROG_MODE_UK:
00943             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
00944                newstate = DSP_TONE_STATE_HUNGUP;
00945             }
00946             break;
00947          default:
00948             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
00949          }
00950          if (newstate == dsp->tstate) {
00951             dsp->tcount++;
00952             if (dsp->ringtimeout)
00953                dsp->ringtimeout++;
00954             switch (dsp->tstate) {
00955                case DSP_TONE_STATE_RINGING:
00956                   if ((dsp->features & DSP_PROGRESS_RINGING) &&
00957                       (dsp->tcount==THRESH_RING)) {
00958                      res = AST_CONTROL_RINGING;
00959                      dsp->ringtimeout= 1;
00960                   }
00961                   break;
00962                case DSP_TONE_STATE_BUSY:
00963                   if ((dsp->features & DSP_PROGRESS_BUSY) &&
00964                       (dsp->tcount==THRESH_BUSY)) {
00965                      res = AST_CONTROL_BUSY;
00966                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
00967                   }
00968                   break;
00969                case DSP_TONE_STATE_TALKING:
00970                   if ((dsp->features & DSP_PROGRESS_TALK) &&
00971                       (dsp->tcount==THRESH_TALK)) {
00972                      res = AST_CONTROL_ANSWER;
00973                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
00974                   }
00975                   break;
00976                case DSP_TONE_STATE_SPECIAL3:
00977                   if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
00978                       (dsp->tcount==THRESH_CONGESTION)) {
00979                      res = AST_CONTROL_CONGESTION;
00980                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
00981                   }
00982                   break;
00983                case DSP_TONE_STATE_HUNGUP:
00984                   if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
00985                       (dsp->tcount==THRESH_HANGUP)) {
00986                      res = AST_CONTROL_HANGUP;
00987                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
00988                   }
00989                   break;
00990             }
00991             if (dsp->ringtimeout==THRESH_RING2ANSWER) {
00992                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
00993                res = AST_CONTROL_ANSWER;
00994                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
00995             }
00996          } else {
00997             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
00998             ast_debug(5, "Start state %d\n", newstate);
00999             dsp->tstate = newstate;
01000             dsp->tcount = 1;
01001          }
01002          
01003          /* Reset goertzel */                
01004          for (x=0;x<7;x++)
01005             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01006          dsp->gsamps = 0;
01007          dsp->genergy = 0.0;
01008       }
01009    }
01010 
01011    return res;
01012 }

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

Definition at line 811 of file dsp.c.

References ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dtmf_detect(), ast_dsp::faxmode, ast_dsp::features, mf_detect(), store_digit(), and tone_detect().

Referenced by ast_dsp_digitdetect(), and ast_dsp_process().

00812 {
00813    int res = 0;
00814    
00815    if ((dsp->features & DSP_FEATURE_DTMF_DETECT) && (dsp->digitmode & DSP_DIGITMODE_MF))
00816       res = mf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00817    else if (dsp->features & DSP_FEATURE_DTMF_DETECT)
00818       res = dtmf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
00819 
00820    if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CNG)) {
00821       if (tone_detect(&dsp->cng_tone_state, s, len, NULL)) {
00822          store_digit(&dsp->digit_state, 'f');
00823          res = 'f';
00824       }
00825    }
00826 
00827    if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CED)) {
00828       if (tone_detect(&dsp->ced_tone_state, s, len, NULL)) {
00829          store_digit(&dsp->digit_state, 'e');
00830          res = 'e';
00831       }
00832    }
00833 
00834    return res;
00835 }

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

Definition at line 1027 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

01028 {
01029    int accum;
01030    int x;
01031    int res = 0;
01032 
01033    if (!len)
01034       return 0;
01035    accum = 0;
01036    for (x=0;x<len; x++) 
01037       accum += abs(s[x]);
01038    accum /= len;
01039    if (accum < dsp->threshold) {
01040       /* Silent */
01041       dsp->totalsilence += len/8;
01042 #ifdef DEBUG_DSP_BUSYDETECT
01043       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01044 #endif
01045       if (dsp->totalnoise) {
01046          /* Move and save history */
01047          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicnoise[0]));
01048          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01049          /* check if previous tone differs BUSY_PERCENT from the one before it */
01050          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01051          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01052          if (tone1 < tone2) {
01053            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01054                dsp->busymaybe = 1;
01055            else
01056                dsp->busymaybe = 0;
01057          } else {
01058            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01059                dsp->busymaybe = 1;
01060             else
01061                dsp->busymaybe = 0;
01062          }
01063       }
01064       dsp->totalnoise = 0;
01065       res = 1;
01066    } else {
01067       /* Not silent */
01068       dsp->totalnoise += len/8;
01069 #ifdef DEBUG_DSP_BUSYDETECT
01070       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01071 #endif     
01072       if (dsp->totalsilence) {
01073          /* Move and save history */
01074          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicsilence[0]));
01075          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01076       }
01077       dsp->totalsilence = 0;
01078    }
01079    if (totalsilence)
01080       *totalsilence = dsp->totalsilence;
01081    return res;
01082 }

static void ast_digit_detect_init ( digit_detect_state_t s,
int  mf 
) [static]

Definition at line 445 of file dsp.c.

References ast_dtmf_detect_init(), ast_mf_detect_init(), and s.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

00446 {
00447    s->current_digits = 0;
00448    s->detected_digits = 0;
00449    s->lost_digits = 0;
00450    s->digits[0] = '\0';
00451 
00452    if (mf)
00453       ast_mf_detect_init(&s->td.mf);
00454    else
00455       ast_dtmf_detect_init(&s->td.dtmf);
00456 }

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

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

Referenced by ast_dsp_process().

01085 {
01086    int res = 0, x;
01087    int avgsilence = 0, hitsilence = 0;
01088    int avgtone = 0, hittone = 0;
01089 #ifdef DEBUG_DSP_BUSYDETECT
01090    char buf[16];
01091    char silence_list[64]="", tone_list[64]="";
01092 #endif
01093    
01094    if (!dsp->busymaybe)
01095       return res;
01096    dsp->busymaybe = 0;
01097 
01098    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01099       avgsilence += dsp->historicsilence[x];
01100       avgtone += dsp->historicnoise[x];
01101    }
01102    avgsilence /= dsp->busycount;
01103    avgtone /= dsp->busycount;
01104 #ifdef DEBUG_DSP_BUSYDETECT
01105    sprintf(silence_list,"Silences: ");
01106    sprintf(tone_list,"Tones:    ");
01107 #endif
01108    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01109 #ifdef DEBUG_DSP_BUSYDETECT
01110       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01111       strcat(silence_list, buf);
01112       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01113       strcat(tone_list, buf); 
01114 #endif
01115       if (!dsp->busytoneonly) {
01116          if (avgsilence > dsp->historicsilence[x]) {
01117             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01118                hitsilence++;
01119          } else {
01120             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01121                hitsilence++;
01122          }
01123       }
01124       if (avgtone > dsp->historicnoise[x]) {
01125          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01126             hittone++;
01127       } else {
01128          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01129             hittone++;
01130       }
01131    }
01132 #ifdef DEBUG_DSP_BUSYDETECT
01133    fprintf(stderr, "BUSY DETECTOR\n");   
01134    fprintf(stderr, "%s\n", tone_list);
01135    fprintf(stderr, "%s\n", silence_list)
01136 #endif
01137    if ((dsp->busytoneonly || 
01138        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01139       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01140       if (dsp->busycompare) {
01141            if (dsp->busytoneonly) {
01142              res = 1;
01143             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01144          } else {
01145               if (avgtone > avgsilence) {
01146                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01147                     res = 1;
01148             } else {
01149                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01150                    res = 1;
01151             }
01152          }
01153       } else {
01154          res = 1;
01155       }
01156    }
01157    /* If we know the expected busy tone length, check we are in the range */
01158    if (res && (dsp->busy_tonelength > 0)) {
01159       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01160 #ifdef BUSYDETECT_DEBUG
01161          if(option_debug) {
01162             ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength);
01163          }
01164 #endif
01165          res = 0;
01166       }
01167    }
01168    /* If we know the expected busy tone silent-period length, check we are in the range */
01169    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01170       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01171 #ifdef BUSYDETECT_DEBUG
01172          if(option_debug) {
01173             ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength);
01174          }
01175 #endif
01176          res = 0;
01177       }
01178    }
01179    if (res) {
01180       if (option_debug)
01181          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01182    } else {
01183       if (option_debug)
01184          ast_log(LOG_NOTICE, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01185    }
01186    return res;
01187 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01015 {
01016    if (inf->frametype != AST_FRAME_VOICE) {
01017       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01018       return 0;
01019    }
01020    if (inf->subclass != AST_FORMAT_SLINEAR) {
01021       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01022       return 0;
01023    }
01024    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01025 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

00838 {
00839    short *s;
00840    int len;
00841    int ign=0;
00842 
00843    if (inf->frametype != AST_FRAME_VOICE) {
00844       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
00845       return 0;
00846    }
00847    if (inf->subclass != AST_FORMAT_SLINEAR) {
00848       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
00849       return 0;
00850    }
00851    s = inf->data;
00852    len = inf->datalen / 2;
00853    return __ast_dsp_digitdetect(dsp, s, len, &ign);
00854 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1541 of file dsp.c.

References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.

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

01542 {
01543    int new;
01544    int old;
01545    
01546    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01547    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01548    if (old != new) {
01549       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01550       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01551    }
01552    dsp->digitmode = digitmode;
01553    return 0;
01554 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1499 of file dsp.c.

References digit_detect_state_t::current_digits, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, goertzel_reset(), digit_detect_state_t::mf, s, digit_detect_state_t::td, and ast_dsp::thinkdigit.

Referenced by ss_thread().

01500 {
01501    int i;
01502    
01503    dsp->thinkdigit = 0;
01504    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01505       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01506       /* Reinitialise the detector for the next block */
01507       for (i = 0;  i < 6;  i++) {
01508          goertzel_reset(&s->tone_out[i]);
01509       }
01510       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01511       s->current_sample = 0;
01512    } else {
01513       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01514       /* Reinitialise the detector for the next block */
01515       for (i = 0;  i < 4;  i++) {
01516          goertzel_reset(&s->row_out[i]);
01517          goertzel_reset(&s->col_out[i]);
01518       }
01519       s->lasthit = s->current_hit = 0;
01520       s->energy = 0.0;
01521       s->current_sample = 0;
01522    }
01523 
01524    dsp->digit_state.digits[0] = '\0';
01525    dsp->digit_state.current_digits = 0;
01526 }

void ast_dsp_frame_freed ( struct ast_frame fr  ) 

Hint that a frame from a dsp was freed.

This is called from ast_frame_free if AST_FRFLAG_FROM_DSP is set. This occurs because it is possible for the dsp to be freed while someone still holds a reference to the frame that is in that dsp. This has been known to happen when the dsp on a DAHDI channel detects a busy signal. The channel is hung up, and the application that read the frame to begin with still has a reference to the frame.

Returns:
nothing

Definition at line 1589 of file dsp.c.

References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, f, and ast_dsp::freqcount.

Referenced by __frame_free().

01590 {
01591    struct ast_dsp *dsp;
01592 
01593    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01594 
01595    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01596 
01597    if (dsp->freqcount != -1)
01598       return;
01599    
01600    ast_dsp_free(dsp);
01601 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1446 of file dsp.c.

References ast_free, AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::f, and ast_dsp::freqcount.

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

01447 {
01448    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01449       /* If this flag is still set, that means that the dsp's destruction 
01450        * been torn down, while we still have a frame out there being used.
01451        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01452        * will get destroyed, too. */
01453 
01454       /* Set the magic flag to destroy the dsp when the frame is freed */
01455       dsp->freqcount = -1;
01456 
01457       return;
01458    }
01459    ast_free(dsp);
01460 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1584 of file dsp.c.

References ast_dsp::tcount.

01585 {
01586    return dsp->tcount;
01587 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1579 of file dsp.c.

References ast_dsp::tstate.

01580 {
01581    return dsp->tstate;
01582 }

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

Get pending DTMF/MF digits.

Definition at line 876 of file dsp.c.

References digit_detect_state_t::current_digits, ast_dsp::digit_state, and digit_detect_state_t::digits.

00877 {
00878    if (max > dsp->digit_state.current_digits)
00879       max = dsp->digit_state.current_digits;
00880    if (max > 0) {
00881       memcpy(buf, dsp->digit_state.digits, max);
00882       memmove(dsp->digit_state.digits, dsp->digit_state.digits + max, dsp->digit_state.current_digits - max);
00883       dsp->digit_state.current_digits -= max;
00884    }
00885    buf[max] = '\0';
00886    return  max;
00887 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1407 of file dsp.c.

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and ast_dsp::threshold.

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

01408 {
01409    struct ast_dsp *dsp;
01410    
01411    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01412       dsp->threshold = DEFAULT_THRESHOLD;
01413       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01414       dsp->busycount = DSP_HISTORY;
01415       dsp->digitmode = DSP_DIGITMODE_DTMF;
01416       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01417       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01418 #ifdef BUSYDETECT_TONEONLY
01419       dsp->busytoneonly = 1;
01420 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01421 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01422 #endif
01423 #else
01424    dsp->busytoneonly = 0;
01425 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01426    dsp->busycompare = 1;
01427 #else
01428    dsp->busycompare = 0;
01429 #endif
01430 #endif
01431       /* Initialize digit detector */
01432       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01433       /* Initialize initial DSP progress detect parameters */
01434       ast_dsp_prog_reset(dsp);
01435       /* Initialize fax detector */
01436       ast_fax_detect_init(dsp);
01437    }
01438    return dsp;
01439 }

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 1207 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_debug, 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_FRFLAG_FROM_DSP, ast_frfree, ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, chan, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len(), LOG_WARNING, ast_channel::name, ast_frame::src, ast_frame::subclass, and ast_dsp::thinkdigit.

Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), transmit_audio(), and usbradio_read().

01208 {
01209    int silence;
01210    int res;
01211    int digit;
01212    int x;
01213    short *shortdata;
01214    unsigned char *odata;
01215    int len;
01216    int writeback = 0;
01217 
01218 #define FIX_INF(inf) do { \
01219       if (writeback) { \
01220          switch (inf->subclass) { \
01221          case AST_FORMAT_SLINEAR: \
01222             break; \
01223          case AST_FORMAT_ULAW: \
01224             for (x=0;x<len;x++) \
01225                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01226             break; \
01227          case AST_FORMAT_ALAW: \
01228             for (x=0;x<len;x++) \
01229                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01230             break; \
01231          } \
01232       } \
01233    } while(0) 
01234 
01235    if (!af)
01236       return NULL;
01237    if (af->frametype != AST_FRAME_VOICE)
01238       return af;
01239    odata = af->data;
01240    len = af->datalen;
01241    /* Make sure we have short data */
01242    switch (af->subclass) {
01243    case AST_FORMAT_SLINEAR:
01244       shortdata = af->data;
01245       len = af->datalen / 2;
01246       break;
01247    case AST_FORMAT_ULAW:
01248       shortdata = alloca(af->datalen * 2);
01249       for (x = 0;x < len; x++) 
01250          shortdata[x] = AST_MULAW(odata[x]);
01251       break;
01252    case AST_FORMAT_ALAW:
01253       shortdata = alloca(af->datalen * 2);
01254       for (x = 0; x < len; x++) 
01255          shortdata[x] = AST_ALAW(odata[x]);
01256       break;
01257    default:
01258       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01259       return af;
01260    }
01261    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01262    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01263       memset(&dsp->f, 0, sizeof(dsp->f));
01264       dsp->f.frametype = AST_FRAME_NULL;
01265       ast_frfree(af);
01266       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01267       return &dsp->f;
01268    }
01269    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01270       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01271       memset(&dsp->f, 0, sizeof(dsp->f));
01272       dsp->f.frametype = AST_FRAME_CONTROL;
01273       dsp->f.subclass = AST_CONTROL_BUSY;
01274       ast_frfree(af);
01275       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01276       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01277       return &dsp->f;
01278    }
01279    if (((dsp->features & DSP_FEATURE_DTMF_DETECT) || (dsp->features & DSP_FEATURE_FAX_DETECT))) {
01280       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01281 #if 0
01282       if (digit)
01283          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01284 #endif
01285       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01286          if (!dsp->thinkdigit) {
01287             if (digit) {
01288                /* Looks like we might have something.  
01289                 * Request a conference mute for the moment */
01290                memset(&dsp->f, 0, sizeof(dsp->f));
01291                dsp->f.frametype = AST_FRAME_DTMF;
01292                dsp->f.subclass = 'm';
01293                dsp->thinkdigit = 'x';
01294                FIX_INF(af);
01295                if (chan)
01296                   ast_queue_frame(chan, af);
01297                ast_frfree(af);
01298                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01299                return &dsp->f;
01300             }
01301          } else {
01302             if (digit) {
01303                /* Thought we saw one last time.  Pretty sure we really have now */
01304                if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01305                   /* If we found a digit, and we're changing digits, go
01306                      ahead and send this one, but DON'T stop confmute because
01307                      we're detecting something else, too... */
01308                   memset(&dsp->f, 0, sizeof(dsp->f));
01309                   dsp->f.frametype = AST_FRAME_DTMF_END;
01310                   dsp->f.subclass = dsp->thinkdigit;
01311                   FIX_INF(af);
01312                   if (chan)
01313                      ast_queue_frame(chan, af);
01314                   ast_frfree(af);
01315                } else {
01316                   dsp->thinkdigit = digit;
01317                   memset(&dsp->f, 0, sizeof(dsp->f));
01318                   dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
01319                   dsp->f.subclass = dsp->thinkdigit;
01320                   FIX_INF(af);
01321                   if (chan)
01322                      ast_queue_frame(chan, af);
01323                   ast_frfree(af);
01324                }
01325                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01326                return &dsp->f;
01327             } else {
01328                memset(&dsp->f, 0, sizeof(dsp->f));
01329                if (dsp->thinkdigit != 'x') {
01330                   /* If we found a digit, send it now */
01331                   dsp->f.frametype = AST_FRAME_DTMF_END;
01332                   dsp->f.subclass = dsp->thinkdigit;
01333                   dsp->thinkdigit = 0;
01334                } else {
01335                   dsp->f.frametype = AST_FRAME_DTMF;
01336                   dsp->f.subclass = 'u';
01337                   dsp->thinkdigit = 0;
01338                }
01339                FIX_INF(af);
01340                if (chan)
01341                   ast_queue_frame(chan, af);
01342                ast_frfree(af);
01343                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01344                return &dsp->f;
01345             }
01346          }
01347       } else if (dsp->digit_state.current_digits > 1 ||
01348          (dsp->digit_state.current_digits == 1 && digit != dsp->digit_state.digits[0])) {
01349          /* Since we basically generate DTMF_END frames we do it only when a digit
01350             has finished. */
01351 
01352          memset(&dsp->f, 0, sizeof(dsp->f));
01353          dsp->f.frametype = AST_FRAME_DTMF;
01354          dsp->f.subclass = dsp->digit_state.digits[0];
01355          memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits);
01356          dsp->digit_state.current_digits--;
01357          FIX_INF(af);
01358          if (chan)
01359             ast_queue_frame(chan, af);
01360          ast_frfree(af);
01361          ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01362          return &dsp->f;
01363       }
01364    }
01365    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01366       res = __ast_dsp_call_progress(dsp, shortdata, len);
01367       if (res) {
01368          switch (res) {
01369          case AST_CONTROL_ANSWER:
01370          case AST_CONTROL_BUSY:
01371          case AST_CONTROL_RINGING:
01372          case AST_CONTROL_CONGESTION:
01373          case AST_CONTROL_HANGUP:
01374             memset(&dsp->f, 0, sizeof(dsp->f));
01375             dsp->f.frametype = AST_FRAME_CONTROL;
01376             dsp->f.subclass = res;
01377             dsp->f.src = "dsp_progress";
01378             if (chan) 
01379                ast_queue_frame(chan, &dsp->f);
01380             break;
01381          default:
01382             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01383          }
01384       }
01385    }
01386    FIX_INF(af);
01387    return af;
01388 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1390 of file dsp.c.

References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::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().

01391 {
01392    int max = 0;
01393    int x;
01394    
01395    dsp->gsamp_size = modes[dsp->progmode].size;
01396    dsp->gsamps = 0;
01397    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01398       if (modes[dsp->progmode].freqs[x]) {
01399          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01400          max = x + 1;
01401       }
01402    }
01403    dsp->freqcount = max;
01404    dsp->ringtimeout= 0;
01405 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01529 {
01530    int x;
01531    
01532    dsp->totalsilence = 0;
01533    dsp->gsamps = 0;
01534    for (x=0;x<4;x++)
01535       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01536    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01537    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01538    dsp->ringtimeout= 0;
01539 }

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

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

Definition at line 1479 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

01480 {
01481   if (compare > 0)
01482       dsp->busycompare = 1;
01483   else
01484       dsp->busycompare = 0;
01485 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1470 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01471 {
01472    if (cadences < 4)
01473       cadences = 4;
01474    if (cadences > DSP_HISTORY)
01475       cadences = DSP_HISTORY;
01476    dsp->busycount = cadences;
01477 }

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

Set expected lengths of the busy tones.

Definition at line 1487 of file dsp.c.

References ast_debug, ast_dsp::busy_pattern_fuzzy, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and ast_dsp::busytoneonly.

Referenced by dahdi_new().

01488 {
01489    dsp->busy_tonelength = tonelength;
01490    if (quietlength > 0)
01491       dsp->busy_quietlength = quietlength;
01492    else 
01493      dsp->busytoneonly = 1;
01494    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01495    if( fuzzy > 0 && fuzzy < 50 ) 
01496       dsp->busy_pattern_fuzzy = fuzzy;
01497 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1565 of file dsp.c.

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

Referenced by dahdi_new().

01566 {
01567    int x;
01568    
01569    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01570       if (!strcasecmp(aliases[x].name, zone)) {
01571          dsp->progmode = aliases[x].mode;
01572          ast_dsp_prog_reset(dsp);
01573          return 0;
01574       }
01575    }
01576    return -1;
01577 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1556 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by transmit_audio().

01557 {
01558    if (dsp->faxmode != faxmode) {
01559       ast_fax_detect_init(dsp);
01560    }
01561    dsp->faxmode = faxmode;
01562    return 0;
01563 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1441 of file dsp.c.

References ast_dsp::features.

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

01442 {
01443    dsp->features = features;
01444 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1462 of file dsp.c.

References ast_dsp::threshold.

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

01463 {
01464    if (threshold < 256)
01465      dsp->threshold = 256;
01466    else
01467      dsp->threshold = threshold;
01468 }

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

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

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

01190 {
01191    short *s;
01192    int len;
01193    
01194    if (f->frametype != AST_FRAME_VOICE) {
01195       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01196       return 0;
01197    }
01198    if (f->subclass != AST_FORMAT_SLINEAR) {
01199       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01200       return 0;
01201    }
01202    s = f->data;
01203    len = f->datalen/2;
01204    return __ast_dsp_silence(dsp, s, len, totalsilence);
01205 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 420 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_digit_detect_init().

00421 {
00422    int i;
00423 
00424    s->lasthit = 0;
00425    s->current_hit = 0;
00426    for (i = 0;  i < 4;  i++) {
00427       goertzel_init (&s->row_out[i], dtmf_row[i], 102);
00428       goertzel_init (&s->col_out[i], dtmf_col[i], 102);
00429       s->energy = 0.0;
00430    }
00431    s->current_sample = 0;
00432 }

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

Definition at line 414 of file dsp.c.

References ast_tone_detect_init(), FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_FREQ, and s.

Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 434 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_digit_detect_init().

00435 {
00436    int i;
00437    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00438    for (i = 0;  i < 6;  i++) {
00439       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00440    }
00441    s->current_sample = 0;
00442    s->current_hit = 0;
00443 }

static void ast_tone_detect_init ( tone_detect_state_t s,
int  freq,
int  duration,
int  amp 
) [static]

Definition at line 354 of file dsp.c.

References ast_debug, goertzel_init(), s, SAMPLE_RATE, and SAMPLES_IN_FRAME.

Referenced by ast_fax_detect_init().

00355 {
00356    int duration_samples;
00357    float x;
00358    int periods_in_block;
00359 
00360    s->freq = freq;
00361 
00362    /* Desired tone duration in samples */
00363    duration_samples = duration * SAMPLE_RATE / 1000;
00364    /* We want to allow 10% deviation of tone duration */
00365    duration_samples = duration_samples * 9 / 10;
00366 
00367    /* If we want to remove tone, it is important to have block size not
00368       to exceed frame size. Otherwise by the moment tone is detected it is too late
00369       to squelch it from previous frames */
00370    s->block_size = SAMPLES_IN_FRAME;
00371 
00372    periods_in_block = s->block_size * freq / SAMPLE_RATE;
00373 
00374    /* Make sure we will have at least 5 periods at target frequency for analisys.
00375       This may make block larger than expected packet and will make squelching impossible
00376       but at least we will be detecting the tone */
00377    if (periods_in_block < 5)
00378       periods_in_block = 5;
00379 
00380    /* Now calculate final block size. It will contain integer number of periods */
00381    s->block_size = periods_in_block * SAMPLE_RATE / freq;
00382 
00383    /* tone_detect is currently only used to detect fax tones and we
00384       do not need suqlching the fax tones */
00385    s->squelch = 0;
00386 
00387    /* Account for the first and the last block to be incomplete
00388       and thus no tone will be detected in them */
00389    s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
00390 
00391    goertzel_init(&s->tone, freq, s->block_size);
00392 
00393    s->samples_pending = s->block_size;
00394    s->hit_count = 0;
00395    s->last_hit = 0;
00396    s->energy = 0.0;
00397 
00398    /* We want tone energy to be amp decibels above the rest of the signal (the noise).
00399       According to Parseval's theorem the energy computed in time domain equals to energy
00400       computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
00401       from the energy in the time domain we will get energy of the remaining signal (without the tone
00402       we are detecting). We will be checking that
00403       10*log(Ew / (Et - Ew)) > amp
00404       Calculate threshold so that we will be actually checking
00405       Ew > Et * threshold
00406    */
00407 
00408    x = pow(10.0, amp / 10.0);
00409    s->threshold = x / (x + 1);
00410 
00411    ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
00412 }

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

Definition at line 561 of file dsp.c.

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

Referenced by __ast_dsp_digitdetect().

00563 {
00564    float row_energy[4];
00565    float col_energy[4];
00566    float famp;
00567    int i;
00568    int j;
00569    int sample;
00570    int best_row;
00571    int best_col;
00572    int hit;
00573    int limit;
00574 
00575    hit = 0;
00576    for (sample = 0;  sample < samples;  sample = limit) {
00577       /* 102 is optimised to meet the DTMF specs. */
00578       if ((samples - sample) >= (102 - s->td.dtmf.current_sample))
00579          limit = sample + (102 - s->td.dtmf.current_sample);
00580       else
00581          limit = samples;
00582       /* The following unrolled loop takes only 35% (rough estimate) of the 
00583          time of a rolled loop on the machine on which it was developed */
00584       for (j = sample; j < limit; j++) {
00585          famp = amp[j];
00586          s->td.dtmf.energy += famp*famp;
00587          /* With GCC 2.95, the following unrolled code seems to take about 35%
00588             (rough estimate) as long as a neat little 0-3 loop */
00589          goertzel_sample(s->td.dtmf.row_out, amp[j]);
00590          goertzel_sample(s->td.dtmf.col_out, amp[j]);
00591          goertzel_sample(s->td.dtmf.row_out + 1, amp[j]);
00592          goertzel_sample(s->td.dtmf.col_out + 1, amp[j]);
00593          goertzel_sample(s->td.dtmf.row_out + 2, amp[j]);
00594          goertzel_sample(s->td.dtmf.col_out + 2, amp[j]);
00595          goertzel_sample(s->td.dtmf.row_out + 3, amp[j]);
00596          goertzel_sample(s->td.dtmf.col_out + 3, amp[j]);
00597       }
00598       s->td.dtmf.current_sample += (limit - sample);
00599       if (s->td.dtmf.current_sample < 102) {
00600          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00601             /* If we had a hit last time, go ahead and clear this out since likely it
00602                will be another hit */
00603             for (i=sample;i<limit;i++) 
00604                amp[i] = 0;
00605             *writeback = 1;
00606          }
00607          continue;
00608       }
00609       /* We are at the end of a DTMF detection block */
00610       /* Find the peak row and the peak column */
00611       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00612       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00613 
00614       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00615          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00616          if (row_energy[i] > row_energy[best_row])
00617             best_row = i;
00618          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00619          if (col_energy[i] > col_energy[best_col])
00620             best_col = i;
00621       }
00622       hit = 0;
00623       /* Basic signal level test and the twist test */
00624       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00625           col_energy[best_col] >= DTMF_THRESHOLD &&
00626           col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
00627           col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
00628          /* Relative peak test */
00629          for (i = 0;  i < 4;  i++) {
00630             if ((i != best_col &&
00631                 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00632                 (i != best_row 
00633                  && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00634                break;
00635             }
00636          }
00637          /* ... and fraction of total energy test */
00638          if (i >= 4 &&
00639              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy) {
00640             /* Got a hit */
00641             hit = dtmf_positions[(best_row << 2) + best_col];
00642             if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
00643                /* Zero out frame data if this is part DTMF */
00644                for (i=sample;i<limit;i++) 
00645                   amp[i] = 0;
00646                *writeback = 1;
00647             }
00648          }
00649       } 
00650 
00651       /* The logic in the next test is:
00652          For digits we need two successive identical clean detects, with
00653          something different preceeding it. This can work with
00654          back to back differing digits. More importantly, it
00655          can work with nasty phones that give a very wobbly start
00656          to a digit */
00657       if (hit != s->td.dtmf.current_hit) {
00658          if (hit && s->td.dtmf.lasthit == hit) {
00659             s->td.dtmf.current_hit = hit;
00660             store_digit(s, hit);
00661          } else if (s->td.dtmf.lasthit != s->td.dtmf.current_hit) {
00662             s->td.dtmf.current_hit = 0;
00663          }
00664       }
00665       s->td.dtmf.lasthit = hit;
00666 
00667       /* Reinitialise the detector for the next block */
00668       for (i = 0;  i < 4;  i++) {
00669          goertzel_reset(&s->td.dtmf.row_out[i]);
00670          goertzel_reset(&s->td.dtmf.col_out[i]);
00671       }
00672       s->td.dtmf.energy = 0.0;
00673       s->td.dtmf.current_sample = 0;
00674    }
00675    return (s->td.dtmf.current_hit); /* return the debounced hit */
00676 }

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

Definition at line 310 of file dsp.c.

References cos, s, and SAMPLE_RATE.

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

00311 {
00312    s->v2 = s->v3 = s->chunky = 0.0;
00313    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00314    s->samples = samples;
00315 }

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

Definition at line 317 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset().

00318 {
00319    s->v2 = s->v3 = s->chunky = 0.0;
00320 }

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

Definition at line 301 of file dsp.c.

References goertzel_result_t::power, s, and goertzel_result_t::value.

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

00302 {
00303    goertzel_result_t r;
00304    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00305    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00306    r.power = s->chunky * 2;
00307    return (float)r.value * (float)(1 << r.power);
00308 }

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

Definition at line 275 of file dsp.c.

References s.

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

00276 {
00277    int v1;
00278    
00279    v1 = s->v2;
00280    s->v2 = s->v3;
00281    
00282    s->v3 = (s->fac * s->v2) >> 15;
00283    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00284    if (abs(s->v3) > 32768) {
00285       s->chunky++;
00286       s->v3 = s->v3 >> 1;
00287       s->v2 = s->v2 >> 1;
00288       v1 = v1 >> 1;
00289    }
00290 }

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

Definition at line 292 of file dsp.c.

References goertzel_sample(), and s.

00293 {
00294    int i;
00295    
00296    for (i=0;i<count;i++) 
00297       goertzel_sample(s, samps[i]);
00298 }

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

Definition at line 681 of file dsp.c.

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, DSP_DIGITMODE_NOQUELCH, goertzel_result(), goertzel_sample(), MF_GSIZE, s, and store_digit().

Referenced by __ast_dsp_digitdetect().

00683 {
00684    float energy[6];
00685    int best;
00686    int second_best;
00687    float famp;
00688    int i;
00689    int j;
00690    int sample;
00691    int hit;
00692    int limit;
00693 
00694    hit = 0;
00695    for (sample = 0;  sample < samples;  sample = limit) {
00696       /* 80 is optimised to meet the MF specs. */
00697       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample))
00698          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00699       else
00700          limit = samples;
00701       /* The following unrolled loop takes only 35% (rough estimate) of the 
00702          time of a rolled loop on the machine on which it was developed */
00703       for (j = sample;  j < limit;  j++) {
00704          famp = amp[j];
00705          /* With GCC 2.95, the following unrolled code seems to take about 35%
00706             (rough estimate) as long as a neat little 0-3 loop */
00707          goertzel_sample(s->td.mf.tone_out, amp[j]);
00708          goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
00709          goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
00710          goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
00711          goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
00712          goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
00713       }
00714       s->td.mf.current_sample += (limit - sample);
00715       if (s->td.mf.current_sample < MF_GSIZE) {
00716          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
00717             /* If we had a hit last time, go ahead and clear this out since likely it
00718                will be another hit */
00719             for (i=sample;i<limit;i++) 
00720                amp[i] = 0;
00721             *writeback = 1;
00722          }
00723          continue;
00724       }
00725       /* We're at the end of an MF detection block.  */
00726       /* Find the two highest energies. The spec says to look for
00727          two tones and two tones only. Taking this literally -ie
00728          only two tones pass the minimum threshold - doesn't work
00729          well. The sinc function mess, due to rectangular windowing
00730          ensure that! Find the two highest energies and ensure they
00731          are considerably stronger than any of the others. */
00732       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00733       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00734       if (energy[0] > energy[1]) {
00735          best = 0;
00736          second_best = 1;
00737       } else {
00738          best = 1;
00739          second_best = 0;
00740       }
00741       /*endif*/
00742       for (i=2;i<6;i++) {
00743          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00744          if (energy[i] >= energy[best]) {
00745             second_best = best;
00746             best = i;
00747          } else if (energy[i] >= energy[second_best]) {
00748             second_best = i;
00749          }
00750       }
00751       /* Basic signal level and twist tests */
00752       hit = 0;
00753       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00754                && energy[best] < energy[second_best]*BELL_MF_TWIST
00755                && energy[best]*BELL_MF_TWIST > energy[second_best]) {
00756          /* Relative peak test */
00757          hit = -1;
00758          for (i=0;i<6;i++) {
00759             if (i != best && i != second_best) {
00760                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00761                   /* The best two are not clearly the best */
00762                   hit = 0;
00763                   break;
00764                }
00765             }
00766          }
00767       }
00768       if (hit) {
00769          /* Get the values into ascending order */
00770          if (second_best < best) {
00771             i = best;
00772             best = second_best;
00773             second_best = i;
00774          }
00775          best = best*5 + second_best - 1;
00776          hit = bell_mf_positions[best];
00777          /* Look for two successive similar results */
00778          /* The logic in the next test is:
00779             For KP we need 4 successive identical clean detects, with
00780             two blocks of something different preceeding it. For anything
00781             else we need two successive identical clean detects, with
00782             two blocks of something different preceeding it. */
00783          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00784             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00785              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00786              hit != s->td.mf.hits[0]))) {
00787             store_digit(s, hit);
00788          }
00789       }
00790 
00791 
00792       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00793          /* Two successive block without a hit terminate current digit */
00794          s->td.mf.current_hit = 0;
00795       }
00796 
00797       s->td.mf.hits[0] = s->td.mf.hits[1];
00798       s->td.mf.hits[1] = s->td.mf.hits[2];
00799       s->td.mf.hits[2] = s->td.mf.hits[3];
00800       s->td.mf.hits[3] = s->td.mf.hits[4];
00801       s->td.mf.hits[4] = hit;
00802       /* Reinitialise the detector for the next block */
00803       for (i = 0;  i < 6;  i++)
00804          goertzel_reset(&s->td.mf.tone_out[i]);
00805       s->td.mf.current_sample = 0;
00806    }
00807 
00808    return (s->td.mf.current_hit); /* return the debounced hit */
00809 }

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

Definition at line 856 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

00857 {
00858    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00859    /* Make sure absolute levels are high enough */
00860    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
00861       return 0;
00862    /* Amplify ignored stuff */
00863    i2 *= TONE_THRESH;
00864    i1 *= TONE_THRESH;
00865    e *= TONE_THRESH;
00866    /* Check first tone */
00867    if ((p1 < i1) || (p1 < i2) || (p1 < e))
00868       return 0;
00869    /* And second */
00870    if ((p2 < i1) || (p2 < i2) || (p2 < e))
00871       return 0;
00872    /* Guess it's there... */
00873    return 1;
00874 }

static void store_digit ( digit_detect_state_t s,
char  digit 
) [static]

Definition at line 549 of file dsp.c.

References ast_log(), LOG_WARNING, MAX_DTMF_DIGITS, and s.

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

00550 {
00551    s->detected_digits++;
00552    if (s->current_digits < MAX_DTMF_DIGITS) {
00553       s->digits[s->current_digits++] = digit;
00554       s->digits[s->current_digits] = '\0';
00555    } else {
00556       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00557       s->lost_digits++;
00558    }
00559 }

static int tone_detect ( tone_detect_state_t s,
int16_t *  amp,
int  samples,
int *  writeback 
) [static]

Definition at line 458 of file dsp.c.

References goertzel_sample(), and s.

Referenced by __ast_dsp_digitdetect().

00460 {
00461    float tone_energy;
00462    int i;
00463    int hit = 0;
00464    int limit;
00465    int res = 0;
00466    int16_t *ptr;
00467 
00468    while (1) {
00469       /* Process in blocks. */
00470       limit = (samples < s->samples_pending) ? samples : s->samples_pending;
00471 
00472       for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
00473          /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */
00474          s->energy += (int32_t) *ptr * (int32_t) *ptr;
00475 
00476          goertzel_sample(&s->tone, *ptr);
00477       }
00478 
00479       s->samples_pending -= limit;
00480 
00481       if (s->samples_pending) {
00482          /* Finished incomplete (last) block */
00483          if (s->last_hit && s->squelch) {
00484             /* If we had a hit last time, go ahead and clear this out since likely it
00485                will be another hit */
00486             memset(amp, 0, sizeof(*amp) * limit);
00487             if (writeback)
00488                *writeback = 1;
00489          }
00490          break;
00491       }
00492 
00493 
00494       tone_energy = goertzel_result(&s->tone);
00495 
00496       /* Scale to make comparable */
00497       tone_energy *= 2.0;
00498       s->energy *= s->block_size;
00499 
00500       ast_debug(10, "tone %d, Ew=%f, Et=%f, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
00501       hit = 0;
00502       if (tone_energy > s->energy * s->threshold) {
00503 
00504          ast_debug(10, "Hit! count=%d\n", s->hit_count);
00505          hit = 1;
00506 
00507          if (s->squelch) {
00508             /* Zero out frame data */
00509             memset(amp, 0, sizeof(*amp) * limit);
00510             if (writeback)
00511                *writeback = 1;
00512          }
00513       }
00514 
00515       if (s->hit_count)
00516          s->hit_count++;
00517 
00518       if (hit == s->last_hit) {
00519          if (!hit) {
00520             /* Two successive misses. Tone ended */
00521             s->hit_count = 0;
00522          } else if (!s->hit_count) {
00523             s->hit_count++;
00524          }
00525 
00526       }
00527 
00528       if (s->hit_count == s->hits_required) {
00529          ast_debug(1, "%d Hz done detected\n", s->freq);
00530          res = 1;
00531       }
00532 
00533       s->last_hit = hit;
00534 
00535       /* Reset for the next block */
00536       goertzel_reset(&s->tone);
00537 
00538       /* Advance to the next block */
00539       s->energy = 0.0;
00540       s->samples_pending = s->block_size;
00541 
00542       amp += limit;
00543       samples -= limit;
00544    }
00545 
00546    return res;
00547 }


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

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 261 of file dsp.c.

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

Definition at line 271 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 257 of file dsp.c.

float mf_tones[] [static]

Initial value:

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

Definition at line 266 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().


Generated on Thu Jul 9 13:41:16 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7