Wed Oct 28 11:46:08 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"

Include dependency graph for dsp.c:

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 = 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)
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_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.
struct ast_dspast_dsp_new (void)
struct 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.
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 676 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 __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 120 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

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

00109                  {
00110    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last silence periods */
00111    BUSY_PAT_PERCENT = 7,   /*!< 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 = 75,          /*!< Busy must be at least 80 ms in half-cadence */
00114    BUSY_MAX =3100          /*!< Busy can't be longer than 3100 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 };

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

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, 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_WARNING, pair_there(), pass, 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().

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

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

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

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

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

Definition at line 1024 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence().

01025 {
01026    int accum;
01027    int x;
01028    int res = 0;
01029 
01030    if (!len)
01031       return 0;
01032    accum = 0;
01033    for (x=0;x<len; x++) 
01034       accum += abs(s[x]);
01035    accum /= len;
01036    if (accum < dsp->threshold) {
01037       /* Silent */
01038       dsp->totalsilence += len/8;
01039       if (dsp->totalnoise) {
01040          /* Move and save history */
01041          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01042          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01043 /* we don't want to check for busydetect that frequently */
01044 #if 0
01045          dsp->busymaybe = 1;
01046 #endif
01047       }
01048       dsp->totalnoise = 0;
01049       res = 1;
01050    } else {
01051       /* Not silent */
01052       dsp->totalnoise += len/8;
01053       if (dsp->totalsilence) {
01054          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01055          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01056          /* Move and save history */
01057          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01058          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01059          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01060          if (silence1 < silence2) {
01061             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01062                dsp->busymaybe = 1;
01063             else 
01064                dsp->busymaybe = 0;
01065          } else {
01066             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01067                dsp->busymaybe = 1;
01068             else 
01069                dsp->busymaybe = 0;
01070          }
01071       }
01072       dsp->totalsilence = 0;
01073    }
01074    if (totalsilence)
01075       *totalsilence = dsp->totalsilence;
01076    return res;
01077 }

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

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

References ast_debug, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, and ast_dsp::historicsilence.

Referenced by ast_dsp_process().

01080 {
01081    int res = 0, x;
01082 #ifndef BUSYDETECT_TONEONLY
01083    int avgsilence = 0, hitsilence = 0;
01084 #endif
01085    int avgtone = 0, hittone = 0;
01086    if (!dsp->busymaybe)
01087       return res;
01088    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01089 #ifndef BUSYDETECT_TONEONLY
01090       avgsilence += dsp->historicsilence[x];
01091 #endif
01092       avgtone += dsp->historicnoise[x];
01093    }
01094 #ifndef BUSYDETECT_TONEONLY
01095    avgsilence /= dsp->busycount;
01096 #endif
01097    avgtone /= dsp->busycount;
01098    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01099 #ifndef BUSYDETECT_TONEONLY
01100       if (avgsilence > dsp->historicsilence[x]) {
01101          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01102             hitsilence++;
01103       } else {
01104          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01105             hitsilence++;
01106       }
01107 #endif
01108       if (avgtone > dsp->historicnoise[x]) {
01109          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01110             hittone++;
01111       } else {
01112          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01113             hittone++;
01114       }
01115    }
01116 #ifndef BUSYDETECT_TONEONLY
01117    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01118        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01119        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01120 #else
01121    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01122 #endif
01123 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01124       if (avgtone > avgsilence) {
01125          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01126             res = 1;
01127       } else {
01128          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01129             res = 1;
01130       }
01131 #else
01132       res = 1;
01133 #endif
01134    }
01135    /* If we know the expected busy tone length, check we are in the range */
01136    if (res && (dsp->busy_tonelength > 0)) {
01137       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01138 #ifdef BUSYDETECT_DEBUG
01139          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01140             avgtone, dsp->busy_tonelength);
01141 #endif
01142          res = 0;
01143       }
01144    }
01145 #ifndef BUSYDETECT_TONEONLY
01146    /* If we know the expected busy tone silent-period length, check we are in the range */
01147    if (res && (dsp->busy_quietlength > 0)) {
01148       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01149 #ifdef BUSYDETECT_DEBUG
01150       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01151          avgsilence, dsp->busy_quietlength);
01152 #endif
01153          res = 0;
01154       }
01155    }
01156 #endif
01157 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01158    if (res) {
01159       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01160    } else {
01161       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01162    }
01163 #endif
01164    return res;
01165 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame inf 
)

Return non-zero if DTMF hit was found.

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

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

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1472 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(), mkintf(), sip_new(), ss_thread(), and store_config().

01473 {
01474    int new;
01475    int old;
01476    
01477    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01478    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01479    if (old != new) {
01480       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01481       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01482    }
01483    dsp->digitmode = digitmode;
01484    return 0;
01485 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1430 of file dsp.c.

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

Referenced by ss_thread().

01431 {
01432    int i;
01433    
01434    dsp->thinkdigit = 0;
01435    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01436       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01437       /* Reinitialise the detector for the next block */
01438       for (i = 0;  i < 6;  i++) {
01439          goertzel_reset(&s->tone_out[i]);
01440       }
01441       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01442       s->current_sample = 0;
01443    } else {
01444       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01445       /* Reinitialise the detector for the next block */
01446       for (i = 0;  i < 4;  i++) {
01447          goertzel_reset(&s->row_out[i]);
01448          goertzel_reset(&s->col_out[i]);
01449       }
01450       s->lasthit = s->current_hit = 0;
01451       s->energy = 0.0;
01452       s->current_sample = 0;
01453    }
01454 
01455    dsp->digit_state.digits[0] = '\0';
01456    dsp->digit_state.current_digits = 0;
01457 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1515 of file dsp.c.

References ast_dsp::tcount.

01516 {
01517    return dsp->tcount;
01518 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1510 of file dsp.c.

References ast_dsp::tstate.

01511 {
01512    return dsp->tstate;
01513 }

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

Get pending DTMF/MF digits.

Definition at line 873 of file dsp.c.

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

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

struct ast_dsp* ast_dsp_new ( void   )  [read]

struct ast_frame* ast_dsp_process ( struct ast_channel chan,
struct ast_dsp dsp,
struct ast_frame af 
) [read]

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 1185 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_frfree, ast_frisolate(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, 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(), and usbradio_read().

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1362 of file dsp.c.

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

01363 {
01364    int max = 0;
01365    int x;
01366    
01367    dsp->gsamp_size = modes[dsp->progmode].size;
01368    dsp->gsamps = 0;
01369    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01370       if (modes[dsp->progmode].freqs[x]) {
01371          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01372          max = x + 1;
01373       }
01374    }
01375    dsp->freqcount = max;
01376    dsp->ringtimeout= 0;
01377 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01460 {
01461    int x;
01462    
01463    dsp->totalsilence = 0;
01464    dsp->gsamps = 0;
01465    for (x=0;x<4;x++)
01466       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01467    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01468    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01469    dsp->ringtimeout= 0;
01470 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1414 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01415 {
01416    if (cadences < 4)
01417       cadences = 4;
01418    if (cadences > DSP_HISTORY)
01419       cadences = DSP_HISTORY;
01420    dsp->busycount = cadences;
01421 }

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

Set expected lengths of the busy tone.

Definition at line 1423 of file dsp.c.

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

Referenced by dahdi_new().

01424 {
01425    dsp->busy_tonelength = tonelength;
01426    dsp->busy_quietlength = quietlength;
01427    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01428 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1496 of file dsp.c.

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

Referenced by dahdi_new().

01497 {
01498    int x;
01499    
01500    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01501       if (!strcasecmp(aliases[x].name, zone)) {
01502          dsp->progmode = aliases[x].mode;
01503          ast_dsp_prog_reset(dsp);
01504          return 0;
01505       }
01506    }
01507    return -1;
01508 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1487 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01488 {
01489    if (dsp->faxmode != faxmode) {
01490       ast_fax_detect_init(dsp);
01491    }
01492    dsp->faxmode = faxmode;
01493    return 0;
01494 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1399 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(), and store_config().

01400 {
01401    dsp->features = features;
01402 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1409 of file dsp.c.

References ast_dsp::threshold.

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

01410 {
01411    dsp->threshold = threshold;
01412 }

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 1167 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 __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().

01168 {
01169    short *s;
01170    int len;
01171    
01172    if (f->frametype != AST_FRAME_VOICE) {
01173       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01174       return 0;
01175    }
01176    if (f->subclass != AST_FORMAT_SLINEAR) {
01177       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01178       return 0;
01179    }
01180    s = f->data;
01181    len = f->datalen/2;
01182    return __ast_dsp_silence(dsp, s, len, totalsilence);
01183 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 417 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::energy, goertzel_init(), dtmf_detect_state_t::lasthit, and dtmf_detect_state_t::row_out.

Referenced by ast_digit_detect_init().

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

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 431 of file dsp.c.

References mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, goertzel_init(), mf_detect_state_t::hits, and mf_detect_state_t::tone_out.

Referenced by ast_digit_detect_init().

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

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

Definition at line 351 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_init(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, SAMPLE_RATE, SAMPLES_IN_FRAME, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_fax_detect_init().

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

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

Definition at line 558 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, DSP_DIGITMODE_NOQUELCH, digit_detect_state_t::dtmf, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::lasthit, dtmf_detect_state_t::row_out, store_digit(), and digit_detect_state_t::td.

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 310 of file dsp.c.

References goertzel_state_t::chunky, cos, goertzel_state_t::fac, SAMPLE_RATE, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.

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 goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_digitreset(), dtmf_detect(), mf_detect(), and tone_detect().

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_state_t::chunky, goertzel_state_t::fac, goertzel_result_t::power, goertzel_state_t::v2, goertzel_state_t::v3, and goertzel_result_t::value.

Referenced by __ast_dsp_call_progress(), dtmf_detect(), mf_detect(), and tone_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 goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.

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

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

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, DSP_DIGITMODE_NOQUELCH, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by __ast_dsp_digitdetect().

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

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

Definition at line 853 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

Definition at line 546 of file dsp.c.

References ast_log(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, LOG_WARNING, digit_detect_state_t::lost_digits, and MAX_DTMF_DIGITS.

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

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

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

Definition at line 455 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by __ast_dsp_digitdetect().

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


Variable Documentation

struct progalias aliases[] [static]

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 Wed Oct 28 11:46:08 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6