Fri Nov 12 11:59:47 2010

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 "asterisk/config.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  fragment_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 CONFIG_FILE_NAME   "dsp.conf"
#define DEFAULT_THRESHOLD   512
 This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
#define DSP_HISTORY   15
#define DTMF_2ND_HARMONIC_COL   63.1
#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)
#define DTMF_GSIZE   102
#define DTMF_HITS_TO_BEGIN   2
#define DTMF_MISSES_TO_END   3
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   (relax ? 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 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_350UK = 0, HZ_400UK, HZ_440UK
}
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_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
static int _dsp_init (int reload)
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.
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_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf.
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_init (void)
 Load dsp settings from dsp.conf.
struct ast_dspast_dsp_new (void)
int ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
 Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
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)
int ast_dsp_reload (void)
 Reloads dsp settings from dsp.conf.
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_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
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.
int ast_dsp_was_muted (struct ast_dsp *dsp)
 Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.
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 (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
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 (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void mute_fragment (struct ast_dsp *dsp, fragment_t *fragment)
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 (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)

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 []
static int thresholds [THRESHOLD_MAX]

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

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 172 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 173 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 216 of file dsp.c.

#define DEFAULT_THRESHOLD   512

This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.

Definition at line 117 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 128 of file dsp.c.

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

#define DTMF_2ND_HARMONIC_COL   63.1

Definition at line 169 of file dsp.c.

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 168 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 209 of file dsp.c.

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

#define DTMF_HITS_TO_BEGIN   2

Definition at line 212 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_MISSES_TO_END   3

Definition at line 214 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_NORMAL_TWIST   6.3

Definition at line 160 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 167 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 166 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)

Definition at line 164 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 157 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 170 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 159 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 158 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 193 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 192 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 191 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 185 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 184 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 183 of file dsp.c.

Referenced by ast_fax_detect_init().

#define MAX_DTMF_DIGITS   128

Definition at line 143 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 206 of file dsp.c.

Referenced by mf_detect().

#define SAMPLE_RATE   8000

Definition at line 195 of file dsp.c.

#define SAMPLES_IN_FRAME   160

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

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 130 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

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

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

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_350UK 

For UK mode

HZ_400UK 
HZ_440UK 

Definition at line 71 of file dsp.c.

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

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

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

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

Enumerator:
THRESH_RING 

Need at least 150ms ring to accept

THRESH_TALK 

Talk detection does not work continuously

THRESH_BUSY 

Need at least 80ms to accept

THRESH_CONGESTION 

Need at least 80ms to accept

THRESH_HANGUP 

Need at least 1300ms to accept hangup

THRESH_RING2ANSWER 

Timeout from start of ring to answer (about 6600 ms)

Definition at line 134 of file dsp.c.

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

enum prog_mode
Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 65 of file dsp.c.

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


Function Documentation

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

Definition at line 963 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_350UK, HZ_400UK, HZ_425, HZ_440, HZ_440UK, 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().

00964 {
00965    int x;
00966    int y;
00967    int pass;
00968    int newstate = DSP_TONE_STATE_SILENCE;
00969    int res = 0;
00970    while (len) {
00971       /* Take the lesser of the number of samples we need and what we have */
00972       pass = len;
00973       if (pass > dsp->gsamp_size - dsp->gsamps) {
00974          pass = dsp->gsamp_size - dsp->gsamps;
00975       }
00976       for (x = 0; x < pass; x++) {
00977          for (y = 0; y < dsp->freqcount; y++) {
00978             goertzel_sample(&dsp->freqs[y], s[x]);
00979          }
00980          dsp->genergy += s[x] * s[x];
00981       }
00982       s += pass;
00983       dsp->gsamps += pass;
00984       len -= pass;
00985       if (dsp->gsamps == dsp->gsamp_size) {
00986          float hz[7];
00987          for (y = 0; y < 7; y++) {
00988             hz[y] = goertzel_result(&dsp->freqs[y]);
00989          }
00990          switch (dsp->progmode) {
00991          case PROG_MODE_NA:
00992             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
00993                newstate = DSP_TONE_STATE_BUSY;
00994             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
00995                newstate = DSP_TONE_STATE_RINGING;
00996             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
00997                newstate = DSP_TONE_STATE_DIALTONE;
00998             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
00999                newstate = DSP_TONE_STATE_SPECIAL1;
01000             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
01001                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
01002                   newstate = DSP_TONE_STATE_SPECIAL2;
01003             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
01004                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
01005                   newstate = DSP_TONE_STATE_SPECIAL3;
01006                }
01007             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01008                newstate = DSP_TONE_STATE_TALKING;
01009             } else {
01010                newstate = DSP_TONE_STATE_SILENCE;
01011             }
01012             break;
01013          case PROG_MODE_CR:
01014             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
01015                newstate = DSP_TONE_STATE_RINGING;
01016             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
01017                newstate = DSP_TONE_STATE_TALKING;
01018             } else {
01019                newstate = DSP_TONE_STATE_SILENCE;
01020             }
01021             break;
01022          case PROG_MODE_UK:
01023             if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
01024                newstate = DSP_TONE_STATE_HUNGUP;
01025             } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
01026                newstate = DSP_TONE_STATE_DIALTONE;
01027             }
01028             break;
01029          default:
01030             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
01031          }
01032          if (newstate == dsp->tstate) {
01033             dsp->tcount++;
01034             if (dsp->ringtimeout) {
01035                dsp->ringtimeout++;
01036             }
01037             switch (dsp->tstate) {
01038                case DSP_TONE_STATE_RINGING:
01039                   if ((dsp->features & DSP_PROGRESS_RINGING) &&
01040                       (dsp->tcount==THRESH_RING)) {
01041                      res = AST_CONTROL_RINGING;
01042                      dsp->ringtimeout= 1;
01043                   }
01044                   break;
01045                case DSP_TONE_STATE_BUSY:
01046                   if ((dsp->features & DSP_PROGRESS_BUSY) &&
01047                       (dsp->tcount==THRESH_BUSY)) {
01048                      res = AST_CONTROL_BUSY;
01049                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01050                   }
01051                   break;
01052                case DSP_TONE_STATE_TALKING:
01053                   if ((dsp->features & DSP_PROGRESS_TALK) &&
01054                       (dsp->tcount==THRESH_TALK)) {
01055                      res = AST_CONTROL_ANSWER;
01056                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01057                   }
01058                   break;
01059                case DSP_TONE_STATE_SPECIAL3:
01060                   if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
01061                       (dsp->tcount==THRESH_CONGESTION)) {
01062                      res = AST_CONTROL_CONGESTION;
01063                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01064                   }
01065                   break;
01066                case DSP_TONE_STATE_HUNGUP:
01067                   if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
01068                       (dsp->tcount==THRESH_HANGUP)) {
01069                      res = AST_CONTROL_HANGUP;
01070                      dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01071                   }
01072                   break;
01073             }
01074             if (dsp->ringtimeout==THRESH_RING2ANSWER) {
01075                ast_debug(1, "Consider call as answered because of timeout after last ring\n");
01076                res = AST_CONTROL_ANSWER;
01077                dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
01078             }
01079          } else {
01080             ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
01081             ast_debug(5, "Start state %d\n", newstate);
01082             dsp->tstate = newstate;
01083             dsp->tcount = 1;
01084          }
01085          
01086          /* Reset goertzel */                
01087          for (x = 0; x < 7; x++) {
01088             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01089          }
01090          dsp->gsamps = 0;
01091          dsp->genergy = 0.0;
01092       }
01093    }
01094 
01095    return res;
01096 }

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

Definition at line 1111 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_noise(), ast_dsp_process(), and ast_dsp_silence().

01112 {
01113    int accum;
01114    int x;
01115    int res = 0;
01116 
01117    if (!len) {
01118       return 0;
01119    }
01120    accum = 0;
01121    for (x = 0; x < len; x++) {
01122       accum += abs(s[x]);
01123    }
01124    accum /= len;
01125    if (accum < dsp->threshold) {
01126       /* Silent */
01127       dsp->totalsilence += len / 8;
01128       if (dsp->totalnoise) {
01129          /* Move and save history */
01130          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
01131          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01132 /* we don't want to check for busydetect that frequently */
01133 #if 0
01134          dsp->busymaybe = 1;
01135 #endif
01136       }
01137       dsp->totalnoise = 0;
01138       res = 1;
01139    } else {
01140       /* Not silent */
01141       dsp->totalnoise += len / 8;
01142       if (dsp->totalsilence) {
01143          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01144          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01145          /* Move and save history */
01146          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
01147          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01148          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01149          if (silence1 < silence2) {
01150             if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
01151                dsp->busymaybe = 1;
01152             } else {
01153                dsp->busymaybe = 0;
01154             }
01155          } else {
01156             if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
01157                dsp->busymaybe = 1;
01158             } else {
01159                dsp->busymaybe = 0;
01160             }
01161          }
01162       }
01163       dsp->totalsilence = 0;
01164    }
01165    if (totalsilence) {
01166       *totalsilence = dsp->totalsilence;
01167    }
01168    if (totalnoise) {
01169       *totalnoise = dsp->totalnoise;
01170    }
01171    return res;
01172 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1681 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_log(), ast_variable_retrieve(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, and THRESHOLD_SILENCE.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01682 {
01683    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01684    struct ast_config *cfg;
01685 
01686    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01687    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
01688       return 0;
01689    }
01690 
01691    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
01692       const char *value;
01693 
01694       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01695       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01696          ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01697          thresholds[THRESHOLD_SILENCE] = 256;
01698       } else if (!value) {
01699          thresholds[THRESHOLD_SILENCE] = 256;
01700       }
01701 
01702       ast_config_destroy(cfg);
01703    }
01704    return 0;
01705 }

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

01175 {
01176    int res = 0, x;
01177 #ifndef BUSYDETECT_TONEONLY
01178    int avgsilence = 0, hitsilence = 0;
01179 #endif
01180    int avgtone = 0, hittone = 0;
01181    if (!dsp->busymaybe) {
01182       return res;
01183    }
01184    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01185 #ifndef BUSYDETECT_TONEONLY
01186       avgsilence += dsp->historicsilence[x];
01187 #endif
01188       avgtone += dsp->historicnoise[x];
01189    }
01190 #ifndef BUSYDETECT_TONEONLY
01191    avgsilence /= dsp->busycount;
01192 #endif
01193    avgtone /= dsp->busycount;
01194    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01195 #ifndef BUSYDETECT_TONEONLY
01196       if (avgsilence > dsp->historicsilence[x]) {
01197          if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
01198             hitsilence++;
01199          }
01200       } else {
01201          if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
01202             hitsilence++;
01203          }
01204       }
01205 #endif
01206       if (avgtone > dsp->historicnoise[x]) {
01207          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01208             hittone++;
01209          }
01210       } else {
01211          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01212             hittone++;
01213          }
01214       }
01215    }
01216 #ifndef BUSYDETECT_TONEONLY
01217    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01218        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01219        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01220 #else
01221    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01222 #endif
01223 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01224       if (avgtone > avgsilence) {
01225          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
01226             res = 1;
01227          }
01228       } else {
01229          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
01230             res = 1;
01231          }
01232       }
01233 #else
01234       res = 1;
01235 #endif
01236    }
01237    /* If we know the expected busy tone length, check we are in the range */
01238    if (res && (dsp->busy_tonelength > 0)) {
01239       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01240 #ifdef BUSYDETECT_DEBUG
01241          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01242             avgtone, dsp->busy_tonelength);
01243 #endif
01244          res = 0;
01245       }
01246    }
01247 #ifndef BUSYDETECT_TONEONLY
01248    /* If we know the expected busy tone silent-period length, check we are in the range */
01249    if (res && (dsp->busy_quietlength > 0)) {
01250       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01251 #ifdef BUSYDETECT_DEBUG
01252       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01253          avgsilence, dsp->busy_quietlength);
01254 #endif
01255          res = 0;
01256       }
01257    }
01258 #endif
01259 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01260    if (res) {
01261       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01262    } else {
01263       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01264    }
01265 #endif
01266    return res;
01267 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1098 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, ast_frame::ptr, and ast_frame::subclass.

01099 {
01100    if (inf->frametype != AST_FRAME_VOICE) {
01101       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01102       return 0;
01103    }
01104    if (inf->subclass != AST_FORMAT_SLINEAR) {
01105       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01106       return 0;
01107    }
01108    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01109 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1583 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, ast_dsp::dtmf_began, dtmf_detect_state_t::energy, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::misses, dtmf_detect_state_t::row_out, s, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ss_thread().

01584 {
01585    int i;
01586    
01587    dsp->dtmf_began = 0;
01588    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01589       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01590       /* Reinitialise the detector for the next block */
01591       for (i = 0;  i < 6;  i++) {
01592          goertzel_reset(&s->tone_out[i]);
01593       }
01594       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01595       s->current_sample = 0;
01596    } else {
01597       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01598       /* Reinitialise the detector for the next block */
01599       for (i = 0;  i < 4;  i++) {
01600          goertzel_reset(&s->row_out[i]);
01601          goertzel_reset(&s->col_out[i]);
01602       }
01603       s->lasthit = s->current_hit = 0;
01604       s->energy = 0.0;
01605       s->current_sample = 0;
01606       s->hits = 0;
01607       s->misses = 0;
01608    }
01609 
01610    dsp->digit_state.digits[0] = '\0';
01611    dsp->digit_state.current_digits = 0;
01612 }

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

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

Referenced by __frame_free().

01723 {
01724    struct ast_dsp *dsp;
01725 
01726    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01727 
01728    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01729 
01730    if (!dsp->destroy)
01731       return;
01732    
01733    ast_dsp_free(dsp);
01734 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1545 of file dsp.c.

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

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

01546 {
01547    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01548       /* If this flag is still set, that means that the dsp's destruction 
01549        * been torn down, while we still have a frame out there being used.
01550        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01551        * will get destroyed, too. */
01552 
01553       dsp->destroy = 1;
01554 
01555       return;
01556    }
01557    ast_free(dsp);
01558 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1676 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01677 {
01678    return dsp->tcount;
01679 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1707 of file dsp.c.

Referenced by app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), and setup_privacy_args().

01708 {
01709    return thresholds[which];
01710 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1671 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01672 {
01673    return dsp->tstate;
01674 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1712 of file dsp.c.

References _dsp_init().

Referenced by main().

01713 {
01714    return _dsp_init(0);
01715 }

struct ast_dsp* ast_dsp_new ( void   )  [read]
int ast_dsp_noise ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalnoise 
)

Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.

Since:
1.6.1

Definition at line 1287 of file dsp.c.

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

Referenced by do_waiting().

01288 {
01289        short *s;
01290        int len;
01291 
01292        if (f->frametype != AST_FRAME_VOICE) {
01293                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01294                return 0;
01295        }
01296        if (f->subclass != AST_FORMAT_SLINEAR) {
01297                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01298                return 0;
01299        }
01300        s = f->data.ptr;
01301        len = f->datalen/2;
01302        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01303 }

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

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), 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_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame::frametype, ast_dsp::historicnoise, ast_dsp::historicsilence, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_channel::name, ast_frame::ptr, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

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

01307 {
01308    int silence;
01309    int res;
01310    int digit = 0, fax_digit = 0;
01311    int x;
01312    short *shortdata;
01313    unsigned char *odata;
01314    int len;
01315    struct ast_frame *outf = NULL;
01316 
01317    if (!af) {
01318       return NULL;
01319    }
01320    if (af->frametype != AST_FRAME_VOICE) {
01321       return af;
01322    }
01323 
01324    odata = af->data.ptr;
01325    len = af->datalen;
01326    /* Make sure we have short data */
01327    switch (af->subclass) {
01328    case AST_FORMAT_SLINEAR:
01329       shortdata = af->data.ptr;
01330       len = af->datalen / 2;
01331       break;
01332    case AST_FORMAT_ULAW:
01333       shortdata = alloca(af->datalen * 2);
01334       for (x = 0;x < len; x++) {
01335          shortdata[x] = AST_MULAW(odata[x]);
01336       }
01337       break;
01338    case AST_FORMAT_ALAW:
01339       shortdata = alloca(af->datalen * 2);
01340       for (x = 0; x < len; x++) {
01341          shortdata[x] = AST_ALAW(odata[x]);
01342       }
01343       break;
01344    default:
01345       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01346       if (dsp->display_inband_dtmf_warning)
01347          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01348       dsp->display_inband_dtmf_warning = 0;
01349       return af;
01350    }
01351 
01352    /* Initially we do not want to mute anything */
01353    dsp->mute_fragments = 0;
01354 
01355    /* Need to run the silence detection stuff for silence suppression and busy detection */
01356    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01357       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01358    }
01359 
01360    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01361       memset(&dsp->f, 0, sizeof(dsp->f));
01362       dsp->f.frametype = AST_FRAME_NULL;
01363       ast_frfree(af);
01364       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01365       return &dsp->f;
01366    }
01367    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01368       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01369       memset(&dsp->f, 0, sizeof(dsp->f));
01370       dsp->f.frametype = AST_FRAME_CONTROL;
01371       dsp->f.subclass = AST_CONTROL_BUSY;
01372       ast_frfree(af);
01373       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01374       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01375       return &dsp->f;
01376    }
01377 
01378    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01379       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01380          fax_digit = 'f';
01381       }
01382 
01383       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01384          fax_digit = 'e';
01385       }
01386    }
01387 
01388    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01389       if (dsp->digitmode & DSP_DIGITMODE_MF)
01390          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01391       else
01392          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01393 
01394       if (dsp->digit_state.current_digits) {
01395          int event = 0;
01396          char event_digit = 0;
01397 
01398          if (!dsp->dtmf_began) {
01399             /* We have not reported DTMF_BEGIN for anything yet */
01400 
01401             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01402                event = AST_FRAME_DTMF_BEGIN;
01403                event_digit = dsp->digit_state.digits[0];
01404             }
01405             dsp->dtmf_began = 1;
01406 
01407          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01408             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01409             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01410                event = AST_FRAME_DTMF_END;
01411                event_digit = dsp->digit_state.digits[0];
01412             }
01413             memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits);
01414             dsp->digit_state.current_digits--;
01415             dsp->dtmf_began = 0;
01416 
01417             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01418                /* Reset Busy Detector as we have some confirmed activity */ 
01419                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01420                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01421                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01422             }
01423          }
01424 
01425          if (event) {
01426             memset(&dsp->f, 0, sizeof(dsp->f));
01427             dsp->f.frametype = event;
01428             dsp->f.subclass = event_digit;
01429             outf = &dsp->f;
01430             goto done;
01431          }
01432       }
01433    }
01434 
01435    if (fax_digit) {
01436       /* Fax was detected - digit is either 'f' or 'e' */
01437 
01438       memset(&dsp->f, 0, sizeof(dsp->f));
01439       dsp->f.frametype = AST_FRAME_DTMF;
01440       dsp->f.subclass = fax_digit;
01441       outf = &dsp->f;
01442       goto done;
01443    }
01444 
01445    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01446       res = __ast_dsp_call_progress(dsp, shortdata, len);
01447       if (res) {
01448          switch (res) {
01449          case AST_CONTROL_ANSWER:
01450          case AST_CONTROL_BUSY:
01451          case AST_CONTROL_RINGING:
01452          case AST_CONTROL_CONGESTION:
01453          case AST_CONTROL_HANGUP:
01454             memset(&dsp->f, 0, sizeof(dsp->f));
01455             dsp->f.frametype = AST_FRAME_CONTROL;
01456             dsp->f.subclass = res;
01457             dsp->f.src = "dsp_progress";
01458             if (chan) 
01459                ast_queue_frame(chan, &dsp->f);
01460             break;
01461          default:
01462             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01463          }
01464       }
01465    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01466       res = __ast_dsp_call_progress(dsp, shortdata, len);
01467    }
01468 
01469 done:
01470    /* Mute fragment of the frame */
01471    for (x = 0; x < dsp->mute_fragments; x++) {
01472       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01473    }
01474 
01475    switch (af->subclass) {
01476    case AST_FORMAT_SLINEAR:
01477       break;
01478    case AST_FORMAT_ULAW:
01479       for (x = 0; x < len; x++) {
01480          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01481       }
01482       break;
01483    case AST_FORMAT_ALAW:
01484       for (x = 0; x < len; x++) {
01485          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01486       }
01487       break;
01488    }
01489 
01490    if (outf) {
01491       if (chan) {
01492          ast_queue_frame(chan, af);
01493       }
01494       ast_frfree(af);
01495       ast_set_flag(outf, AST_FRFLAG_FROM_DSP);
01496       return outf;
01497    } else {
01498       return af;
01499    }
01500 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01503 {
01504    int max = 0;
01505    int x;
01506    
01507    dsp->gsamp_size = modes[dsp->progmode].size;
01508    dsp->gsamps = 0;
01509    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01510       if (modes[dsp->progmode].freqs[x]) {
01511          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01512          max = x + 1;
01513       }
01514    }
01515    dsp->freqcount = max;
01516    dsp->ringtimeout= 0;
01517 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1717 of file dsp.c.

References _dsp_init().

01718 {
01719    return _dsp_init(1);
01720 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01615 {
01616    int x;
01617    
01618    dsp->totalsilence = 0;
01619    dsp->gsamps = 0;
01620    for (x = 0; x < 4; x++) {
01621       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01622    }
01623    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01624    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01625    dsp->ringtimeout= 0;
01626 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1565 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01566 {
01567    if (cadences < 4) {
01568       cadences = 4;
01569    }
01570    if (cadences > DSP_HISTORY) {
01571       cadences = DSP_HISTORY;
01572    }
01573    dsp->busycount = cadences;
01574 }

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

Set expected lengths of the busy tone.

Definition at line 1576 of file dsp.c.

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

Referenced by dahdi_new().

01577 {
01578    dsp->busy_tonelength = tonelength;
01579    dsp->busy_quietlength = quietlength;
01580    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01581 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1652 of file dsp.c.

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

Referenced by dahdi_new().

01653 {
01654    int x;
01655    
01656    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01657       if (!strcasecmp(aliases[x].name, zone)) {
01658          dsp->progmode = aliases[x].mode;
01659          ast_dsp_prog_reset(dsp);
01660          return 0;
01661       }
01662    }
01663    return -1;
01664 }

int ast_dsp_set_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Version:
1.6.1 renamed from ast_dsp_digitmode to ast_dsp_set_digitmode

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

01629 {
01630    int new;
01631    int old;
01632    
01633    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01634    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01635    if (old != new) {
01636       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01637       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01638    }
01639    dsp->digitmode = digitmode;
01640    return 0;
01641 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1643 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01644 {
01645    if (dsp->faxmode != faxmode) {
01646       ast_fax_detect_init(dsp);
01647    }
01648    dsp->faxmode = faxmode;
01649    return 0;
01650 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)
void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1560 of file dsp.c.

References ast_dsp::threshold.

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

01561 {
01562    dsp->threshold = threshold;
01563 }

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

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

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

01270 {
01271    short *s;
01272    int len;
01273    
01274    if (f->frametype != AST_FRAME_VOICE) {
01275       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01276       return 0;
01277    }
01278    if (f->subclass != AST_FORMAT_SLINEAR) {
01279       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01280       return 0;
01281    }
01282    s = f->data.ptr;
01283    len = f->datalen/2;
01284    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01285 }

int ast_dsp_was_muted ( struct ast_dsp dsp  ) 

Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.

Since:
1.6.1

Definition at line 1666 of file dsp.c.

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01667 {
01668    return (dsp->mute_fragments > 0);
01669 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]
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 500 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().

00501 {
00502    int i;
00503    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00504    for (i = 0;  i < 6;  i++) {
00505       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
00506    }
00507    s->current_sample = 0;
00508    s->current_hit = 0;
00509 }

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

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

00416 {
00417    int duration_samples;
00418    float x;
00419    int periods_in_block;
00420 
00421    s->freq = freq;
00422 
00423    /* Desired tone duration in samples */
00424    duration_samples = duration * SAMPLE_RATE / 1000;
00425    /* We want to allow 10% deviation of tone duration */
00426    duration_samples = duration_samples * 9 / 10;
00427 
00428    /* If we want to remove tone, it is important to have block size not
00429       to exceed frame size. Otherwise by the moment tone is detected it is too late
00430       to squelch it from previous frames */
00431    s->block_size = SAMPLES_IN_FRAME;
00432 
00433    periods_in_block = s->block_size * freq / SAMPLE_RATE;
00434 
00435    /* Make sure we will have at least 5 periods at target frequency for analisys.
00436       This may make block larger than expected packet and will make squelching impossible
00437       but at least we will be detecting the tone */
00438    if (periods_in_block < 5)
00439       periods_in_block = 5;
00440 
00441    /* Now calculate final block size. It will contain integer number of periods */
00442    s->block_size = periods_in_block * SAMPLE_RATE / freq;
00443 
00444    /* tone_detect is currently only used to detect fax tones and we
00445       do not need suqlching the fax tones */
00446    s->squelch = 0;
00447 
00448    /* Account for the first and the last block to be incomplete
00449       and thus no tone will be detected in them */
00450    s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
00451 
00452    goertzel_init(&s->tone, freq, s->block_size);
00453 
00454    s->samples_pending = s->block_size;
00455    s->hit_count = 0;
00456    s->last_hit = 0;
00457    s->energy = 0.0;
00458 
00459    /* We want tone energy to be amp decibels above the rest of the signal (the noise).
00460       According to Parseval's theorem the energy computed in time domain equals to energy
00461       computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
00462       from the energy in the time domain we will get energy of the remaining signal (without the tone
00463       we are detecting). We will be checking that
00464       10*log(Ew / (Et - Ew)) > amp
00465       Calculate threshold so that we will be actually checking
00466       Ew > Et * threshold
00467    */
00468 
00469    x = pow(10.0, amp / 10.0);
00470    s->threshold = x / (x + 1);
00471 
00472    ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
00473 }

static int dtmf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
) [static]

Definition at line 641 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, digit_detect_state_t::dtmf, DTMF_GSIZE, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, fragment_t::end, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::hits, dtmf_detect_state_t::hits_to_begin, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, dtmf_detect_state_t::misses_to_end, mute_fragment(), dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, fragment_t::start, store_digit(), and digit_detect_state_t::td.

Referenced by ast_dsp_process().

00642 {
00643    float row_energy[4];
00644    float col_energy[4];
00645    float famp;
00646    int i;
00647    int j;
00648    int sample;
00649    int best_row;
00650    int best_col;
00651    int hit;
00652    int limit;
00653    fragment_t mute = {0, 0};
00654 
00655    if (squelch && s->td.dtmf.mute_samples > 0) {
00656       mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
00657       s->td.dtmf.mute_samples -= mute.end;
00658    }
00659 
00660    hit = 0;
00661    for (sample = 0; sample < samples; sample = limit) {
00662       /* DTMF_GSIZE is optimised to meet the DTMF specs. */
00663       if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
00664          limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
00665       } else {
00666          limit = samples;
00667       }
00668       /* The following unrolled loop takes only 35% (rough estimate) of the 
00669          time of a rolled loop on the machine on which it was developed */
00670       for (j = sample; j < limit; j++) {
00671          famp = amp[j];
00672          s->td.dtmf.energy += famp*famp;
00673          /* With GCC 2.95, the following unrolled code seems to take about 35%
00674             (rough estimate) as long as a neat little 0-3 loop */
00675          goertzel_sample(s->td.dtmf.row_out, amp[j]);
00676          goertzel_sample(s->td.dtmf.col_out, amp[j]);
00677          goertzel_sample(s->td.dtmf.row_out + 1, amp[j]);
00678          goertzel_sample(s->td.dtmf.col_out + 1, amp[j]);
00679          goertzel_sample(s->td.dtmf.row_out + 2, amp[j]);
00680          goertzel_sample(s->td.dtmf.col_out + 2, amp[j]);
00681          goertzel_sample(s->td.dtmf.row_out + 3, amp[j]);
00682          goertzel_sample(s->td.dtmf.col_out + 3, amp[j]);
00683       }
00684       s->td.dtmf.current_sample += (limit - sample);
00685       if (s->td.dtmf.current_sample < DTMF_GSIZE) {
00686          continue;
00687       }
00688       /* We are at the end of a DTMF detection block */
00689       /* Find the peak row and the peak column */
00690       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00691       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00692 
00693       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00694          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00695          if (row_energy[i] > row_energy[best_row]) {
00696             best_row = i;
00697          }
00698          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00699          if (col_energy[i] > col_energy[best_col]) {
00700             best_col = i;
00701          }
00702       }
00703       hit = 0;
00704       /* Basic signal level test and the twist test */
00705       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00706           col_energy[best_col] >= DTMF_THRESHOLD &&
00707           col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST &&
00708           col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) {
00709          /* Relative peak test */
00710          for (i = 0;  i < 4;  i++) {
00711             if ((i != best_col &&
00712                 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00713                 (i != best_row 
00714                  && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00715                break;
00716             }
00717          }
00718          /* ... and fraction of total energy test */
00719          if (i >= 4 &&
00720              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
00721             /* Got a hit */
00722             hit = dtmf_positions[(best_row << 2) + best_col];
00723          }
00724       } 
00725 
00726       if (s->td.dtmf.current_hit) {
00727          /* We are in the middle of a digit already */
00728          if (hit != s->td.dtmf.current_hit) {
00729             s->td.dtmf.misses++;
00730             if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
00731                /* There were enough misses to consider digit ended */
00732                s->td.dtmf.current_hit = 0;
00733             }
00734          } else {
00735             s->td.dtmf.misses = 0;
00736          }
00737       }
00738 
00739       /* Look for a start of a new digit no matter if we are already in the middle of some
00740          digit or not. This is because hits_to_begin may be smaller than misses_to_end
00741          and we may find begin of new digit before we consider last one ended. */
00742       if (hit) {
00743          if (hit == s->td.dtmf.lasthit) {
00744             s->td.dtmf.hits++;
00745          } else {
00746             s->td.dtmf.hits = 1;
00747          }
00748 
00749          if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin && hit != s->td.dtmf.current_hit) {
00750             store_digit(s, hit);
00751             s->td.dtmf.current_hit = hit;
00752             s->td.dtmf.misses = 0;
00753          }
00754       } else {
00755          s->td.dtmf.hits = 0;
00756       }
00757 
00758       s->td.dtmf.lasthit = hit;
00759 
00760       /* If we had a hit in this block, include it into mute fragment */
00761       if (squelch && hit) {
00762          if (mute.end < sample - DTMF_GSIZE) {
00763             /* There is a gap between fragments */
00764             mute_fragment(dsp, &mute);
00765             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00766          }
00767          mute.end = limit + DTMF_GSIZE;
00768       }
00769 
00770       /* Reinitialise the detector for the next block */
00771       for (i = 0; i < 4; i++) {
00772          goertzel_reset(&s->td.dtmf.row_out[i]);
00773          goertzel_reset(&s->td.dtmf.col_out[i]);
00774       }
00775       s->td.dtmf.energy = 0.0;
00776       s->td.dtmf.current_sample = 0;
00777    }
00778 
00779    if (squelch && mute.end) {
00780       if (mute.end > samples) {
00781          s->td.dtmf.mute_samples = mute.end - samples;
00782          mute.end = samples;
00783       }
00784       mute_fragment(dsp, &mute);
00785    }
00786 
00787    return (s->td.dtmf.current_hit); /* return the debounced hit */
00788 }

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

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

00343 {
00344    s->v2 = s->v3 = s->chunky = 0.0;
00345    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00346    s->samples = samples;
00347 }

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

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

00350 {
00351    s->v2 = s->v3 = s->chunky = 0.0;
00352 }

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

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

00334 {
00335    goertzel_result_t r;
00336    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00337    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00338    r.power = s->chunky * 2;
00339    return (float)r.value * (float)(1 << r.power);
00340 }

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

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

00307 {
00308    int v1;
00309    
00310    v1 = s->v2;
00311    s->v2 = s->v3;
00312    
00313    s->v3 = (s->fac * s->v2) >> 15;
00314    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00315    if (abs(s->v3) > 32768) {
00316       s->chunky++;
00317       s->v3 = s->v3 >> 1;
00318       s->v2 = s->v2 >> 1;
00319       v1 = v1 >> 1;
00320    }
00321 }

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

Definition at line 323 of file dsp.c.

References goertzel_sample().

00324 {
00325    int i;
00326    
00327    for (i = 0; i < count; i++) {
00328       goertzel_sample(s, samps[i]);
00329    }
00330 }

static int mf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
) [static]

Definition at line 790 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, DTMF_GSIZE, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute_fragment(), mf_detect_state_t::mute_samples, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_process().

00792 {
00793    float energy[6];
00794    int best;
00795    int second_best;
00796    float famp;
00797    int i;
00798    int j;
00799    int sample;
00800    int hit;
00801    int limit;
00802    fragment_t mute = {0, 0};
00803 
00804    if (squelch && s->td.mf.mute_samples > 0) {
00805       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00806       s->td.mf.mute_samples -= mute.end;
00807    }
00808 
00809    hit = 0;
00810    for (sample = 0;  sample < samples;  sample = limit) {
00811       /* 80 is optimised to meet the MF specs. */
00812       /* XXX So then why is MF_GSIZE defined as 120? */
00813       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00814          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00815       } else {
00816          limit = samples;
00817       }
00818       /* The following unrolled loop takes only 35% (rough estimate) of the 
00819          time of a rolled loop on the machine on which it was developed */
00820       for (j = sample;  j < limit;  j++) {
00821          famp = amp[j];
00822          /* With GCC 2.95, the following unrolled code seems to take about 35%
00823             (rough estimate) as long as a neat little 0-3 loop */
00824          goertzel_sample(s->td.mf.tone_out, amp[j]);
00825          goertzel_sample(s->td.mf.tone_out + 1, amp[j]);
00826          goertzel_sample(s->td.mf.tone_out + 2, amp[j]);
00827          goertzel_sample(s->td.mf.tone_out + 3, amp[j]);
00828          goertzel_sample(s->td.mf.tone_out + 4, amp[j]);
00829          goertzel_sample(s->td.mf.tone_out + 5, amp[j]);
00830       }
00831       s->td.mf.current_sample += (limit - sample);
00832       if (s->td.mf.current_sample < MF_GSIZE) {
00833          continue;
00834       }
00835       /* We're at the end of an MF detection block.  */
00836       /* Find the two highest energies. The spec says to look for
00837          two tones and two tones only. Taking this literally -ie
00838          only two tones pass the minimum threshold - doesn't work
00839          well. The sinc function mess, due to rectangular windowing
00840          ensure that! Find the two highest energies and ensure they
00841          are considerably stronger than any of the others. */
00842       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00843       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00844       if (energy[0] > energy[1]) {
00845          best = 0;
00846          second_best = 1;
00847       } else {
00848          best = 1;
00849          second_best = 0;
00850       }
00851       /*endif*/
00852       for (i = 2; i < 6; i++) {
00853          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00854          if (energy[i] >= energy[best]) {
00855             second_best = best;
00856             best = i;
00857          } else if (energy[i] >= energy[second_best]) {
00858             second_best = i;
00859          }
00860       }
00861       /* Basic signal level and twist tests */
00862       hit = 0;
00863       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00864                && energy[best] < energy[second_best]*BELL_MF_TWIST
00865                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00866          /* Relative peak test */
00867          hit = -1;
00868          for (i = 0; i < 6; i++) {
00869             if (i != best && i != second_best) {
00870                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00871                   /* The best two are not clearly the best */
00872                   hit = 0;
00873                   break;
00874                }
00875             }
00876          }
00877       }
00878       if (hit) {
00879          /* Get the values into ascending order */
00880          if (second_best < best) {
00881             i = best;
00882             best = second_best;
00883             second_best = i;
00884          }
00885          best = best * 5 + second_best - 1;
00886          hit = bell_mf_positions[best];
00887          /* Look for two successive similar results */
00888          /* The logic in the next test is:
00889             For KP we need 4 successive identical clean detects, with
00890             two blocks of something different preceeding it. For anything
00891             else we need two successive identical clean detects, with
00892             two blocks of something different preceeding it. */
00893          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00894             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00895              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00896              hit != s->td.mf.hits[0]))) {
00897             store_digit(s, hit);
00898          }
00899       }
00900 
00901 
00902       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00903          /* Two successive block without a hit terminate current digit */
00904          s->td.mf.current_hit = 0;
00905       }
00906 
00907       s->td.mf.hits[0] = s->td.mf.hits[1];
00908       s->td.mf.hits[1] = s->td.mf.hits[2];
00909       s->td.mf.hits[2] = s->td.mf.hits[3];
00910       s->td.mf.hits[3] = s->td.mf.hits[4];
00911       s->td.mf.hits[4] = hit;
00912 
00913       /* If we had a hit in this block, include it into mute fragment */
00914       if (squelch && hit) {
00915          if (mute.end < sample - MF_GSIZE) {
00916             /* There is a gap between fragments */
00917             mute_fragment(dsp, &mute);
00918             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00919          }
00920          mute.end = limit + DTMF_GSIZE;
00921       }
00922 
00923       /* Reinitialise the detector for the next block */
00924       for (i = 0;  i < 6;  i++)
00925          goertzel_reset(&s->td.mf.tone_out[i]);
00926       s->td.mf.current_sample = 0;
00927    }
00928 
00929    if (squelch && mute.end) {
00930       if (mute.end > samples) {
00931          s->td.mf.mute_samples = mute.end - samples;
00932          mute.end = samples;
00933       }
00934       mute_fragment(dsp, &mute);
00935    }
00936 
00937    return (s->td.mf.current_hit); /* return the debounced hit */
00938 }

static void mute_fragment ( struct ast_dsp dsp,
fragment_t fragment 
) [static]

Definition at line 405 of file dsp.c.

References ARRAY_LEN, ast_log(), LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.

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

00406 {
00407    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00408       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00409       return;
00410    }
00411 
00412    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00413 }

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

Definition at line 940 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

00941 {
00942    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00943    /* Make sure absolute levels are high enough */
00944    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
00945       return 0;
00946    }
00947    /* Amplify ignored stuff */
00948    i2 *= TONE_THRESH;
00949    i1 *= TONE_THRESH;
00950    e *= TONE_THRESH;
00951    /* Check first tone */
00952    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
00953       return 0;
00954    }
00955    /* And second */
00956    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
00957       return 0;
00958    }
00959    /* Guess it's there... */
00960    return 1;
00961 }

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

Definition at line 629 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 dtmf_detect(), and mf_detect().

00630 {
00631    s->detected_digits++;
00632    if (s->current_digits < MAX_DTMF_DIGITS) {
00633       s->digits[s->current_digits++] = digit;
00634       s->digits[s->current_digits] = '\0';
00635    } else {
00636       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00637       s->lost_digits++;
00638    }
00639 }

static int tone_detect ( struct ast_dsp dsp,
tone_detect_state_t s,
int16_t *  amp,
int  samples 
) [static]

Definition at line 525 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, fragment_t::end, 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, mute_fragment(), tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_dsp_process().

00526 {
00527    float tone_energy;
00528    int i;
00529    int hit = 0;
00530    int limit;
00531    int res = 0;
00532    int16_t *ptr;
00533    int start, end;
00534    fragment_t mute = {0, 0};
00535 
00536    if (s->squelch && s->mute_samples > 0) {
00537       mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
00538       s->mute_samples -= mute.end;
00539    }
00540 
00541    for (start = 0;  start < samples;  start = end) {
00542       /* Process in blocks. */
00543       limit = samples - start;
00544       if (limit > s->samples_pending) {
00545          limit = s->samples_pending;
00546       }
00547       end = start + limit;
00548 
00549       for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
00550          /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */
00551          s->energy += (int32_t) *ptr * (int32_t) *ptr;
00552 
00553          goertzel_sample(&s->tone, *ptr);
00554       }
00555 
00556       s->samples_pending -= limit;
00557 
00558       if (s->samples_pending) {
00559          /* Finished incomplete (last) block */
00560          break;
00561       }
00562 
00563       tone_energy = goertzel_result(&s->tone);
00564 
00565       /* Scale to make comparable */
00566       tone_energy *= 2.0;
00567       s->energy *= s->block_size;
00568 
00569       ast_debug(10, "tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
00570       hit = 0;
00571       if (tone_energy > s->energy * s->threshold) {
00572          ast_debug(10, "Hit! count=%d\n", s->hit_count);
00573          hit = 1;
00574       }
00575 
00576       if (s->hit_count) {
00577          s->hit_count++;
00578       }
00579 
00580       if (hit == s->last_hit) {
00581          if (!hit) {
00582             /* Two successive misses. Tone ended */
00583             s->hit_count = 0;
00584          } else if (!s->hit_count) {
00585             s->hit_count++;
00586          }
00587 
00588       }
00589 
00590       if (s->hit_count == s->hits_required) {
00591          ast_debug(1, "%d Hz done detected\n", s->freq);
00592          res = 1;
00593       }
00594 
00595       s->last_hit = hit;
00596 
00597       /* If we had a hit in this block, include it into mute fragment */
00598       if (s->squelch && hit) {
00599          if (mute.end < start - s->block_size) {
00600             /* There is a gap between fragments */
00601             mute_fragment(dsp, &mute);
00602             mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
00603          }
00604          mute.end = end + s->block_size;
00605       }
00606 
00607       /* Reinitialise the detector for the next block */
00608       /* Reset for the next block */
00609       goertzel_reset(&s->tone);
00610 
00611       /* Advance to the next block */
00612       s->energy = 0.0;
00613       s->samples_pending = s->block_size;
00614 
00615       amp += limit;
00616    }
00617 
00618    if (s->squelch && mute.end) {
00619       if (mute.end > samples) {
00620          s->mute_samples = mute.end - samples;
00621          mute.end = samples;
00622       }
00623       mute_fragment(dsp, &mute);
00624    }
00625 
00626    return res;
00627 }


Variable Documentation

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

Definition at line 302 of file dsp.c.

float dtmf_col[] [static]
Initial value:
{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 290 of file dsp.c.

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

Definition at line 300 of file dsp.c.

float dtmf_row[] [static]
Initial value:
{
   697.0,  770.0,  852.0,  941.0
}

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

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().

int thresholds[THRESHOLD_MAX] [static]

Definition at line 304 of file dsp.c.


Generated by  doxygen 1.6.2