Mon Mar 19 11:30:47 2012

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 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   4
#define DTMF_MISSES_TO_END   4
#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 = 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.
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.
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 const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static const float dtmf_row []
static const 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.

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 172 of file dsp.c.

#define BELL_MF_TWIST   4.0

Definition at line 173 of file dsp.c.

#define CONFIG_FILE_NAME   "dsp.conf"

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

#define DTMF_HITS_TO_BEGIN   4

Definition at line 212 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_MISSES_TO_END   4

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


Enumeration Type Documentation

enum busy_detect

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

Definition at line 119 of file dsp.c.

00119                  {
00120    BUSY_PERCENT = 10,      /*!< The percentage difference between the two last tone periods */
00121    BUSY_PAT_PERCENT = 8,   /*!< 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 = 150,       /*!< Busy must be at least 150 ms in half-cadence */
00124    BUSY_MAX = 600          /*!< Busy can't be longer than 600 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 };

enum gsamp_thresh

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

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

Definition at line 134 of file dsp.c.

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

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

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

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

Referenced by ast_dsp_call_progress().

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

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

Definition at line 1116 of file dsp.c.

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

Referenced by ast_dsp_noise(), ast_dsp_process(), and ast_dsp_silence().

01117 {
01118    int accum;
01119    int x;
01120    int res = 0;
01121 
01122    if (!len) {
01123       return 0;
01124    }
01125    accum = 0;
01126    for (x = 0; x < len; x++) {
01127       accum += abs(s[x]);
01128    }
01129    accum /= len;
01130    if (accum < dsp->threshold) {
01131       /* Silent */
01132       dsp->totalsilence += len / 8;
01133 #ifdef DEBUG_DSP_BUSYDETECT
01134       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01135 #endif
01136       if (dsp->totalnoise) {
01137          /* Move and save history */
01138          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0]));
01139          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01140          /* check if previous tone differs BUSY_PERCENT from the one before it */
01141          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01142          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01143          if (tone1 < tone2) {
01144            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01145                dsp->busymaybe = 1;
01146            else
01147                dsp->busymaybe = 0;
01148          } else {
01149            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01150                dsp->busymaybe = 1;
01151             else
01152                dsp->busymaybe = 0;
01153          }
01154       }
01155       dsp->totalnoise = 0;
01156       res = 1;
01157    } else {
01158       /* Not silent */
01159       dsp->totalnoise += len / 8;
01160 #ifdef DEBUG_DSP_BUSYDETECT
01161       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01162 #endif     
01163       if (dsp->totalsilence) {
01164          /* Move and save history */
01165          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0]));
01166          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01167       }
01168       dsp->totalsilence = 0;
01169    }
01170    if (totalsilence) {
01171       *totalsilence = dsp->totalsilence;
01172    }
01173    if (totalnoise) {
01174       *totalnoise = dsp->totalnoise;
01175    }
01176    return res;
01177 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1721 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_variable_retrieve(), ast_verb, CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, THRESHOLD_SILENCE, and value.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01722 {
01723    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01724    struct ast_config *cfg;
01725 
01726    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01727    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01728       ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD);
01729       thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01730       return 0;
01731    }
01732 
01733    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01734       return 0;
01735    }
01736 
01737    if (cfg) {
01738       const char *value;
01739 
01740       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01741       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01742          ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01743          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01744       } else if (!value) {
01745          thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01746       }
01747 
01748       ast_config_destroy(cfg);
01749    }
01750    return 0;
01751 }

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

Definition at line 513 of file dsp.c.

References ast_dtmf_detect_init(), ast_mf_detect_init(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, digit_detect_state_t::dtmf, digit_detect_state_t::lost_digits, digit_detect_state_t::mf, and digit_detect_state_t::td.

Referenced by ast_dsp_new(), and ast_dsp_set_digitmode().

00514 {
00515    s->current_digits = 0;
00516    s->detected_digits = 0;
00517    s->lost_digits = 0;
00518    s->digits[0] = '\0';
00519 
00520    if (mf) {
00521       ast_mf_detect_init(&s->td.mf);
00522    } else {
00523       ast_dtmf_detect_init(&s->td.dtmf);
00524    }
00525 }

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 1179 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.

01180 {
01181    int res = 0, x;
01182    int avgsilence = 0, hitsilence = 0;
01183    int avgtone = 0, hittone = 0;
01184 #ifdef DEBUG_DSP_BUSYDETECT
01185    char buf[16];
01186    char silence_list[64]="", tone_list[64]="";
01187 #endif
01188    
01189    if (!dsp->busymaybe) {
01190       return res;
01191    }
01192    dsp->busymaybe = 0;
01193 
01194    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01195       avgsilence += dsp->historicsilence[x];
01196       avgtone += dsp->historicnoise[x];
01197    }
01198    avgsilence /= dsp->busycount;
01199    avgtone /= dsp->busycount;
01200 #ifdef DEBUG_DSP_BUSYDETECT
01201    sprintf(silence_list,"Silences: ");
01202    sprintf(tone_list,"Tones:    ");
01203 #endif
01204    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01205 #ifdef DEBUG_DSP_BUSYDETECT
01206       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01207       strcat(silence_list, buf);
01208       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01209       strcat(tone_list, buf); 
01210 #endif
01211       if (!dsp->busytoneonly) {
01212          if (avgsilence > dsp->historicsilence[x]) {
01213             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01214                hitsilence++;
01215          } else {
01216             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01217                hitsilence++;
01218          }
01219       }
01220       if (avgtone > dsp->historicnoise[x]) {
01221          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01222             hittone++;
01223          }
01224       } else {
01225          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01226             hittone++;
01227          }
01228       }
01229    }
01230 #ifdef DEBUG_DSP_BUSYDETECT
01231    fprintf(stderr, "BUSY DETECTOR\n");   
01232    fprintf(stderr, "%s\n", tone_list);
01233    fprintf(stderr, "%s\n", silence_list)
01234 #endif
01235    if ((dsp->busytoneonly || 
01236        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01237       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01238       if (dsp->busycompare) {
01239            if (dsp->busytoneonly) {
01240              res = 1;
01241             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01242          } else {
01243               if (avgtone > avgsilence) {
01244                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01245                     res = 1;
01246             } else {
01247                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01248                    res = 1;
01249             }
01250          }
01251       } else {
01252          res = 1;
01253       }
01254    }
01255    /* If we know the expected busy tone length, check we are in the range */
01256    if (res && (dsp->busy_tonelength > 0)) {
01257       if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) {
01258 #ifdef BUSYDETECT_DEBUG
01259          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01260             avgtone, dsp->busy_tonelength);
01261 #endif
01262          res = 0;
01263       }
01264    }
01265    /* If we know the expected busy tone silent-period length, check we are in the range */
01266    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01267       if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) {
01268 #ifdef BUSYDETECT_DEBUG
01269       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01270          avgsilence, dsp->busy_quietlength);
01271 #endif
01272          res = 0;
01273       }
01274    }
01275    if (res) {
01276       if (option_debug)
01277          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01278    } else {
01279       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01280    }
01281    return res;
01282 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

01624 {
01625    int i;
01626    
01627    dsp->dtmf_began = 0;
01628    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01629       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01630       /* Reinitialise the detector for the next block */
01631       for (i = 0;  i < 6;  i++) {
01632          goertzel_reset(&s->tone_out[i]);
01633       }
01634       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01635       s->current_sample = 0;
01636    } else {
01637       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01638       /* Reinitialise the detector for the next block */
01639       for (i = 0;  i < 4;  i++) {
01640          goertzel_reset(&s->row_out[i]);
01641          goertzel_reset(&s->col_out[i]);
01642       }
01643       s->lasthit = s->current_hit = 0;
01644       s->energy = 0.0;
01645       s->current_sample = 0;
01646       s->hits = 0;
01647       s->misses = 0;
01648    }
01649 
01650    dsp->digit_state.digits[0] = '\0';
01651    dsp->digit_state.current_digits = 0;
01652 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1579 of file dsp.c.

References ast_free.

Referenced by __ast_play_and_record(), __oh323_destroy(), analog_ss_thread(), background_detect_exec(), chan_list_destructor(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_session(), disable_dsp_detect(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), my_all_subchannels_hungup(), my_dsp_set_digitmode(), sip_rtp_read(), and unload_module().

01580 {
01581    ast_free(dsp);
01582 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1716 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01717 {
01718    return dsp->tcount;
01719 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1753 of file dsp.c.

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

01754 {
01755    return thresholds[which];
01756 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1711 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01712 {
01713    return dsp->tstate;
01714 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1758 of file dsp.c.

References _dsp_init().

Referenced by main().

01759 {
01760    return _dsp_init(0);
01761 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1536 of file dsp.c.

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_HISTORY, 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 store_config().

01537 {
01538    struct ast_dsp *dsp;
01539    
01540    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01541       dsp->threshold = DEFAULT_THRESHOLD;
01542       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01543       dsp->busycount = DSP_HISTORY;
01544       dsp->digitmode = DSP_DIGITMODE_DTMF;
01545       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01546       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01547 #ifdef BUSYDETECT_TONEONLY
01548       dsp->busytoneonly = 1;
01549 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01550 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01551 #endif
01552 #else
01553    dsp->busytoneonly = 0;
01554 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01555    dsp->busycompare = 1;
01556 #else
01557    dsp->busycompare = 0;
01558 #endif
01559 #endif
01560       /* Initialize digit detector */
01561       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01562       dsp->display_inband_dtmf_warning = 1;
01563       /* Initialize initial DSP progress detect parameters */
01564       ast_dsp_prog_reset(dsp);
01565       /* Initialize fax detector */
01566       ast_fax_detect_init(dsp);
01567    }
01568    return dsp;
01569 }

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

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

Referenced by do_waiting().

01303 {
01304        short *s;
01305        int len;
01306 
01307        if (f->frametype != AST_FRAME_VOICE) {
01308                ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n");
01309                return 0;
01310        }
01311        if (f->subclass.codec != AST_FORMAT_SLINEAR) {
01312                ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n");
01313                return 0;
01314        }
01315        s = f->data.ptr;
01316        len = f->datalen/2;
01317        return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise);
01318 }

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

Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.

Definition at line 1321 of file dsp.c.

References __ast_dsp_silence_noise(), AST_ALAW, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_getformatname(), ast_log(), AST_MULAW, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::features, ast_frame::frametype, len(), LOG_WARNING, ast_dsp::mute_fragments, ast_frame::ptr, and ast_frame::subclass.

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1519 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01520 {
01521    int max = 0;
01522    int x;
01523    
01524    dsp->gsamp_size = modes[dsp->progmode].size;
01525    dsp->gsamps = 0;
01526    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01527       if (modes[dsp->progmode].freqs[x]) {
01528          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01529          max = x + 1;
01530       }
01531    }
01532    dsp->freqcount = max;
01533    dsp->ringtimeout= 0;
01534 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1763 of file dsp.c.

References _dsp_init().

01764 {
01765    return _dsp_init(1);
01766 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01655 {
01656    int x;
01657    
01658    dsp->totalsilence = 0;
01659    dsp->gsamps = 0;
01660    for (x = 0; x < 4; x++) {
01661       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01662    }
01663    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01664    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01665    dsp->ringtimeout= 0;
01666 }

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

References ast_dsp::busycompare.

Referenced by dahdi_new().

01604 {
01605   if (compare > 0)
01606       dsp->busycompare = 1;
01607   else
01608       dsp->busycompare = 0;
01609 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1592 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01593 {
01594    if (cadences < 4) {
01595       cadences = 4;
01596    }
01597    if (cadences > DSP_HISTORY) {
01598       cadences = DSP_HISTORY;
01599    }
01600    dsp->busycount = cadences;
01601 }

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

01612 {
01613    dsp->busy_tonelength = tonelength;
01614    if (quietlength > 0)
01615       dsp->busy_quietlength = quietlength;
01616    else 
01617      dsp->busytoneonly = 1;
01618    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01619    if( fuzzy > 0 && fuzzy < 50 ) 
01620       dsp->busy_pattern_fuzzy = fuzzy;
01621 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1692 of file dsp.c.

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

Referenced by dahdi_new().

01693 {
01694    int x;
01695    
01696    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01697       if (!strcasecmp(aliases[x].name, zone)) {
01698          dsp->progmode = aliases[x].mode;
01699          ast_dsp_prog_reset(dsp);
01700          return 0;
01701       }
01702    }
01703    return -1;
01704 }

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

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

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), my_dsp_set_digitmode(), and store_config().

01669 {
01670    int new;
01671    int old;
01672    
01673    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01674    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01675    if (old != new) {
01676       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01677       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01678    }
01679    dsp->digitmode = digitmode;
01680    return 0;
01681 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1683 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01684 {
01685    if (dsp->faxmode != faxmode) {
01686       ast_fax_detect_init(dsp);
01687    }
01688    dsp->faxmode = faxmode;
01689    return 0;
01690 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1571 of file dsp.c.

References ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_DIGIT_DETECT, and ast_dsp::features.

Referenced by __oh323_new(), dahdi_handle_dtmf(), dahdi_new(), dahdi_read(), dahdi_setoption(), disable_dtmf_detect(), enable_dsp_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), my_handle_dtmf(), my_pri_open_media(), read_config(), sip_rtp_read(), and store_config().

01572 {
01573    dsp->features = features;
01574    if (!(features & DSP_FEATURE_DIGIT_DETECT)) {
01575       dsp->display_inband_dtmf_warning = 0;
01576    }
01577 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1584 of file dsp.c.

References ast_dsp::threshold.

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

01585 {
01586    if (threshold < 256)
01587      dsp->threshold = 256;
01588    else
01589      dsp->threshold = threshold;
01590 }

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

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

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

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

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01707 {
01708    return (dsp->mute_fragments > 0);
01709 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 483 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_HITS_TO_BEGIN, DTMF_MISSES_TO_END, dtmf_detect_state_t::energy, goertzel_init(), 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, and dtmf_detect_state_t::row_out.

Referenced by ast_digit_detect_init().

00484 {
00485    int i;
00486 
00487    s->lasthit = 0;
00488    s->current_hit = 0;
00489    for (i = 0;  i < 4;  i++) {
00490       goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE);
00491       goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE);
00492       s->energy = 0.0;
00493    }
00494    s->current_sample = 0;
00495    s->hits = 0;
00496    s->misses = 0;
00497 
00498    s->hits_to_begin = DTMF_HITS_TO_BEGIN;
00499    s->misses_to_end = DTMF_MISSES_TO_END;
00500 }

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

Definition at line 477 of file dsp.c.

References ast_tone_detect_init(), ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, and FAX_TONE_CNG_FREQ.

Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

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

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

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

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

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

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

References dtmf_detect_state_t::col_out, 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, dtmf_detect_state_t::energy, goertzel_result(), goertzel_sample(), mute, dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, and digit_detect_state_t::td.

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

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

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

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(), and dtmf_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 794 of file dsp.c.

References mf_detect_state_t::current_sample, goertzel_sample(), digit_detect_state_t::mf, MF_GSIZE, mute, mf_detect_state_t::mute_samples, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

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

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

Definition at line 407 of file dsp.c.

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

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

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

Definition at line 942 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

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

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

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

Definition at line 527 of file dsp.c.

References tone_detect_state_t::energy, goertzel_sample(), mute, tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, and tone_detect_state_t::tone.

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


Variable Documentation

struct progalias aliases[] [static]

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

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

const float dtmf_col[] [static]

Initial value:

 {
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 296 of file dsp.c.

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

Definition at line 302 of file dsp.c.

const float dtmf_row[] [static]

Initial value:

 {
   697.0,  770.0,  852.0,  941.0
}

Definition at line 293 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 299 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 on Mon Mar 19 11:30:47 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7