Tue Mar 2 17:33:19 2010

Asterisk developer's documentation


dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

struct  ast_dsp
struct  digit_detect_state_t
struct  dtmf_detect_state_t
struct  fragment_t
struct  goertzel_result_t
struct  goertzel_state_t
struct  mf_detect_state_t
struct  progalias
struct  progress
struct  tone_detect_state_t

Defines

#define BELL_MF_RELATIVE_PEAK   12.6
#define BELL_MF_THRESHOLD   1.6e9
#define BELL_MF_TWIST   4.0
#define CONFIG_FILE_NAME   "dsp.conf"
#define DEFAULT_THRESHOLD   512
 This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
#define DSP_HISTORY   15
#define DTMF_2ND_HARMONIC_COL   63.1
#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)
#define DTMF_GSIZE   102
#define DTMF_HITS_TO_BEGIN   2
#define DTMF_MISSES_TO_END   3
#define DTMF_NORMAL_TWIST   6.3
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_REVERSE_TWIST   (relax ? 4.0 : 2.5)
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_THRESHOLD   8.0e7
#define FAX_TONE_CED_DB   16
#define FAX_TONE_CED_DURATION   2600
#define FAX_TONE_CED_FREQ   2100
#define FAX_TONE_CNG_DB   16
#define FAX_TONE_CNG_DURATION   500
#define FAX_TONE_CNG_FREQ   1100
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#define SAMPLE_RATE   8000
#define SAMPLES_IN_FRAME   160
#define TONE_MIN_THRESH   1e8
#define TONE_THRESH   10.0

Enumerations

enum  busy_detect {
  BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 7, BUSY_THRESHOLD = 100, BUSY_MIN = 75,
  BUSY_MAX = 3100
}
enum  freq_index {
  HZ_350 = 0, HZ_440, HZ_480, HZ_620,
  HZ_950, HZ_1400, HZ_1800, HZ_425 = 0,
  HZ_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_free (struct ast_dsp *dsp)
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter).
int ast_dsp_get_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf.
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State).
int ast_dsp_init (void)
 Load dsp settings from dsp.conf.
struct ast_dspast_dsp_new (void)
int ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
 Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
struct ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
int ast_dsp_reload (void)
 Reloads dsp settings from dsp.conf.
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength)
 Set expected lengths of the busy tone.
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
int ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode.
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set.
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set threshold value for silence.
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
int ast_dsp_was_muted (struct ast_dsp *dsp)
 Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.
static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void ast_fax_detect_init (struct ast_dsp *s)
static void ast_mf_detect_init (mf_detect_state_t *s)
static void ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp)
static int dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void goertzel_init (goertzel_state_t *s, float freq, int samples)
static void goertzel_reset (goertzel_state_t *s)
static float goertzel_result (goertzel_state_t *s)
static void goertzel_sample (goertzel_state_t *s, short sample)
static void goertzel_update (goertzel_state_t *s, short *samps, int count)
static int mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void mute_fragment (struct ast_dsp *dsp, fragment_t *fragment)
static int pair_there (float p1, float p2, float i1, float i2, float e)
static void store_digit (digit_detect_state_t *s, char digit)
static int tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)

Variables

static struct progalias aliases []
static char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static float dtmf_col []
static char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_row []
static float mf_tones []
static struct progress modes []
static int thresholds [THRESHOLD_MAX]

Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>
Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

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

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 128 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().


Enumeration Type Documentation

Enumerator:
BUSY_PERCENT 

The percentage difference between the two last silence periods

BUSY_PAT_PERCENT 

The percentage difference between measured and actual pattern

BUSY_THRESHOLD 

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

BUSY_MIN 

Busy must be at least 80 ms in half-cadence

BUSY_MAX 

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

Definition at line 117 of file dsp.c.

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

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

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

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

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

Definition at line 1087 of file dsp.c.

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

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

01088 {
01089    int accum;
01090    int x;
01091    int res = 0;
01092 
01093    if (!len)
01094       return 0;
01095    accum = 0;
01096    for (x=0;x<len; x++) 
01097       accum += abs(s[x]);
01098    accum /= len;
01099    if (accum < dsp->threshold) {
01100       /* Silent */
01101       dsp->totalsilence += len/8;
01102       if (dsp->totalnoise) {
01103          /* Move and save history */
01104          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
01105          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01106 /* we don't want to check for busydetect that frequently */
01107 #if 0
01108          dsp->busymaybe = 1;
01109 #endif
01110       }
01111       dsp->totalnoise = 0;
01112       res = 1;
01113    } else {
01114       /* Not silent */
01115       dsp->totalnoise += len/8;
01116       if (dsp->totalsilence) {
01117          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01118          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01119          /* Move and save history */
01120          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
01121          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01122          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01123          if (silence1 < silence2) {
01124             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
01125                dsp->busymaybe = 1;
01126             else 
01127                dsp->busymaybe = 0;
01128          } else {
01129             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
01130                dsp->busymaybe = 1;
01131             else 
01132                dsp->busymaybe = 0;
01133          }
01134       }
01135       dsp->totalsilence = 0;
01136    }
01137    if (totalsilence)
01138       *totalsilence = dsp->totalsilence;
01139    if (totalnoise)
01140       *totalnoise = dsp->totalnoise;
01141    return res;
01142 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1619 of file dsp.c.

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

Referenced by ast_dsp_init(), and ast_dsp_reload().

01620 {
01621    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01622    struct ast_config *cfg;
01623 
01624    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01625 
01626    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
01627       const char *value;
01628 
01629       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01630       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01631          ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01632          thresholds[THRESHOLD_SILENCE] = 256;
01633       } else if (!value)
01634          thresholds[THRESHOLD_SILENCE] = 256;
01635 
01636       ast_config_destroy(cfg);
01637    }
01638    return 0;
01639 }

static void ast_digit_detect_init ( digit_detect_state_t s,
int  mf 
) [static]
int ast_dsp_busydetect ( struct ast_dsp dsp  ) 

Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.

Definition at line 1144 of file dsp.c.

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

Referenced by ast_dsp_process().

01145 {
01146    int res = 0, x;
01147 #ifndef BUSYDETECT_TONEONLY
01148    int avgsilence = 0, hitsilence = 0;
01149 #endif
01150    int avgtone = 0, hittone = 0;
01151    if (!dsp->busymaybe)
01152       return res;
01153    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01154 #ifndef BUSYDETECT_TONEONLY
01155       avgsilence += dsp->historicsilence[x];
01156 #endif
01157       avgtone += dsp->historicnoise[x];
01158    }
01159 #ifndef BUSYDETECT_TONEONLY
01160    avgsilence /= dsp->busycount;
01161 #endif
01162    avgtone /= dsp->busycount;
01163    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01164 #ifndef BUSYDETECT_TONEONLY
01165       if (avgsilence > dsp->historicsilence[x]) {
01166          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01167             hitsilence++;
01168       } else {
01169          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01170             hitsilence++;
01171       }
01172 #endif
01173       if (avgtone > dsp->historicnoise[x]) {
01174          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01175             hittone++;
01176       } else {
01177          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01178             hittone++;
01179       }
01180    }
01181 #ifndef BUSYDETECT_TONEONLY
01182    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01183        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01184        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01185 #else
01186    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01187 #endif
01188 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01189       if (avgtone > avgsilence) {
01190          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01191             res = 1;
01192       } else {
01193          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01194             res = 1;
01195       }
01196 #else
01197       res = 1;
01198 #endif
01199    }
01200    /* If we know the expected busy tone length, check we are in the range */
01201    if (res && (dsp->busy_tonelength > 0)) {
01202       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01203 #ifdef BUSYDETECT_DEBUG
01204          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01205             avgtone, dsp->busy_tonelength);
01206 #endif
01207          res = 0;
01208       }
01209    }
01210 #ifndef BUSYDETECT_TONEONLY
01211    /* If we know the expected busy tone silent-period length, check we are in the range */
01212    if (res && (dsp->busy_quietlength > 0)) {
01213       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01214 #ifdef BUSYDETECT_DEBUG
01215       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01216          avgsilence, dsp->busy_quietlength);
01217 #endif
01218          res = 0;
01219       }
01220    }
01221 #endif
01222 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01223    if (res) {
01224       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01225    } else {
01226       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01227    }
01228 #endif
01229    return res;
01230 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1522 of file dsp.c.

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

Referenced by ss_thread().

01523 {
01524    int i;
01525    
01526    dsp->dtmf_began = 0;
01527    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01528       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01529       /* Reinitialise the detector for the next block */
01530       for (i = 0;  i < 6;  i++) {
01531          goertzel_reset(&s->tone_out[i]);
01532       }
01533       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01534       s->current_sample = 0;
01535    } else {
01536       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01537       /* Reinitialise the detector for the next block */
01538       for (i = 0;  i < 4;  i++) {
01539          goertzel_reset(&s->row_out[i]);
01540          goertzel_reset(&s->col_out[i]);
01541       }
01542       s->lasthit = s->current_hit = 0;
01543       s->energy = 0.0;
01544       s->current_sample = 0;
01545       s->hits = 0;
01546       s->misses = 0;
01547    }
01548 
01549    dsp->digit_state.digits[0] = '\0';
01550    dsp->digit_state.current_digits = 0;
01551 }

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

Get tcount (Threshold counter).

Definition at line 1614 of file dsp.c.

References ast_dsp::tcount.

01615 {
01616    return dsp->tcount;
01617 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1641 of file dsp.c.

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

01642 {
01643    return thresholds[which];
01644 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1609 of file dsp.c.

References ast_dsp::tstate.

01610 {
01611    return dsp->tstate;
01612 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1646 of file dsp.c.

References _dsp_init().

Referenced by main().

01647 {
01648    return _dsp_init(0);
01649 }

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

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

Since:
1.6.1

Definition at line 1250 of file dsp.c.

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

Referenced by do_waiting().

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

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

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

Definition at line 1269 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_frfree, ast_frisolate(), ast_getformatname(), AST_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame::frametype, ast_dsp::historicnoise, ast_dsp::historicsilence, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_frame::ptr, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1453 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01454 {
01455    int max = 0;
01456    int x;
01457    
01458    dsp->gsamp_size = modes[dsp->progmode].size;
01459    dsp->gsamps = 0;
01460    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01461       if (modes[dsp->progmode].freqs[x]) {
01462          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01463          max = x + 1;
01464       }
01465    }
01466    dsp->freqcount = max;
01467    dsp->ringtimeout= 0;
01468 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1651 of file dsp.c.

References _dsp_init().

01652 {
01653    return _dsp_init(1);
01654 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01554 {
01555    int x;
01556    
01557    dsp->totalsilence = 0;
01558    dsp->gsamps = 0;
01559    for (x=0;x<4;x++)
01560       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01561    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01562    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01563    dsp->ringtimeout= 0;
01564 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1506 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01507 {
01508    if (cadences < 4)
01509       cadences = 4;
01510    if (cadences > DSP_HISTORY)
01511       cadences = DSP_HISTORY;
01512    dsp->busycount = cadences;
01513 }

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

Set expected lengths of the busy tone.

Definition at line 1515 of file dsp.c.

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

Referenced by dahdi_new().

01516 {
01517    dsp->busy_tonelength = tonelength;
01518    dsp->busy_quietlength = quietlength;
01519    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01520 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1590 of file dsp.c.

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

Referenced by dahdi_new().

01591 {
01592    int x;
01593    
01594    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01595       if (!strcasecmp(aliases[x].name, zone)) {
01596          dsp->progmode = aliases[x].mode;
01597          ast_dsp_prog_reset(dsp);
01598          return 0;
01599       }
01600    }
01601    return -1;
01602 }

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

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

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

01567 {
01568    int new;
01569    int old;
01570    
01571    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01572    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01573    if (old != new) {
01574       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01575       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01576    }
01577    dsp->digitmode = digitmode;
01578    return 0;
01579 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1581 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01582 {
01583    if (dsp->faxmode != faxmode) {
01584       ast_fax_detect_init(dsp);
01585    }
01586    dsp->faxmode = faxmode;
01587    return 0;
01588 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1491 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(), pri_dchannel(), read_config(), sip_dtmfmode(), sip_new(), sip_rtp_read(), ss7_linkset(), and store_config().

01492 {
01493    dsp->features = features;
01494 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1501 of file dsp.c.

References ast_dsp::threshold.

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

01502 {
01503    dsp->threshold = threshold;
01504 }

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

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

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

01233 {
01234    short *s;
01235    int len;
01236    
01237    if (f->frametype != AST_FRAME_VOICE) {
01238       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01239       return 0;
01240    }
01241    if (f->subclass != AST_FORMAT_SLINEAR) {
01242       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01243       return 0;
01244    }
01245    s = f->data.ptr;
01246    len = f->datalen/2;
01247    return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL);
01248 }

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01605 {
01606    return (dsp->mute_fragments > 0);
01607 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s  )  [static]
static void ast_fax_detect_init ( struct ast_dsp s  )  [static]
static void ast_mf_detect_init ( mf_detect_state_t s  )  [static]

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

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

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

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

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

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

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

Referenced by ast_dsp_process().

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

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

Definition at line 339 of file dsp.c.

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

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

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

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

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

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

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

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

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

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, DTMF_GSIZE, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute_fragment(), mf_detect_state_t::mute_samples, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_process().

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

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

Definition at line 401 of file dsp.c.

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

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

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

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

Definition at line 929 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

Definition at line 622 of file dsp.c.

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

Referenced by dtmf_detect(), and mf_detect().

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

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

Definition at line 520 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, fragment_t::end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute_fragment(), tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_dsp_process().

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


Variable Documentation

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

Definition at line 300 of file dsp.c.

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.


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1