Tue Aug 20 16:35:02 2013

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"

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 DEF_DTMF_HITS_TO_BEGIN   2
#define DEF_DTMF_MISSES_TO_END   3
#define DEF_DTMF_NORMAL_TWIST   6.31
#define DEF_DTMF_REVERSE_TWIST   2.51
#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31
#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98
#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_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#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 = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150,
  BUSY_MAX = 600
}
enum  freq_index {
  HZ_350 = 0, HZ_440, HZ_480, HZ_620,
  HZ_950, HZ_1400, HZ_1800, HZ_425 = 0,
  HZ_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_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_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
 Set expected lengths of the busy tones.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
int ast_dsp_set_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 const char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static const int DEFAULT_SILENCE_THRESHOLD = 256
 The default silence threshold we will use if an alternate configured value is not present or is invalid.
static const float dtmf_col []
static int dtmf_hits_to_begin
static int dtmf_misses_to_end
static float dtmf_normal_twist
static const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_reverse_twist
static const float dtmf_row []
static const float mf_tones []
static struct progress modes []
static float relax_dtmf_normal_twist
static float relax_dtmf_reverse_twist
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 184 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 182 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 183 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 237 of file dsp.c.

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 224 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 229 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_NORMAL_TWIST   6.31

Definition at line 165 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_REVERSE_TWIST   2.51

Definition at line 172 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31

Definition at line 166 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98

Definition at line 173 of file dsp.c.

Referenced by _dsp_init().

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

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

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

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 178 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 219 of file dsp.c.

Referenced by ast_dtmf_detect_init(), and dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 177 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 176 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 161 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 180 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 163 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 162 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 203 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 202 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 201 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 195 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 194 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 193 of file dsp.c.

Referenced by ast_fax_detect_init().

#define MAX_DTMF_DIGITS   128

Definition at line 147 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 216 of file dsp.c.

Referenced by ast_mf_detect_init(), and mf_detect().

#define SAMPLE_RATE   8000

Definition at line 205 of file dsp.c.

#define SAMPLES_IN_FRAME   160

Definition at line 213 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 135 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 134 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 tone periods

BUSY_PAT_PERCENT 

The percentage difference between measured and actual pattern

BUSY_THRESHOLD 

Max number of ms difference between max and min times in busy

BUSY_MIN 

Busy must be at least 150 ms in half-cadence

BUSY_MAX 

Busy can't be longer than 600 ms in half-cadence

Definition at line 123 of file dsp.c.

00123                  {
00124    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last tone periods */
00125    BUSY_PAT_PERCENT = 8,   /*!< The percentage difference between measured and actual pattern */
00126    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00127    BUSY_MIN = 150,       /*!< Busy must be at least 150 ms in half-cadence */
00128    BUSY_MAX = 600          /*!< Busy can't be longer than 600 ms in half-cadence */
00129 };

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

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

enum gsamp_size

Number of goertzels for progress detect

Enumerator:
GSAMP_SIZE_NA 

North America - 350, 440, 480, 620, 950, 1400, 1800 Hz

GSAMP_SIZE_CR 

Costa Rica, Brazil - Only care about 425 Hz

GSAMP_SIZE_UK 

UK disconnect goertzel feed - should trigger 400hz

Definition at line 63 of file dsp.c.

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

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

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

enum prog_mode
Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 69 of file dsp.c.

00069                {
00070    PROG_MODE_NA = 0,
00071    PROG_MODE_CR,
00072    PROG_MODE_UK
00073 };


Function Documentation

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

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

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

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

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

01188 {
01189    int accum;
01190    int x;
01191    int res = 0;
01192 
01193    if (!len) {
01194       return 0;
01195    }
01196    accum = 0;
01197    for (x = 0; x < len; x++) {
01198       accum += abs(s[x]);
01199    }
01200    accum /= len;
01201    if (accum < dsp->threshold) {
01202       /* Silent */
01203       dsp->totalsilence += len / 8;
01204 #ifdef DEBUG_DSP_BUSYDETECT
01205       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01206 #endif
01207       if (dsp->totalnoise) {
01208          /* Move and save history */
01209          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0]));
01210          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01211          /* check if previous tone differs BUSY_PERCENT from the one before it */
01212          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01213          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01214          if (tone1 < tone2) {
01215            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01216                dsp->busymaybe = 1;
01217            else
01218                dsp->busymaybe = 0;
01219          } else {
01220            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01221                dsp->busymaybe = 1;
01222             else
01223                dsp->busymaybe = 0;
01224          }
01225       }
01226       dsp->totalnoise = 0;
01227       res = 1;
01228    } else {
01229       /* Not silent */
01230       dsp->totalnoise += len / 8;
01231 #ifdef DEBUG_DSP_BUSYDETECT
01232       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01233 #endif     
01234       if (dsp->totalsilence) {
01235          /* Move and save history */
01236          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0]));
01237          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01238       }
01239       dsp->totalsilence = 0;
01240    }
01241    if (totalsilence) {
01242       *totalsilence = dsp->totalsilence;
01243    }
01244    if (totalnoise) {
01245       *totalnoise = dsp->totalnoise;
01246    }
01247    return res;
01248 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1792 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_log(), ast_variable_browse(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEF_DTMF_HITS_TO_BEGIN, DEF_DTMF_MISSES_TO_END, DEF_DTMF_NORMAL_TWIST, DEF_DTMF_REVERSE_TWIST, DEF_RELAX_DTMF_NORMAL_TWIST, DEF_RELAX_DTMF_REVERSE_TWIST, LOG_WARNING, ast_variable::name, ast_variable::next, THRESHOLD_SILENCE, and ast_variable::value.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01793 {
01794    struct ast_config *cfg;
01795    struct ast_variable *v;
01796    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01797    int cfg_threshold;
01798    float cfg_twist;
01799 
01800    if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
01801       return 0;
01802    }
01803 
01804    thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01805    dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
01806    dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
01807    relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST;
01808    relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST;
01809         dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN;
01810         dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END;
01811 
01812    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01813       return 0;
01814    }
01815 
01816    for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
01817       if (!strcasecmp(v->name, "silencethreshold")) {
01818          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01819             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01820          } else if (cfg_threshold < 0) {
01821             ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
01822          } else {
01823             thresholds[THRESHOLD_SILENCE] = cfg_threshold;
01824          }
01825       } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
01826          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01827             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01828          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01829             ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
01830          } else {
01831             dtmf_normal_twist = cfg_twist;
01832          }
01833       } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
01834          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01835             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01836          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01837             ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
01838          } else {
01839             dtmf_reverse_twist = cfg_twist;
01840          }
01841       } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
01842          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01843             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01844          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01845             ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
01846          } else {
01847             relax_dtmf_normal_twist = cfg_twist;
01848          }
01849       } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
01850          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01851             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01852          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01853             ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
01854          } else {
01855             relax_dtmf_reverse_twist = cfg_twist;
01856          }
01857       } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
01858          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01859             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01860          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01861             ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
01862          } else {
01863             dtmf_hits_to_begin = cfg_threshold;
01864          }
01865       } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
01866          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01867             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01868          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01869             ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
01870          } else {
01871             dtmf_misses_to_end = cfg_threshold;
01872          }
01873       }
01874    }
01875    ast_config_destroy(cfg);
01876 
01877    return 0;
01878 }

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

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

Referenced by ast_dsp_process().

01251 {
01252    int res = 0, x;
01253    int avgsilence = 0, hitsilence = 0;
01254    int avgtone = 0, hittone = 0;
01255 #ifdef DEBUG_DSP_BUSYDETECT
01256    char buf[16];
01257    char silence_list[64]="", tone_list[64]="";
01258 #endif
01259    
01260    if (!dsp->busymaybe) {
01261       return res;
01262    }
01263    dsp->busymaybe = 0;
01264 
01265    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01266       avgsilence += dsp->historicsilence[x];
01267       avgtone += dsp->historicnoise[x];
01268    }
01269    avgsilence /= dsp->busycount;
01270    avgtone /= dsp->busycount;
01271 #ifdef DEBUG_DSP_BUSYDETECT
01272    sprintf(silence_list,"Silences: ");
01273    sprintf(tone_list,"Tones:    ");
01274 #endif
01275    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01276 #ifdef DEBUG_DSP_BUSYDETECT
01277       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01278       strcat(silence_list, buf);
01279       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01280       strcat(tone_list, buf); 
01281 #endif
01282       if (!dsp->busytoneonly) {
01283          if (avgsilence > dsp->historicsilence[x]) {
01284             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01285                hitsilence++;
01286          } else {
01287             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01288                hitsilence++;
01289          }
01290       }
01291       if (avgtone > dsp->historicnoise[x]) {
01292          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01293             hittone++;
01294          }
01295       } else {
01296          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01297             hittone++;
01298          }
01299       }
01300    }
01301 #ifdef DEBUG_DSP_BUSYDETECT
01302    fprintf(stderr, "BUSY DETECTOR\n");   
01303    fprintf(stderr, "%s\n", tone_list);
01304    fprintf(stderr, "%s\n", silence_list)
01305 #endif
01306    if ((dsp->busytoneonly || 
01307        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01308       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01309       if (dsp->busycompare) {
01310            if (dsp->busytoneonly) {
01311              res = 1;
01312             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01313          } else {
01314               if (avgtone > avgsilence) {
01315                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01316                     res = 1;
01317             } else {
01318                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01319                    res = 1;
01320             }
01321          }
01322       } else {
01323          res = 1;
01324       }
01325    }
01326    /* If we know the expected busy tone length, check we are in the range */
01327    if (res && (dsp->busy_tonelength > 0)) {
01328       if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) {
01329 #ifdef BUSYDETECT_DEBUG
01330          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01331             avgtone, dsp->busy_tonelength);
01332 #endif
01333          res = 0;
01334       }
01335    }
01336    /* If we know the expected busy tone silent-period length, check we are in the range */
01337    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01338       if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) {
01339 #ifdef BUSYDETECT_DEBUG
01340       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01341          avgsilence, dsp->busy_quietlength);
01342 #endif
01343          res = 0;
01344       }
01345    }
01346    if (res) {
01347       if (option_debug)
01348          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01349    } else {
01350       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01351    }
01352    return res;
01353 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1174 of file dsp.c.

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

01175 {
01176    if (inf->frametype != AST_FRAME_VOICE) {
01177       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01178       return 0;
01179    }
01180    if (inf->subclass.codec != AST_FORMAT_SLINEAR) {
01181       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01182       return 0;
01183    }
01184    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01185 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1694 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, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by analog_ss_thread(), and my_dsp_reset_and_flush_digits().

01695 {
01696    int i;
01697    
01698    dsp->dtmf_began = 0;
01699    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01700       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01701       /* Reinitialise the detector for the next block */
01702       for (i = 0;  i < 6;  i++) {
01703          goertzel_reset(&s->tone_out[i]);
01704       }
01705       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01706       s->current_sample = 0;
01707    } else {
01708       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01709       /* Reinitialise the detector for the next block */
01710       for (i = 0;  i < 4;  i++) {
01711          goertzel_reset(&s->row_out[i]);
01712          goertzel_reset(&s->col_out[i]);
01713       }
01714       s->lasthit = s->current_hit = 0;
01715       s->energy = 0.0;
01716       s->current_sample = 0;
01717       s->hits = 0;
01718       s->misses = 0;
01719    }
01720 
01721    dsp->digit_state.digits[0] = '\0';
01722    dsp->digit_state.current_digits = 0;
01723 }

void ast_dsp_free ( struct ast_dsp dsp  ) 
int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1787 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01788 {
01789    return dsp->tcount;
01790 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1880 of file dsp.c.

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

01881 {
01882    return thresholds[which];
01883 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1782 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01783 {
01784    return dsp->tstate;
01785 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1885 of file dsp.c.

References _dsp_init().

Referenced by main().

01886 {
01887    return _dsp_init(0);
01888 }

struct ast_dsp* ast_dsp_new ( void   )  [read]

Definition at line 1607 of file dsp.c.

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, ast_dsp::busy_pattern_fuzzy, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busytoneonly, DEFAULT_THRESHOLD, ast_dsp::digit_state, ast_dsp::digitmode, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::faxmode, ast_dsp::features, and ast_dsp::threshold.

Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), enable_dsp_detect(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), my_dsp_set_digitmode(), read_config(), and record_exec().

01608 {
01609    struct ast_dsp *dsp;
01610    
01611    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01612       dsp->threshold = DEFAULT_THRESHOLD;
01613       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01614       dsp->busycount = DSP_HISTORY;
01615       dsp->digitmode = DSP_DIGITMODE_DTMF;
01616       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01617       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01618 #ifdef BUSYDETECT_TONEONLY
01619       dsp->busytoneonly = 1;
01620 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01621 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01622 #endif
01623 #else
01624    dsp->busytoneonly = 0;
01625 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01626    dsp->busycompare = 1;
01627 #else
01628    dsp->busycompare = 0;
01629 #endif
01630 #endif
01631       /* Initialize digit detector */
01632       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01633       dsp->display_inband_dtmf_warning = 1;
01634       /* Initialize initial DSP progress detect parameters */
01635       ast_dsp_prog_reset(dsp);
01636       /* Initialize fax detector */
01637       ast_fax_detect_init(dsp);
01638    }
01639    return dsp;
01640 }

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

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

Referenced by do_waiting().

01374 {
01375        short *s;
01376        int len;
01377 
01378        if (f->frametype != AST_FRAME_VOICE) {
01379                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01380                return 0;
01381        }
01382        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01383                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01384                return 0;
01385        }
01386        s = f->data.ptr;
01387        len = f->datalen/2;
01388        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01389 }

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

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), ast_channel::_softhangup, AST_ALAW, ast_alloca, 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_TESTLAW, 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_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_frame_subclass::codec, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, digit_detect_state_t::digitlen, 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, ast_frame_subclass::integer, ast_frame::len, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_frame::ptr, SAMPLE_RATE, 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(), and sip_rtp_read().

01393 {
01394    int silence;
01395    int res;
01396    int digit = 0, fax_digit = 0;
01397    int x;
01398    short *shortdata;
01399    unsigned char *odata;
01400    int len;
01401    struct ast_frame *outf = NULL;
01402 
01403    if (!af) {
01404       return NULL;
01405    }
01406    if (af->frametype != AST_FRAME_VOICE) {
01407       return af;
01408    }
01409 
01410    odata = af->data.ptr;
01411    len = af->datalen;
01412    /* Make sure we have short data */
01413    switch (af->subclass.codec) {
01414    case AST_FORMAT_SLINEAR:
01415       shortdata = af->data.ptr;
01416       len = af->datalen / 2;
01417       break;
01418    case AST_FORMAT_ULAW:
01419    case AST_FORMAT_TESTLAW:
01420       shortdata = ast_alloca(af->datalen * 2);
01421       for (x = 0;x < len; x++) {
01422          shortdata[x] = AST_MULAW(odata[x]);
01423       }
01424       break;
01425    case AST_FORMAT_ALAW:
01426       shortdata = ast_alloca(af->datalen * 2);
01427       for (x = 0; x < len; x++) {
01428          shortdata[x] = AST_ALAW(odata[x]);
01429       }
01430       break;
01431    default:
01432       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01433       if (dsp->display_inband_dtmf_warning)
01434          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec));
01435       dsp->display_inband_dtmf_warning = 0;
01436       return af;
01437    }
01438 
01439    /* Initially we do not want to mute anything */
01440    dsp->mute_fragments = 0;
01441 
01442    /* Need to run the silence detection stuff for silence suppression and busy detection */
01443    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01444       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL);
01445    }
01446 
01447    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01448       memset(&dsp->f, 0, sizeof(dsp->f));
01449       dsp->f.frametype = AST_FRAME_NULL;
01450       ast_frfree(af);
01451       return ast_frisolate(&dsp->f);
01452    }
01453    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01454       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01455       memset(&dsp->f, 0, sizeof(dsp->f));
01456       dsp->f.frametype = AST_FRAME_CONTROL;
01457       /* Signal this as it was a channel hangup, to avoid msg "channel.c:3473 ast_waitfordigit_full: Unexpected control subclass '5'" */
01458       dsp->f.subclass.integer = AST_CONTROL_HANGUP;
01459       ast_frfree(af);
01460       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01461       return ast_frisolate(&dsp->f);
01462    }
01463 
01464    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01465       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01466          fax_digit = 'f';
01467       }
01468 
01469       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01470          fax_digit = 'e';
01471       }
01472    }
01473 
01474    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01475       if (dsp->digitmode & DSP_DIGITMODE_MF)
01476          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01477       else
01478          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01479 
01480       if (dsp->digit_state.current_digits) {
01481          int event = 0, event_len = 0;
01482          char event_digit = 0;
01483 
01484          if (!dsp->dtmf_began) {
01485             /* We have not reported DTMF_BEGIN for anything yet */
01486 
01487             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01488                event = AST_FRAME_DTMF_BEGIN;
01489                event_digit = dsp->digit_state.digits[0];
01490             }
01491             dsp->dtmf_began = 1;
01492 
01493          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01494             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01495             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01496                event = AST_FRAME_DTMF_END;
01497                event_digit = dsp->digit_state.digits[0];
01498                event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE;
01499             }
01500             memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
01501             memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
01502             dsp->digit_state.current_digits--;
01503             dsp->dtmf_began = 0;
01504 
01505             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01506                /* Reset Busy Detector as we have some confirmed activity */ 
01507                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01508                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01509                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01510             }
01511          }
01512 
01513          if (event) {
01514             memset(&dsp->f, 0, sizeof(dsp->f));
01515             dsp->f.frametype = event;
01516             dsp->f.subclass.integer = event_digit;
01517             dsp->f.len = event_len;
01518             outf = &dsp->f;
01519             goto done;
01520          }
01521       }
01522    }
01523 
01524    if (fax_digit) {
01525       /* Fax was detected - digit is either 'f' or 'e' */
01526 
01527       memset(&dsp->f, 0, sizeof(dsp->f));
01528       dsp->f.frametype = AST_FRAME_DTMF;
01529       dsp->f.subclass.integer = fax_digit;
01530       outf = &dsp->f;
01531       goto done;
01532    }
01533 
01534    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01535       res = __ast_dsp_call_progress(dsp, shortdata, len);
01536       if (res) {
01537          switch (res) {
01538          case AST_CONTROL_ANSWER:
01539          case AST_CONTROL_BUSY:
01540          case AST_CONTROL_RINGING:
01541          case AST_CONTROL_CONGESTION:
01542          case AST_CONTROL_HANGUP:
01543             memset(&dsp->f, 0, sizeof(dsp->f));
01544             dsp->f.frametype = AST_FRAME_CONTROL;
01545             dsp->f.subclass.integer = res;
01546             dsp->f.src = "dsp_progress";
01547             if (chan) 
01548                ast_queue_frame(chan, &dsp->f);
01549             break;
01550          default:
01551             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01552          }
01553       }
01554    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01555       res = __ast_dsp_call_progress(dsp, shortdata, len);
01556    }
01557 
01558 done:
01559    /* Mute fragment of the frame */
01560    for (x = 0; x < dsp->mute_fragments; x++) {
01561       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01562    }
01563 
01564    switch (af->subclass.codec) {
01565    case AST_FORMAT_SLINEAR:
01566       break;
01567    case AST_FORMAT_ULAW:
01568       for (x = 0; x < len; x++) {
01569          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01570       }
01571       break;
01572    case AST_FORMAT_ALAW:
01573       for (x = 0; x < len; x++) {
01574          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01575       }
01576       break;
01577    }
01578 
01579    if (outf) {
01580       if (chan) {
01581          ast_queue_frame(chan, af);
01582       }
01583       ast_frfree(af);
01584       return ast_frisolate(outf);
01585    } else {
01586       return af;
01587    }
01588 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01591 {
01592    int max = 0;
01593    int x;
01594    
01595    dsp->gsamp_size = modes[dsp->progmode].size;
01596    dsp->gsamps = 0;
01597    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01598       if (modes[dsp->progmode].freqs[x]) {
01599          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01600          max = x + 1;
01601       }
01602    }
01603    dsp->freqcount = max;
01604    dsp->ringtimeout= 0;
01605 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1890 of file dsp.c.

References _dsp_init().

01891 {
01892    return _dsp_init(1);
01893 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

Referenced by debug_check_frame_for_silence().

01726 {
01727    int x;
01728    
01729    dsp->totalsilence = 0;
01730    dsp->gsamps = 0;
01731    for (x = 0; x < 4; x++) {
01732       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01733    }
01734    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01735    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01736    dsp->ringtimeout= 0;
01737 }

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

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

Definition at line 1674 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

01675 {
01676   if (compare > 0)
01677       dsp->busycompare = 1;
01678   else
01679       dsp->busycompare = 0;
01680 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1663 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01664 {
01665    if (cadences < 4) {
01666       cadences = 4;
01667    }
01668    if (cadences > DSP_HISTORY) {
01669       cadences = DSP_HISTORY;
01670    }
01671    dsp->busycount = cadences;
01672 }

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

Set expected lengths of the busy tones.

Definition at line 1682 of file dsp.c.

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

Referenced by dahdi_new().

01683 {
01684    dsp->busy_tonelength = tonelength;
01685    if (quietlength > 0)
01686       dsp->busy_quietlength = quietlength;
01687    else 
01688      dsp->busytoneonly = 1;
01689    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01690    if( fuzzy > 0 && fuzzy < 50 ) 
01691       dsp->busy_pattern_fuzzy = fuzzy;
01692 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1763 of file dsp.c.

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

Referenced by dahdi_new().

01764 {
01765    int x;
01766    
01767    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01768       if (!strcasecmp(aliases[x].name, zone)) {
01769          dsp->progmode = aliases[x].mode;
01770          ast_dsp_prog_reset(dsp);
01771          return 0;
01772       }
01773    }
01774    return -1;
01775 }

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 1739 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 analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), mkintf(), and my_dsp_set_digitmode().

01740 {
01741    int new;
01742    int old;
01743    
01744    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01745    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01746    if (old != new) {
01747       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01748       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01749    }
01750    dsp->digitmode = digitmode;
01751    return 0;
01752 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1754 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01755 {
01756    if (dsp->faxmode != faxmode) {
01757       ast_fax_detect_init(dsp);
01758    }
01759    dsp->faxmode = faxmode;
01760    return 0;
01761 }

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

References ast_dsp::threshold.

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

01656 {
01657    if (threshold < 256)
01658      dsp->threshold = 256;
01659    else
01660      dsp->threshold = threshold;
01661 }

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

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

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

01356 {
01357    short *s;
01358    int len;
01359    
01360    if (f->frametype != AST_FRAME_VOICE) {
01361       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01362       return 0;
01363    }
01364    if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01365       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01366       return 0;
01367    }
01368    s = f->data.ptr;
01369    len = f->datalen/2;
01370    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01371 }

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01778 {
01779    return (dsp->mute_fragments > 0);
01780 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 501 of file dsp.c.

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

Referenced by ast_digit_detect_init().

00502 {
00503    int i;
00504 
00505    s->lasthit = 0;
00506    s->current_hit = 0;
00507    for (i = 0;  i < 4;  i++) {
00508       goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE);
00509       goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE);
00510       s->energy = 0.0;
00511    }
00512    s->current_sample = 0;
00513    s->hits = 0;
00514    s->misses = 0;
00515 }

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

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

Referenced by ast_digit_detect_init().

00518 {
00519    int i;
00520    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00521    for (i = 0;  i < 6;  i++) {
00522       goertzel_init (&s->tone_out[i], mf_tones[i], MF_GSIZE);
00523    }
00524    s->current_sample = 0;
00525    s->current_hit = 0;
00526 }

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

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

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

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

References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, digit_detect_state_t::digitlen, digit_detect_state_t::dtmf, DTMF_GSIZE, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, 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::lasthit, dtmf_detect_state_t::misses, mute, 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().

00662 {
00663    float row_energy[4];
00664    float col_energy[4];
00665    int i;
00666    int j;
00667    int sample;
00668    short samp;
00669    int best_row;
00670    int best_col;
00671    int hit;
00672    int limit;
00673    fragment_t mute = {0, 0};
00674 
00675    if (squelch && s->td.dtmf.mute_samples > 0) {
00676       mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
00677       s->td.dtmf.mute_samples -= mute.end;
00678    }
00679 
00680    hit = 0;
00681    for (sample = 0; sample < samples; sample = limit) {
00682       /* DTMF_GSIZE is optimised to meet the DTMF specs. */
00683       if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
00684          limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
00685       } else {
00686          limit = samples;
00687       }
00688       /* The following unrolled loop takes only 35% (rough estimate) of the 
00689          time of a rolled loop on the machine on which it was developed */
00690       for (j = sample; j < limit; j++) {
00691          samp = amp[j];
00692          s->td.dtmf.energy += (int32_t) samp * (int32_t) samp;
00693          /* With GCC 2.95, the following unrolled code seems to take about 35%
00694             (rough estimate) as long as a neat little 0-3 loop */
00695          goertzel_sample(s->td.dtmf.row_out, samp);
00696          goertzel_sample(s->td.dtmf.col_out, samp);
00697          goertzel_sample(s->td.dtmf.row_out + 1, samp);
00698          goertzel_sample(s->td.dtmf.col_out + 1, samp);
00699          goertzel_sample(s->td.dtmf.row_out + 2, samp);
00700          goertzel_sample(s->td.dtmf.col_out + 2, samp);
00701          goertzel_sample(s->td.dtmf.row_out + 3, samp);
00702          goertzel_sample(s->td.dtmf.col_out + 3, samp);
00703       }
00704       s->td.dtmf.current_sample += (limit - sample);
00705       if (s->td.dtmf.current_sample < DTMF_GSIZE) {
00706          continue;
00707       }
00708       /* We are at the end of a DTMF detection block */
00709       /* Find the peak row and the peak column */
00710       row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]);
00711       col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]);
00712 
00713       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
00714          row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]);
00715          if (row_energy[i] > row_energy[best_row]) {
00716             best_row = i;
00717          }
00718          col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]);
00719          if (col_energy[i] > col_energy[best_col]) {
00720             best_col = i;
00721          }
00722       }
00723       hit = 0;
00724       /* Basic signal level test and the twist test */
00725       if (row_energy[best_row] >= DTMF_THRESHOLD && 
00726           col_energy[best_col] >= DTMF_THRESHOLD &&
00727           col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
00728           row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
00729          /* Relative peak test */
00730          for (i = 0;  i < 4;  i++) {
00731             if ((i != best_col &&
00732                 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
00733                 (i != best_row 
00734                  && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
00735                break;
00736             }
00737          }
00738          /* ... and fraction of total energy test */
00739          if (i >= 4 &&
00740              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
00741             /* Got a hit */
00742             hit = dtmf_positions[(best_row << 2) + best_col];
00743          }
00744       } 
00745 
00746 /*
00747  * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03)
00748  * (40ms reference is tunable with hits_to_begin and misses_to_end)
00749  * each hit/miss is 12.75ms with DTMF_GSIZE at 102
00750  *
00751  * Character recognition: When not DRC *(1) and then
00752  *      Shall exist VSC > 40 ms (hits_to_begin)
00753  *      May exist 20 ms <= VSC <= 40 ms
00754  *      Shall not exist VSC < 20 ms
00755  *
00756  * Character recognition: When DRC and then
00757  *      Shall cease Not VSC > 40 ms (misses_to_end)
00758  *      May cease 20 ms >= Not VSC >= 40 ms
00759  *      Shall not cease Not VSC < 20 ms
00760  *
00761  * *(1) or optionally a different digit recognition condition
00762  *
00763  * Legend: VSC The continuous existence of a valid signal condition.
00764  *      Not VSC The continuous non-existence of valid signal condition.
00765  *      DRC The existence of digit recognition condition.
00766  *      Not DRC The non-existence of digit recognition condition.
00767  */
00768 
00769 /*
00770  * Example: hits_to_begin=2 misses_to_end=3
00771  * -------A last_hit=A hits=0&1
00772  * ------AA hits=2 current_hit=A misses=0       BEGIN A
00773  * -----AA- misses=1 last_hit=' ' hits=0
00774  * ----AA-- misses=2
00775  * ---AA--- misses=3 current_hit=' '            END A
00776  * --AA---B last_hit=B hits=0&1
00777  * -AA---BC last_hit=C hits=0&1
00778  * AA---BCC hits=2 current_hit=C misses=0       BEGIN C
00779  * A---BCC- misses=1 last_hit=' ' hits=0
00780  * ---BCC-C misses=0 last_hit=C hits=0&1
00781  * --BCC-CC misses=0
00782  *
00783  * Example: hits_to_begin=3 misses_to_end=2
00784  * -------A last_hit=A hits=0&1
00785  * ------AA hits=2
00786  * -----AAA hits=3 current_hit=A misses=0       BEGIN A
00787  * ----AAAB misses=1 last_hit=B hits=0&1
00788  * ---AAABB misses=2 current_hit=' ' hits=2     END A
00789  * --AAABBB hits=3 current_hit=B misses=0       BEGIN B
00790  * -AAABBBB misses=0
00791  *
00792  * Example: hits_to_begin=2 misses_to_end=2
00793  * -------A last_hit=A hits=0&1
00794  * ------AA hits=2 current_hit=A misses=0       BEGIN A
00795  * -----AAB misses=1 hits=0&1
00796  * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B
00797  * ---AABBB misses=0
00798  */
00799 
00800       if (s->td.dtmf.current_hit) {
00801          /* We are in the middle of a digit already */
00802          if (hit != s->td.dtmf.current_hit) {
00803             s->td.dtmf.misses++;
00804             if (s->td.dtmf.misses == dtmf_misses_to_end) {
00805                /* There were enough misses to consider digit ended */
00806                s->td.dtmf.current_hit = 0;
00807             }
00808          } else {
00809             s->td.dtmf.misses = 0;
00810             /* Current hit was same as last, so increment digit duration (of last digit) */
00811             s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
00812          }
00813       }
00814 
00815       /* Look for a start of a new digit no matter if we are already in the middle of some
00816          digit or not. This is because hits_to_begin may be smaller than misses_to_end
00817          and we may find begin of new digit before we consider last one ended. */
00818 
00819       if (hit != s->td.dtmf.lasthit) {
00820          s->td.dtmf.lasthit = hit;
00821          s->td.dtmf.hits = 0;
00822       }
00823       if (hit && hit != s->td.dtmf.current_hit) {
00824          s->td.dtmf.hits++;
00825          if (s->td.dtmf.hits == dtmf_hits_to_begin) {
00826             store_digit(s, hit);
00827             s->digitlen[s->current_digits - 1] = dtmf_hits_to_begin * DTMF_GSIZE;
00828             s->td.dtmf.current_hit = hit;
00829             s->td.dtmf.misses = 0;
00830          }
00831       }
00832 
00833       /* If we had a hit in this block, include it into mute fragment */
00834       if (squelch && hit) {
00835          if (mute.end < sample - DTMF_GSIZE) {
00836             /* There is a gap between fragments */
00837             mute_fragment(dsp, &mute);
00838             mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
00839          }
00840          mute.end = limit + DTMF_GSIZE;
00841       }
00842 
00843       /* Reinitialise the detector for the next block */
00844       for (i = 0; i < 4; i++) {
00845          goertzel_reset(&s->td.dtmf.row_out[i]);
00846          goertzel_reset(&s->td.dtmf.col_out[i]);
00847       }
00848       s->td.dtmf.energy = 0.0;
00849       s->td.dtmf.current_sample = 0;
00850    }
00851 
00852    if (squelch && mute.end) {
00853       if (mute.end > samples) {
00854          s->td.dtmf.mute_samples = mute.end - samples;
00855          mute.end = samples;
00856       }
00857       mute_fragment(dsp, &mute);
00858    }
00859 
00860    return (s->td.dtmf.current_hit); /* return the debounced hit */
00861 }

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

Definition at line 360 of file dsp.c.

References goertzel_state_t::chunky, cos, goertzel_state_t::fac, M_PI, 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().

00361 {
00362    s->v2 = s->v3 = s->chunky = 0.0;
00363    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE));
00364    s->samples = samples;
00365 }

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

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

00368 {
00369    s->v2 = s->v3 = s->chunky = 0.0;
00370 }

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

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

00352 {
00353    goertzel_result_t r;
00354    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00355    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00356    r.power = s->chunky * 2;
00357    return (float)r.value * (float)(1 << r.power);
00358 }

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

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

00326 {
00327    int v1;
00328    
00329    v1 = s->v2;
00330    s->v2 = s->v3;
00331    
00332    s->v3 = (s->fac * s->v2) >> 15;
00333    s->v3 = s->v3 - v1 + (sample >> s->chunky);
00334    if (abs(s->v3) > 32768) {
00335       s->chunky++;
00336       s->v3 = s->v3 >> 1;
00337       s->v2 = s->v2 >> 1;
00338    }
00339 }

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

Definition at line 341 of file dsp.c.

References goertzel_sample().

00342 {
00343    int i;
00344    
00345    for (i = 0; i < count; i++) {
00346       goertzel_sample(s, samps[i]);
00347    }
00348 }

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 863 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, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute, 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().

00865 {
00866    float energy[6];
00867    int best;
00868    int second_best;
00869    int i;
00870    int j;
00871    int sample;
00872    short samp;
00873    int hit;
00874    int limit;
00875    fragment_t mute = {0, 0};
00876 
00877    if (squelch && s->td.mf.mute_samples > 0) {
00878       mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
00879       s->td.mf.mute_samples -= mute.end;
00880    }
00881 
00882    hit = 0;
00883    for (sample = 0;  sample < samples;  sample = limit) {
00884       /* 80 is optimised to meet the MF specs. */
00885       /* XXX So then why is MF_GSIZE defined as 120? */
00886       if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
00887          limit = sample + (MF_GSIZE - s->td.mf.current_sample);
00888       } else {
00889          limit = samples;
00890       }
00891       /* The following unrolled loop takes only 35% (rough estimate) of the 
00892          time of a rolled loop on the machine on which it was developed */
00893       for (j = sample;  j < limit;  j++) {
00894          /* With GCC 2.95, the following unrolled code seems to take about 35%
00895             (rough estimate) as long as a neat little 0-3 loop */
00896          samp = amp[j];
00897          goertzel_sample(s->td.mf.tone_out, samp);
00898          goertzel_sample(s->td.mf.tone_out + 1, samp);
00899          goertzel_sample(s->td.mf.tone_out + 2, samp);
00900          goertzel_sample(s->td.mf.tone_out + 3, samp);
00901          goertzel_sample(s->td.mf.tone_out + 4, samp);
00902          goertzel_sample(s->td.mf.tone_out + 5, samp);
00903       }
00904       s->td.mf.current_sample += (limit - sample);
00905       if (s->td.mf.current_sample < MF_GSIZE) {
00906          continue;
00907       }
00908       /* We're at the end of an MF detection block.  */
00909       /* Find the two highest energies. The spec says to look for
00910          two tones and two tones only. Taking this literally -ie
00911          only two tones pass the minimum threshold - doesn't work
00912          well. The sinc function mess, due to rectangular windowing
00913          ensure that! Find the two highest energies and ensure they
00914          are considerably stronger than any of the others. */
00915       energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
00916       energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
00917       if (energy[0] > energy[1]) {
00918          best = 0;
00919          second_best = 1;
00920       } else {
00921          best = 1;
00922          second_best = 0;
00923       }
00924       /*endif*/
00925       for (i = 2; i < 6; i++) {
00926          energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
00927          if (energy[i] >= energy[best]) {
00928             second_best = best;
00929             best = i;
00930          } else if (energy[i] >= energy[second_best]) {
00931             second_best = i;
00932          }
00933       }
00934       /* Basic signal level and twist tests */
00935       hit = 0;
00936       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
00937                && energy[best] < energy[second_best]*BELL_MF_TWIST
00938                && energy[best] * BELL_MF_TWIST > energy[second_best]) {
00939          /* Relative peak test */
00940          hit = -1;
00941          for (i = 0; i < 6; i++) {
00942             if (i != best && i != second_best) {
00943                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
00944                   /* The best two are not clearly the best */
00945                   hit = 0;
00946                   break;
00947                }
00948             }
00949          }
00950       }
00951       if (hit) {
00952          /* Get the values into ascending order */
00953          if (second_best < best) {
00954             i = best;
00955             best = second_best;
00956             second_best = i;
00957          }
00958          best = best * 5 + second_best - 1;
00959          hit = bell_mf_positions[best];
00960          /* Look for two successive similar results */
00961          /* The logic in the next test is:
00962             For KP we need 4 successive identical clean detects, with
00963             two blocks of something different preceeding it. For anything
00964             else we need two successive identical clean detects, with
00965             two blocks of something different preceeding it. */
00966          if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
00967             ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
00968              (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 
00969              hit != s->td.mf.hits[0]))) {
00970             store_digit(s, hit);
00971          }
00972       }
00973 
00974 
00975       if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
00976          /* Two successive block without a hit terminate current digit */
00977          s->td.mf.current_hit = 0;
00978       }
00979 
00980       s->td.mf.hits[0] = s->td.mf.hits[1];
00981       s->td.mf.hits[1] = s->td.mf.hits[2];
00982       s->td.mf.hits[2] = s->td.mf.hits[3];
00983       s->td.mf.hits[3] = s->td.mf.hits[4];
00984       s->td.mf.hits[4] = hit;
00985 
00986       /* If we had a hit in this block, include it into mute fragment */
00987       if (squelch && hit) {
00988          if (mute.end < sample - MF_GSIZE) {
00989             /* There is a gap between fragments */
00990             mute_fragment(dsp, &mute);
00991             mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
00992          }
00993          mute.end = limit + MF_GSIZE;
00994       }
00995 
00996       /* Reinitialise the detector for the next block */
00997       for (i = 0;  i < 6;  i++)
00998          goertzel_reset(&s->td.mf.tone_out[i]);
00999       s->td.mf.current_sample = 0;
01000    }
01001 
01002    if (squelch && mute.end) {
01003       if (mute.end > samples) {
01004          s->td.mf.mute_samples = mute.end - samples;
01005          mute.end = samples;
01006       }
01007       mute_fragment(dsp, &mute);
01008    }
01009 
01010    return (s->td.mf.current_hit); /* return the debounced hit */
01011 }

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

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

00426 {
00427    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00428       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00429       return;
00430    }
00431 
00432    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00433 }

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

Definition at line 1013 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

01014 {
01015    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
01016    /* Make sure absolute levels are high enough */
01017    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
01018       return 0;
01019    }
01020    /* Amplify ignored stuff */
01021    i2 *= TONE_THRESH;
01022    i1 *= TONE_THRESH;
01023    e *= TONE_THRESH;
01024    /* Check first tone */
01025    if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
01026       return 0;
01027    }
01028    /* And second */
01029    if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
01030       return 0;
01031    }
01032    /* Guess it's there... */
01033    return 1;
01034 }

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

Definition at line 648 of file dsp.c.

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

Referenced by dtmf_detect(), and mf_detect().

00649 {
00650    s->detected_digits++;
00651    if (s->current_digits < MAX_DTMF_DIGITS) {
00652       s->digitlen[s->current_digits] = 0;
00653       s->digits[s->current_digits++] = digit;
00654       s->digits[s->current_digits] = '\0';
00655    } else {
00656       ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
00657       s->lost_digits++;
00658    }
00659 }

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

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

00543 {
00544    float tone_energy;
00545    int i;
00546    int hit = 0;
00547    int limit;
00548    int res = 0;
00549    int16_t *ptr;
00550    short samp;
00551    int start, end;
00552    fragment_t mute = {0, 0};
00553 
00554    if (s->squelch && s->mute_samples > 0) {
00555       mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
00556       s->mute_samples -= mute.end;
00557    }
00558 
00559    for (start = 0;  start < samples;  start = end) {
00560       /* Process in blocks. */
00561       limit = samples - start;
00562       if (limit > s->samples_pending) {
00563          limit = s->samples_pending;
00564       }
00565       end = start + limit;
00566 
00567       for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
00568          samp = *ptr;
00569          /* signed 32 bit int should be enough to square any possible signed 16 bit value */
00570          s->energy += (int32_t) samp * (int32_t) samp;
00571 
00572          goertzel_sample(&s->tone, samp);
00573       }
00574 
00575       s->samples_pending -= limit;
00576 
00577       if (s->samples_pending) {
00578          /* Finished incomplete (last) block */
00579          break;
00580       }
00581 
00582       tone_energy = goertzel_result(&s->tone);
00583 
00584       /* Scale to make comparable */
00585       tone_energy *= 2.0;
00586       s->energy *= s->block_size;
00587 
00588       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));
00589       hit = 0;
00590       if (tone_energy > s->energy * s->threshold) {
00591          ast_debug(10, "Hit! count=%d\n", s->hit_count);
00592          hit = 1;
00593       }
00594 
00595       if (s->hit_count) {
00596          s->hit_count++;
00597       }
00598 
00599       if (hit == s->last_hit) {
00600          if (!hit) {
00601             /* Two successive misses. Tone ended */
00602             s->hit_count = 0;
00603          } else if (!s->hit_count) {
00604             s->hit_count++;
00605          }
00606 
00607       }
00608 
00609       if (s->hit_count == s->hits_required) {
00610          ast_debug(1, "%d Hz done detected\n", s->freq);
00611          res = 1;
00612       }
00613 
00614       s->last_hit = hit;
00615 
00616       /* If we had a hit in this block, include it into mute fragment */
00617       if (s->squelch && hit) {
00618          if (mute.end < start - s->block_size) {
00619             /* There is a gap between fragments */
00620             mute_fragment(dsp, &mute);
00621             mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
00622          }
00623          mute.end = end + s->block_size;
00624       }
00625 
00626       /* Reinitialise the detector for the next block */
00627       /* Reset for the next block */
00628       goertzel_reset(&s->tone);
00629 
00630       /* Advance to the next block */
00631       s->energy = 0.0;
00632       s->samples_pending = s->block_size;
00633 
00634       amp += limit;
00635    }
00636 
00637    if (s->squelch && mute.end) {
00638       if (mute.end > samples) {
00639          s->mute_samples = mute.end - samples;
00640          mute.end = samples;
00641       }
00642       mute_fragment(dsp, &mute);
00643    }
00644 
00645    return res;
00646 }


Variable Documentation

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

Definition at line 316 of file dsp.c.

const int DEFAULT_SILENCE_THRESHOLD = 256 [static]

The default silence threshold we will use if an alternate configured value is not present or is invalid.

Definition at line 235 of file dsp.c.

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

Definition at line 309 of file dsp.c.

int dtmf_hits_to_begin [static]

Definition at line 322 of file dsp.c.

int dtmf_misses_to_end [static]

Definition at line 323 of file dsp.c.

float dtmf_normal_twist [static]

Definition at line 318 of file dsp.c.

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

Definition at line 315 of file dsp.c.

float dtmf_reverse_twist [static]

Definition at line 319 of file dsp.c.

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

Definition at line 306 of file dsp.c.

const float mf_tones[] [static]
Initial value:
 {
   700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
}

Definition at line 312 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().

float relax_dtmf_normal_twist [static]

Definition at line 320 of file dsp.c.

float relax_dtmf_reverse_twist [static]

Definition at line 321 of file dsp.c.

int thresholds[THRESHOLD_MAX] [static]

Definition at line 317 of file dsp.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1