Wed Oct 28 11:52:19 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"

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

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

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

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

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

static int _dsp_init ( int  reload  )  [static]

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

01605 {
01606    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01607    struct ast_config *cfg;
01608 
01609    cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags);
01610 
01611    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
01612       const char *value;
01613 
01614       value = ast_variable_retrieve(cfg, "default", "silencethreshold");
01615       if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) {
01616          ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value);
01617          thresholds[THRESHOLD_SILENCE] = 256;
01618       } else if (!value)
01619          thresholds[THRESHOLD_SILENCE] = 256;
01620 
01621       ast_config_destroy(cfg);
01622    }
01623    return 0;
01624 }

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

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

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

01508 {
01509    int i;
01510    
01511    dsp->dtmf_began = 0;
01512    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01513       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01514       /* Reinitialise the detector for the next block */
01515       for (i = 0;  i < 6;  i++) {
01516          goertzel_reset(&s->tone_out[i]);
01517       }
01518       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01519       s->current_sample = 0;
01520    } else {
01521       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01522       /* Reinitialise the detector for the next block */
01523       for (i = 0;  i < 4;  i++) {
01524          goertzel_reset(&s->row_out[i]);
01525          goertzel_reset(&s->col_out[i]);
01526       }
01527       s->lasthit = s->current_hit = 0;
01528       s->energy = 0.0;
01529       s->current_sample = 0;
01530       s->hits = 0;
01531       s->misses = 0;
01532    }
01533 
01534    dsp->digit_state.digits[0] = '\0';
01535    dsp->digit_state.current_digits = 0;
01536 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1599 of file dsp.c.

References ast_dsp::tcount.

01600 {
01601    return dsp->tcount;
01602 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

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

01627 {
01628    return thresholds[which];
01629 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1594 of file dsp.c.

References ast_dsp::tstate.

01595 {
01596    return dsp->tstate;
01597 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1631 of file dsp.c.

References _dsp_init().

Referenced by main().

01632 {
01633    return _dsp_init(0);
01634 }

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

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

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

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

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

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

01440 {
01441    int max = 0;
01442    int x;
01443    
01444    dsp->gsamp_size = modes[dsp->progmode].size;
01445    dsp->gsamps = 0;
01446    for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) {
01447       if (modes[dsp->progmode].freqs[x]) {
01448          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
01449          max = x + 1;
01450       }
01451    }
01452    dsp->freqcount = max;
01453    dsp->ringtimeout= 0;
01454 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1636 of file dsp.c.

References _dsp_init().

01637 {
01638    return _dsp_init(1);
01639 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01539 {
01540    int x;
01541    
01542    dsp->totalsilence = 0;
01543    dsp->gsamps = 0;
01544    for (x=0;x<4;x++)
01545       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01546    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01547    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01548    dsp->ringtimeout= 0;
01549 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1491 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01492 {
01493    if (cadences < 4)
01494       cadences = 4;
01495    if (cadences > DSP_HISTORY)
01496       cadences = DSP_HISTORY;
01497    dsp->busycount = cadences;
01498 }

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

Set expected lengths of the busy tone.

Definition at line 1500 of file dsp.c.

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

Referenced by dahdi_new().

01501 {
01502    dsp->busy_tonelength = tonelength;
01503    dsp->busy_quietlength = quietlength;
01504    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01505 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1575 of file dsp.c.

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

Referenced by dahdi_new().

01576 {
01577    int x;
01578    
01579    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01580       if (!strcasecmp(aliases[x].name, zone)) {
01581          dsp->progmode = aliases[x].mode;
01582          ast_dsp_prog_reset(dsp);
01583          return 0;
01584       }
01585    }
01586    return -1;
01587 }

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

01552 {
01553    int new;
01554    int old;
01555    
01556    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01557    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01558    if (old != new) {
01559       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01560       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01561    }
01562    dsp->digitmode = digitmode;
01563    return 0;
01564 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1566 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

01567 {
01568    if (dsp->faxmode != faxmode) {
01569       ast_fax_detect_init(dsp);
01570    }
01571    dsp->faxmode = faxmode;
01572    return 0;
01573 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

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

01477 {
01478    dsp->features = features;
01479 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1486 of file dsp.c.

References ast_dsp::threshold.

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

01487 {
01488    dsp->threshold = threshold;
01489 }

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

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

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01590 {
01591    return (dsp->mute_fragments > 0);
01592 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 928 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

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

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

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

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

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


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 Wed Oct 28 11:52:19 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6