Fri Jun 19 12:10:32 2009

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "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   2
#define DTMF_MISSES_TO_END   3
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_THRESHOLD   8.0e7
#define FAX_TONE_CED_DB   16
#define FAX_TONE_CED_DURATION   2600
#define FAX_TONE_CED_FREQ   2100
#define FAX_TONE_CNG_DB   16
#define FAX_TONE_CNG_DURATION   500
#define FAX_TONE_CNG_FREQ   1100
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define SAMPLE_RATE   8000
#define SAMPLES_IN_FRAME   160
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0

Enumerations

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

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static int __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
static int _dsp_init (int reload)
static void ast_digit_detect_init (digit_detect_state_t *s, int mf)
int ast_dsp_busydetect (struct ast_dsp *dsp)
 Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
 Scans for progress indication in audio.
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector.
void ast_dsp_frame_freed (struct ast_frame *fr)
 Hint that a frame from a dsp was freed.
void ast_dsp_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf.
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_init (void)
 Load dsp settings from dsp.conf.
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 char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static float dtmf_col []
static char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_row []
static float mf_tones []
static struct progress modes []
static int thresholds [THRESHOLD_MAX]


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 172 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 170 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 171 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 214 of file dsp.c.

Referenced by _dsp_init(), conf_exec(), find_conf(), and load_config_meetme().

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

Referenced by ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

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

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 166 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 207 of file dsp.c.

Referenced by ast_dtmf_detect_init(), and dtmf_detect().

#define DTMF_HITS_TO_BEGIN   2

Definition at line 210 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_MISSES_TO_END   3

Definition at line 212 of file dsp.c.

Referenced by ast_dtmf_detect_init().

#define DTMF_NORMAL_TWIST   6.3

Definition at line 158 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 165 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 164 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)

Definition at line 162 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 155 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 168 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 157 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 156 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 191 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 190 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 189 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 183 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 182 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 181 of file dsp.c.

Referenced by ast_fax_detect_init().

#define MAX_DTMF_DIGITS   128

Definition at line 141 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 204 of file dsp.c.

Referenced by mf_detect().

#define SAMPLE_RATE   8000

Definition at line 193 of file dsp.c.

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

#define SAMPLES_IN_FRAME   160

Definition at line 201 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 129 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 128 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 117 of file dsp.c.

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

enum freq_index

Enumerator:
HZ_350  For US modes {
HZ_440 
HZ_480 
HZ_620 
HZ_950 
HZ_1400 
HZ_1800  }
HZ_425  For CR/BR modes
HZ_400  For UK mode

Definition at line 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_400 = 0
00086 };

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

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

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

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

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

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

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

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

01091 {
01092    int accum;
01093    int x;
01094    int res = 0;
01095 
01096    if (!len)
01097       return 0;
01098    accum = 0;
01099    for (x=0;x<len; x++) 
01100       accum += abs(s[x]);
01101    accum /= len;
01102    if (accum < dsp->threshold) {
01103       /* Silent */
01104       dsp->totalsilence += len/8;
01105 #ifdef DEBUG_DSP_BUSYDETECT
01106       fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum);
01107 #endif
01108       if (dsp->totalnoise) {
01109          /* Move and save history */
01110          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicnoise[0]));
01111          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01112          /* check if previous tone differs BUSY_PERCENT from the one before it */
01113          int tone1 = dsp->historicnoise[DSP_HISTORY - 1];
01114          int tone2 = dsp->historicnoise[DSP_HISTORY - 2];
01115          if (tone1 < tone2) {
01116            if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2)
01117                dsp->busymaybe = 1;
01118            else
01119                dsp->busymaybe = 0;
01120          } else {
01121            if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2)
01122                dsp->busymaybe = 1;
01123             else
01124                dsp->busymaybe = 0;
01125          }
01126       }
01127       dsp->totalnoise = 0;
01128       res = 1;
01129    } else {
01130       /* Not silent */
01131       dsp->totalnoise += len/8;
01132 #ifdef DEBUG_DSP_BUSYDETECT
01133       fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum);
01134 #endif     
01135       if (dsp->totalsilence) {
01136          /* Move and save history */
01137          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicsilence[0]));
01138          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01139       }
01140       dsp->totalsilence = 0;
01141    }
01142    if (totalsilence)
01143       *totalsilence = dsp->totalsilence;
01144    if (totalnoise)
01145       *totalnoise = dsp->totalnoise;
01146    return res;
01147 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1670 of file dsp.c.

References ast_config_destroy(), ast_config_load2(), ast_log(), ast_variable_retrieve(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, THRESHOLD_SILENCE, and thresholds.

Referenced by ast_dsp_init(), and ast_dsp_reload().

01671 {
01672    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01673    struct ast_config *cfg;
01674 
01675    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01676 
01677    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
01678       const char *value;
01679 
01680       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01681       if (value && sscanf(value, "%d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01682          ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01683          thresholds[THRESHOLD_SILENCE] = 256;
01684       } else if (!value)
01685          thresholds[THRESHOLD_SILENCE] = 256;
01686 
01687       ast_config_destroy(cfg);
01688    }
01689    return 0;
01690 }

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

Definition at line 510 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_digitmode().

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

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

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

Referenced by ast_dsp_process().

01150 {
01151    int res = 0, x;
01152    int avgsilence = 0, hitsilence = 0;
01153    int avgtone = 0, hittone = 0;
01154 #ifdef DEBUG_DSP_BUSYDETECT
01155    char buf[16];
01156    char silence_list[64]="", tone_list[64]="";
01157 #endif
01158    
01159    if (!dsp->busymaybe)
01160       return res;
01161    dsp->busymaybe = 0;
01162 
01163    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01164       avgsilence += dsp->historicsilence[x];
01165       avgtone += dsp->historicnoise[x];
01166    }
01167    avgsilence /= dsp->busycount;
01168    avgtone /= dsp->busycount;
01169 #ifdef DEBUG_DSP_BUSYDETECT
01170    sprintf(silence_list,"Silences: ");
01171    sprintf(tone_list,"Tones:    ");
01172 #endif
01173    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01174 #ifdef DEBUG_DSP_BUSYDETECT
01175       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01176       strcat(silence_list, buf);
01177       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01178       strcat(tone_list, buf); 
01179 #endif
01180       if (!dsp->busytoneonly) {
01181          if (avgsilence > dsp->historicsilence[x]) {
01182             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01183                hitsilence++;
01184          } else {
01185             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01186                hitsilence++;
01187          }
01188       }
01189       if (avgtone > dsp->historicnoise[x]) {
01190          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01191             hittone++;
01192       } else {
01193          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01194             hittone++;
01195       }
01196    }
01197 #ifdef DEBUG_DSP_BUSYDETECT
01198    fprintf(stderr, "BUSY DETECTOR\n");   
01199    fprintf(stderr, "%s\n", tone_list);
01200    fprintf(stderr, "%s\n", silence_list)
01201 #endif
01202    if ((dsp->busytoneonly || 
01203        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01204       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01205       if (dsp->busycompare) {
01206            if (dsp->busytoneonly) {
01207              res = 1;
01208             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01209          } else {
01210               if (avgtone > avgsilence) {
01211                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01212                     res = 1;
01213             } else {
01214                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01215                    res = 1;
01216             }
01217          }
01218       } else {
01219          res = 1;
01220       }
01221    }
01222    /* If we know the expected busy tone length, check we are in the range */
01223    if (res && (dsp->busy_tonelength > 0)) {
01224       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01225 #ifdef BUSYDETECT_DEBUG
01226          if(option_debug) {
01227             ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength);
01228          }
01229 #endif
01230          res = 0;
01231       }
01232    }
01233    /* If we know the expected busy tone silent-period length, check we are in the range */
01234    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01235       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01236 #ifdef BUSYDETECT_DEBUG
01237          if(option_debug) {
01238             ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength);
01239          }
01240 #endif
01241          res = 0;
01242       }
01243    }
01244    if (res) {
01245       if (option_debug)
01246          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01247    } else {
01248       if (option_debug)
01249          ast_log(LOG_NOTICE, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01250    }
01251    return res;
01252 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1077 of file dsp.c.

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

01078 {
01079    if (inf->frametype != AST_FRAME_VOICE) {
01080       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01081       return 0;
01082    }
01083    if (inf->subclass != AST_FORMAT_SLINEAR) {
01084       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01085       return 0;
01086    }
01087    return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
01088 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1573 of file dsp.c.

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

Referenced by ss_thread().

01574 {
01575    int i;
01576    
01577    dsp->dtmf_began = 0;
01578    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01579       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01580       /* Reinitialise the detector for the next block */
01581       for (i = 0;  i < 6;  i++) {
01582          goertzel_reset(&s->tone_out[i]);
01583       }
01584       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01585       s->current_sample = 0;
01586    } else {
01587       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01588       /* Reinitialise the detector for the next block */
01589       for (i = 0;  i < 4;  i++) {
01590          goertzel_reset(&s->row_out[i]);
01591          goertzel_reset(&s->col_out[i]);
01592       }
01593       s->lasthit = s->current_hit = 0;
01594       s->energy = 0.0;
01595       s->current_sample = 0;
01596       s->hits = 0;
01597       s->misses = 0;
01598    }
01599 
01600    dsp->digit_state.digits[0] = '\0';
01601    dsp->digit_state.current_digits = 0;
01602 }

void ast_dsp_frame_freed ( struct ast_frame fr  ) 

Hint that a frame from a dsp was freed.

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

Returns:
nothing

Definition at line 1707 of file dsp.c.

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

Referenced by ast_frame_free().

01708 {
01709    struct ast_dsp *dsp;
01710 
01711    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01712 
01713    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01714 
01715    if (!dsp->destroy)
01716       return;
01717    
01718    ast_dsp_free(dsp);
01719 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1521 of file dsp.c.

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

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

01522 {
01523    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01524       /* If this flag is still set, that means that the dsp's destruction 
01525        * been torn down, while we still have a frame out there being used.
01526        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01527        * will get destroyed, too. */
01528 
01529       dsp->destroy = 1;
01530 
01531       return;
01532    }
01533    ast_free(dsp);
01534 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1665 of file dsp.c.

References ast_dsp::tcount.

01666 {
01667    return dsp->tcount;
01668 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1692 of file dsp.c.

References thresholds.

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

01693 {
01694    return thresholds[which];
01695 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1660 of file dsp.c.

References ast_dsp::tstate.

01661 {
01662    return dsp->tstate;
01663 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1697 of file dsp.c.

References _dsp_init().

Referenced by main().

01698 {
01699    return _dsp_init(0);
01700 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1482 of file dsp.c.

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

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

01483 {
01484    struct ast_dsp *dsp;
01485    
01486    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01487       dsp->threshold = DEFAULT_THRESHOLD;
01488       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01489       dsp->busycount = DSP_HISTORY;
01490       dsp->digitmode = DSP_DIGITMODE_DTMF;
01491       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01492       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01493 #ifdef BUSYDETECT_TONEONLY
01494       dsp->busytoneonly = 1;
01495 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01496 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01497 #endif
01498 #else
01499    dsp->busytoneonly = 0;
01500 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01501    dsp->busycompare = 1;
01502 #else
01503    dsp->busycompare = 0;
01504 #endif
01505 #endif
01506       /* Initialize digit detector */
01507       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01508       /* Initialize initial DSP progress detect parameters */
01509       ast_dsp_prog_reset(dsp);
01510       /* Initialize fax detector */
01511       ast_fax_detect_init(dsp);
01512    }
01513    return dsp;
01514 }

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

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

Referenced by do_waiting().

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

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

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRFLAG_FROM_DSP, ast_frfree, ast_getformatname(), AST_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, chan, ast_dsp::cng_tone_state, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, 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, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame::frametype, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_channel::name, ast_frame::ptr, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01466 {
01467    int max = 0;
01468    int x;
01469    
01470    dsp->gsamp_size = modes[dsp->progmode].size;
01471    dsp->gsamps = 0;
01472    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01473       if (modes[dsp->progmode].freqs[x]) {
01474          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01475          max = x + 1;
01476       }
01477    }
01478    dsp->freqcount = max;
01479    dsp->ringtimeout= 0;
01480 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1702 of file dsp.c.

References _dsp_init().

01703 {
01704    return _dsp_init(1);
01705 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01605 {
01606    int x;
01607    
01608    dsp->totalsilence = 0;
01609    dsp->gsamps = 0;
01610    for (x=0;x<4;x++)
01611       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01612    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01613    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01614    dsp->ringtimeout= 0;
01615 }

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

References ast_dsp::busycompare.

Referenced by dahdi_new().

01554 {
01555   if (compare > 0)
01556       dsp->busycompare = 1;
01557   else
01558       dsp->busycompare = 0;
01559 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1544 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01545 {
01546    if (cadences < 4)
01547       cadences = 4;
01548    if (cadences > DSP_HISTORY)
01549       cadences = DSP_HISTORY;
01550    dsp->busycount = cadences;
01551 }

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

01562 {
01563    dsp->busy_tonelength = tonelength;
01564    if (quietlength > 0)
01565       dsp->busy_quietlength = quietlength;
01566    else 
01567      dsp->busytoneonly = 1;
01568    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01569    if( fuzzy > 0 && fuzzy < 50 ) 
01570       dsp->busy_pattern_fuzzy = fuzzy;
01571 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1641 of file dsp.c.

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

Referenced by dahdi_new().

01642 {
01643    int x;
01644    
01645    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01646       if (!strcasecmp(aliases[x].name, zone)) {
01647          dsp->progmode = aliases[x].mode;
01648          ast_dsp_prog_reset(dsp);
01649          return 0;
01650       }
01651    }
01652    return -1;
01653 }

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

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

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

01618 {
01619    int new;
01620    int old;
01621    
01622    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01623    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01624    if (old != new) {
01625       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01626       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01627    }
01628    dsp->digitmode = digitmode;
01629    return 0;
01630 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1632 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by transmit_audio().

01633 {
01634    if (dsp->faxmode != faxmode) {
01635       ast_fax_detect_init(dsp);
01636    }
01637    dsp->faxmode = faxmode;
01638    return 0;
01639 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1516 of file dsp.c.

References ast_dsp::features.

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

01517 {
01518    dsp->features = features;
01519 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1536 of file dsp.c.

References ast_dsp::threshold.

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

01537 {
01538    if (threshold < 256)
01539      dsp->threshold = 256;
01540    else
01541      dsp->threshold = threshold;
01542 }

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

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

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

01255 {
01256    short *s;
01257    int len;
01258    
01259    if (f->frametype != AST_FRAME_VOICE) {
01260       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01261       return 0;
01262    }
01263    if (f->subclass != AST_FORMAT_SLINEAR) {
01264       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01265       return 0;
01266    }
01267    s = f->data.ptr;
01268    len = f->datalen/2;
01269    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01270 }

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01656 {
01657    return (dsp->mute_fragments > 0);
01658 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]

Definition at line 480 of file dsp.c.

References DTMF_GSIZE, DTMF_HITS_TO_BEGIN, DTMF_MISSES_TO_END, goertzel_init(), and s.

Referenced by ast_digit_detect_init().

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

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

Definition at line 474 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().

static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

Definition at line 499 of file dsp.c.

References goertzel_init(), and s.

Referenced by ast_digit_detect_init().

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

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

Definition at line 414 of file dsp.c.

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

Referenced by ast_fax_detect_init().

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

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

References DTMF_GSIZE, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, fragment_t::end, goertzel_result(), goertzel_sample(), and s.

Referenced by ast_dsp_process().

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

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

Definition at line 339 of file dsp.c.

References cos, s, and SAMPLE_RATE.

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

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

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

Definition at line 346 of file dsp.c.

References s.

Referenced by ast_dsp_digitreset(), and tone_detect().

00347 {
00348    s->v2 = s->v3 = s->chunky = 0.0;
00349 }

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

Definition at line 330 of file dsp.c.

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

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

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

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

Definition at line 304 of file dsp.c.

References s.

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

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

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

Definition at line 321 of file dsp.c.

References goertzel_sample(), and s.

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

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

References bell_mf_positions, BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, fragment_t::end, goertzel_result(), goertzel_sample(), MF_GSIZE, s, and store_digit().

Referenced by ast_dsp_process().

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

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

Definition at line 404 of file dsp.c.

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

Referenced by tone_detect().

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

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

Definition at line 932 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

00933 {
00934    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
00935    /* Make sure absolute levels are high enough */
00936    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
00937       return 0;
00938    /* Amplify ignored stuff */
00939    i2 *= TONE_THRESH;
00940    i1 *= TONE_THRESH;
00941    e *= TONE_THRESH;
00942    /* Check first tone */
00943    if ((p1 < i1) || (p1 < i2) || (p1 < e))
00944       return 0;
00945    /* And second */
00946    if ((p2 < i1) || (p2 < i2) || (p2 < e))
00947       return 0;
00948    /* Guess it's there... */
00949    return 1;
00950 }

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

Definition at line 625 of file dsp.c.

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

Referenced by mf_detect().

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

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

Definition at line 523 of file dsp.c.

References ast_debug, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mute_fragment(), ast_frame::ptr, s, and fragment_t::start.

Referenced by ast_dsp_process().

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


Variable Documentation

struct progalias aliases[] [static]

Referenced by ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 300 of file dsp.c.

Referenced by mf_detect().

float dtmf_col[] [static]

Initial value:

{
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 288 of file dsp.c.

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

Definition at line 298 of file dsp.c.

float dtmf_row[] [static]

Initial value:

{
   697.0,  770.0,  852.0,  941.0
}

Definition at line 284 of file dsp.c.

float mf_tones[] [static]

Initial value:

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

Definition at line 293 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset(), and setrem().

int thresholds[THRESHOLD_MAX] [static]

Definition at line 302 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().


Generated on Fri Jun 19 12:10:33 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7