dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/format_cache.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 DEF_DTMF_HITS_TO_BEGIN   2
#define DEF_DTMF_MISSES_TO_END   3
#define DEF_DTMF_NORMAL_TWIST   6.31
#define DEF_DTMF_REVERSE_TWIST   2.51
#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31
#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98
#define DEFAULT_SAMPLE_RATE   8000
#define DEFAULT_THRESHOLD   512
 This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
#define DSP_HISTORY   15
#define DTMF_2ND_HARMONIC_COL   63.1
#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)
#define DTMF_GSIZE   102
#define DTMF_RELATIVE_PEAK_COL   6.3
#define DTMF_RELATIVE_PEAK_ROW   6.3
#define DTMF_THRESHOLD   8.0e7
#define DTMF_TO_TOTAL_ENERGY   42.0
#define FAX_2ND_HARMONIC   2.0
#define FAX_THRESHOLD   8.0e7
#define FAX_TONE_CED_DB   16
#define FAX_TONE_CED_DURATION   2600
#define FAX_TONE_CED_FREQ   2100
#define FAX_TONE_CNG_DB   16
#define FAX_TONE_CNG_DURATION   500
#define FAX_TONE_CNG_FREQ   1100
#define FREQ_ARRAY_SIZE   7
#define MAX_DTMF_DIGITS   128
#define MF_GSIZE   120
#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_350UK = 0, HZ_400UK, HZ_440UK
}
enum  gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 }
enum  gsamp_thresh {
  THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4,
  THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300
}
enum  prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK }

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static struct ast_dsp__ast_dsp_new (unsigned int sample_rate)
static int __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
static int _dsp_init (int reload)
static void ast_digit_detect_init (digit_detect_state_t *s, int mf, unsigned int sample_rate)
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_features (struct ast_dsp *dsp)
 Get features.
unsigned int ast_dsp_get_sample_rate (const struct ast_dsp *dsp)
 Retrieve the sample rate this DSP structure was created with.
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)
 Allocates a new dsp, assumes 8khz for internal sample rate.
struct ast_dspast_dsp_new_with_rate (unsigned int sample_rate)
 Allocates a new dsp with a specific internal sample rate used during processing.
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, const struct ast_dsp_busy_pattern *cadence)
 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.
static int ast_dsp_silence_noise_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
int ast_dsp_silence_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence, int *frames_energy)
 Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. Returns the average energy of the samples in the frame in frames_energy variable.
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, unsigned int sample_rate)
static void ast_fax_detect_init (struct ast_dsp *s)
static void ast_mf_detect_init (mf_detect_state_t *s, unsigned int sample_rate)
static void ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
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, unsigned int sample_rate)
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 int mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static void mute_fragment (struct ast_dsp *dsp, fragment_t *fragment)
static int pair_there (float p1, float p2, float i1, float i2, float e)
static void store_digit (digit_detect_state_t *s, char digit)
static int tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)

Variables

static struct progalias aliases []
static const char bell_mf_positions [] = "1247C-358A--69*---0B----#"
static const int DEFAULT_SILENCE_THRESHOLD = 256
 The default silence threshold we will use if an alternate configured value is not present or is invalid.
static const float dtmf_col []
static int dtmf_hits_to_begin
static int dtmf_misses_to_end
static float dtmf_normal_twist
static const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float dtmf_reverse_twist
static const float dtmf_row []
static const float mf_tones []
static struct progress modes []
static float relax_dtmf_normal_twist
static float relax_dtmf_reverse_twist
static int thresholds [THRESHOLD_MAX]


Detailed Description

Convenience Signal Processing routines.

Author:
Mark Spencer <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Definition in file dsp.c.


Define Documentation

#define BELL_MF_RELATIVE_PEAK   12.6

Definition at line 196 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 194 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST   4.0

Definition at line 195 of file dsp.c.

Referenced by mf_detect().

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 241 of file dsp.c.

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 228 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 233 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_NORMAL_TWIST   6.31

Definition at line 177 of file dsp.c.

Referenced by _dsp_init().

#define DEF_DTMF_REVERSE_TWIST   2.51

Definition at line 184 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31

Definition at line 178 of file dsp.c.

Referenced by _dsp_init().

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98

Definition at line 185 of file dsp.c.

Referenced by _dsp_init().

#define DEFAULT_SAMPLE_RATE   8000

Definition at line 217 of file dsp.c.

#define DEFAULT_THRESHOLD   512

This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.

Definition at line 133 of file dsp.c.

Referenced by __ast_dsp_new().

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 144 of file dsp.c.

Referenced by __ast_dsp_new(), __ast_dsp_silence_noise(), ast_dsp_busydetect(), and ast_dsp_set_busy_count().

#define DTMF_2ND_HARMONIC_COL   63.1

Definition at line 191 of file dsp.c.

#define DTMF_2ND_HARMONIC_ROW   (relax ? 1.7 : 2.5)

Definition at line 190 of file dsp.c.

#define DTMF_GSIZE   102

Definition at line 223 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL   6.3

Definition at line 189 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW   6.3

Definition at line 188 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD   8.0e7

Definition at line 173 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 192 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC   2.0

Definition at line 175 of file dsp.c.

#define FAX_THRESHOLD   8.0e7

Definition at line 174 of file dsp.c.

#define FAX_TONE_CED_DB   16

Definition at line 215 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_DURATION   2600

Definition at line 214 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CED_FREQ   2100

Definition at line 213 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DB   16

Definition at line 207 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_DURATION   500

Definition at line 206 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FAX_TONE_CNG_FREQ   1100

Definition at line 205 of file dsp.c.

Referenced by ast_fax_detect_init().

#define FREQ_ARRAY_SIZE   7

Definition at line 115 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and ast_dsp_prog_reset().

#define MAX_DTMF_DIGITS   128

Definition at line 159 of file dsp.c.

Referenced by store_digit().

#define MF_GSIZE   120

Definition at line 220 of file dsp.c.

Referenced by mf_detect().

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

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

00135                  {
00136    BUSY_PERCENT = 10,   /*!< The percentage difference between the two last silence periods */
00137    BUSY_PAT_PERCENT = 7,   /*!< The percentage difference between measured and actual pattern */
00138    BUSY_THRESHOLD = 100,   /*!< Max number of ms difference between max and min times in busy */
00139    BUSY_MIN = 75,    /*!< Busy must be at least 80 ms in half-cadence */
00140    BUSY_MAX = 3100      /*!< Busy can't be longer than 3100 ms in half-cadence */
00141 };

enum freq_index

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

Definition at line 85 of file dsp.c.

00085                 {
00086    /*! For US modes { */
00087    HZ_350 = 0,
00088    HZ_440,
00089    HZ_480,
00090    HZ_620,
00091    HZ_950,
00092    HZ_1400,
00093    HZ_1800, /*!< } */
00094 
00095    /*! For CR/BR modes */
00096    HZ_425 = 0,
00097 
00098    /*! For UK mode */
00099    HZ_350UK = 0,
00100    HZ_400UK,
00101    HZ_440UK
00102 };

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

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

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

00150                   {
00151    THRESH_RING = 8,     /*!< Need at least 150ms ring to accept */
00152    THRESH_TALK = 2,     /*!< Talk detection does not work continuously */
00153    THRESH_BUSY = 4,     /*!< Need at least 80ms to accept */
00154    THRESH_CONGESTION = 4,     /*!< Need at least 80ms to accept */
00155    THRESH_HANGUP = 60,     /*!< Need at least 1300ms to accept hangup */
00156    THRESH_RING2ANSWER = 300   /*!< Timeout from start of ring to answer (about 6600 ms) */
00157 };

enum prog_mode

Enumerator:
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 79 of file dsp.c.

00079                {
00080    PROG_MODE_NA = 0,
00081    PROG_MODE_CR,
00082    PROG_MODE_UK
00083 };


Function Documentation

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

Definition at line 1033 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, FREQ_ARRAY_SIZE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_350UK, HZ_400UK, HZ_425, HZ_440, HZ_440UK, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

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

static struct ast_dsp* __ast_dsp_new ( unsigned int  sample_rate  )  [static, read]

Definition at line 1664 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_new_with_rate().

01665 {
01666    struct ast_dsp *dsp;
01667 
01668    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
01669       dsp->threshold = DEFAULT_THRESHOLD;
01670       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01671       dsp->busycount = DSP_HISTORY;
01672       dsp->digitmode = DSP_DIGITMODE_DTMF;
01673       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01674       dsp->sample_rate = sample_rate;
01675       dsp->freqcount = 0;
01676       /* Initialize digit detector */
01677       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF, dsp->sample_rate);
01678       dsp->display_inband_dtmf_warning = 1;
01679       /* Initialize initial DSP progress detect parameters */
01680       ast_dsp_prog_reset(dsp);
01681       /* Initialize fax detector */
01682       ast_fax_detect_init(dsp);
01683    }
01684    return dsp;
01685 }

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

Definition at line 1188 of file dsp.c.

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

Referenced by ast_dsp_process(), and ast_dsp_silence_noise_with_energy().

01189 {
01190    int accum;
01191    int x;
01192    int res = 0;
01193 
01194    if (!len) {
01195       return 0;
01196    }
01197    accum = 0;
01198    for (x = 0; x < len; x++) {
01199       accum += abs(s[x]);
01200    }
01201    accum /= len;
01202    if (accum < dsp->threshold) {
01203       /* Silent */
01204       dsp->totalsilence += len / (dsp->sample_rate / 1000);
01205       if (dsp->totalnoise) {
01206          /* Move and save history */
01207          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
01208          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
01209 /* we don't want to check for busydetect that frequently */
01210 #if 0
01211          dsp->busymaybe = 1;
01212 #endif
01213       }
01214       dsp->totalnoise = 0;
01215       res = 1;
01216    } else {
01217       /* Not silent */
01218       dsp->totalnoise += len / (dsp->sample_rate / 1000);
01219       if (dsp->totalsilence) {
01220          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
01221          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
01222          /* Move and save history */
01223          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
01224          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
01225          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
01226          if (silence1 < silence2) {
01227             if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
01228                dsp->busymaybe = 1;
01229             } else {
01230                dsp->busymaybe = 0;
01231             }
01232          } else {
01233             if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
01234                dsp->busymaybe = 1;
01235             } else {
01236                dsp->busymaybe = 0;
01237             }
01238          }
01239       }
01240       dsp->totalsilence = 0;
01241    }
01242    if (totalsilence) {
01243       *totalsilence = dsp->totalsilence;
01244    }
01245    if (totalnoise) {
01246       *totalnoise = dsp->totalnoise;
01247    }
01248    if (frames_energy) {
01249       *frames_energy = accum;
01250    }
01251    return res;
01252 }

static int _dsp_init ( int  reload  )  [static]

Definition at line 1839 of file dsp.c.

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

Referenced by ast_dsp_init(), and ast_dsp_reload().

01840 {
01841    struct ast_config *cfg;
01842    struct ast_variable *v;
01843    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01844    int cfg_threshold;
01845    float cfg_twist;
01846 
01847    if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
01848       return 0;
01849    }
01850 
01851    thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD;
01852    dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
01853    dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
01854    relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST;
01855    relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST;
01856         dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN;
01857         dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END;
01858 
01859    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01860       return 0;
01861    }
01862 
01863    for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
01864       if (!strcasecmp(v->name, "silencethreshold")) {
01865          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01866             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01867          } else if (cfg_threshold < 0) {
01868             ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
01869          } else {
01870             thresholds[THRESHOLD_SILENCE] = cfg_threshold;
01871          }
01872       } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
01873          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01874             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01875          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01876             ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
01877          } else {
01878             dtmf_normal_twist = cfg_twist;
01879          }
01880       } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
01881          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01882             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01883          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01884             ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
01885          } else {
01886             dtmf_reverse_twist = cfg_twist;
01887          }
01888       } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
01889          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01890             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01891          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01892             ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
01893          } else {
01894             relax_dtmf_normal_twist = cfg_twist;
01895          }
01896       } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
01897          if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
01898             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01899          } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {      /* < 3.0dB or > 20dB */
01900             ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
01901          } else {
01902             relax_dtmf_reverse_twist = cfg_twist;
01903          }
01904       } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
01905          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01906             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01907          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01908             ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
01909          } else {
01910             dtmf_hits_to_begin = cfg_threshold;
01911          }
01912       } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
01913          if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
01914             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
01915          } else if (cfg_threshold < 1) {     /* must be 1 or greater */
01916             ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
01917          } else {
01918             dtmf_misses_to_end = cfg_threshold;
01919          }
01920       }
01921    }
01922    ast_config_destroy(cfg);
01923 
01924    return 0;
01925 }

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

Definition at line 524 of file dsp.c.

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

Referenced by __ast_dsp_new(), and ast_dsp_set_digitmode().

00525 {
00526    s->current_digits = 0;
00527    s->detected_digits = 0;
00528    s->lost_digits = 0;
00529    s->digits[0] = '\0';
00530 
00531    if (mf) {
00532       ast_mf_detect_init(&s->td.mf, sample_rate);
00533    } else {
00534       ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
00535    }
00536 }

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

References abs, ast_debug, ast_dsp::busy_cadence, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp_busy_pattern::length, MAX, and ast_dsp_busy_pattern::pattern.

Referenced by ast_dsp_process().

01255 {
01256    int res = 0, x;
01257 #ifndef BUSYDETECT_TONEONLY
01258    int avgsilence = 0, hitsilence = 0;
01259 #endif
01260    int avgtone = 0, hittone = 0;
01261 
01262    /* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */
01263    if (dsp->busy_cadence.length != 4) {
01264       if (!dsp->busymaybe) {
01265          return res;
01266       }
01267    }
01268 
01269    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01270 #ifndef BUSYDETECT_TONEONLY
01271       avgsilence += dsp->historicsilence[x];
01272 #endif
01273       avgtone += dsp->historicnoise[x];
01274    }
01275 #ifndef BUSYDETECT_TONEONLY
01276    avgsilence /= dsp->busycount;
01277 #endif
01278    avgtone /= dsp->busycount;
01279    for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
01280 #ifndef BUSYDETECT_TONEONLY
01281       if (avgsilence > dsp->historicsilence[x]) {
01282          if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
01283             hitsilence++;
01284          }
01285       } else {
01286          if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
01287             hitsilence++;
01288          }
01289       }
01290 #endif
01291       if (avgtone > dsp->historicnoise[x]) {
01292          if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
01293             hittone++;
01294          }
01295       } else {
01296          if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
01297             hittone++;
01298          }
01299       }
01300    }
01301 #ifndef BUSYDETECT_TONEONLY
01302    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
01303        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
01304        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01305 #else
01306    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01307 #endif
01308 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01309       if (avgtone > avgsilence) {
01310          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
01311             res = 1;
01312          }
01313       } else {
01314          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
01315             res = 1;
01316          }
01317       }
01318 #else
01319       res = 1;
01320 #endif
01321    }
01322 
01323    /* If we have a 4-length pattern, we can go ahead and just check it in a different way. */
01324    if (dsp->busy_cadence.length == 4) {
01325       int x;
01326       int errors = 0;
01327       int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT;
01328 
01329       for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) {
01330          int temp_error;
01331          temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]);
01332          if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) {
01333             errors++;
01334          }
01335 
01336          temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]);
01337          if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) {
01338             errors++;
01339          }
01340 
01341          temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]);
01342          if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) {
01343             errors++;
01344          }
01345 
01346          temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]);
01347          if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) {
01348             errors++;
01349          }
01350       }
01351 
01352       ast_debug(5, "errors = %d  max = %d\n", errors, errors_max);
01353 
01354       if (errors <= errors_max) {
01355          return 1;
01356       }
01357    }
01358 
01359    /* If we know the expected busy tone length, check we are in the range */
01360    if (res && (dsp->busy_cadence.pattern[0] > 0)) {
01361       if (abs(avgtone - dsp->busy_cadence.pattern[0]) > MAX(dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100, 20)) {
01362 #ifdef BUSYDETECT_DEBUG
01363          ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
01364             avgtone, dsp->busy_cadence.pattern[0]);
01365 #endif
01366          res = 0;
01367       }
01368    }
01369 #ifndef BUSYDETECT_TONEONLY
01370    /* If we know the expected busy tone silent-period length, check we are in the range */
01371    if (res && (dsp->busy_cadence.pattern[1] > 0)) {
01372       if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > MAX(dsp->busy_cadence.pattern[1]*BUSY_PAT_PERCENT/100, 20)) {
01373 #ifdef BUSYDETECT_DEBUG
01374       ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
01375          avgsilence, dsp->busy_cadence.pattern[1]);
01376 #endif
01377          res = 0;
01378       }
01379    }
01380 #endif
01381 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
01382    if (res) {
01383       ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01384    } else {
01385       ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01386    }
01387 #endif
01388    return res;
01389 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1175 of file dsp.c.

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

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

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1739 of file dsp.c.

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

Referenced by analog_ss_thread(), mbl_new(), and my_dsp_reset_and_flush_digits().

01740 {
01741    int i;
01742 
01743    dsp->dtmf_began = 0;
01744    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01745       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01746       /* Reinitialise the detector for the next block */
01747       for (i = 0; i < 6; i++) {
01748          goertzel_reset(&s->tone_out[i]);
01749       }
01750       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
01751       s->current_hit = 0;
01752       s->current_sample = 0;
01753    } else {
01754       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01755       /* Reinitialise the detector for the next block */
01756       for (i = 0; i < 4; i++) {
01757          goertzel_reset(&s->row_out[i]);
01758          goertzel_reset(&s->col_out[i]);
01759       }
01760       s->lasthit = 0;
01761       s->current_hit = 0;
01762       s->energy = 0.0;
01763       s->current_sample = 0;
01764       s->hits = 0;
01765       s->misses = 0;
01766    }
01767 
01768    dsp->digit_state.digits[0] = '\0';
01769    dsp->digit_state.current_digits = 0;
01770 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

int ast_dsp_get_features ( struct ast_dsp dsp  ) 

Get features.

Definition at line 1706 of file dsp.c.

References ast_dsp::features.

Referenced by set_caps().

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

unsigned int ast_dsp_get_sample_rate ( const struct ast_dsp dsp  ) 

Retrieve the sample rate this DSP structure was created with.

Definition at line 1659 of file dsp.c.

References ast_dsp::sample_rate.

01660 {
01661    return dsp->sample_rate;
01662 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1834 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

01835 {
01836    return dsp->tcount;
01837 }

int ast_dsp_get_threshold_from_settings ( enum threshold  which  ) 

Get silence threshold from dsp.conf.

Since:
1.6.1

Definition at line 1927 of file dsp.c.

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

01928 {
01929    return thresholds[which];
01930 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1829 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

01830 {
01831    return dsp->tstate;
01832 }

int ast_dsp_init ( void   ) 

Load dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1932 of file dsp.c.

References _dsp_init().

Referenced by main().

01933 {
01934    return _dsp_init(0);
01935 }

struct ast_dsp* ast_dsp_new ( void   )  [read]

struct ast_dsp* ast_dsp_new_with_rate ( unsigned int  sample_rate  )  [read]

Allocates a new dsp with a specific internal sample rate used during processing.

Definition at line 1692 of file dsp.c.

References __ast_dsp_new().

Referenced by set_softmix_bridge_data(), and set_talk_detect().

01693 {
01694    return __ast_dsp_new(sample_rate);
01695 }

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

References ast_dsp_silence_noise_with_energy(), and NULL.

Referenced by do_waiting().

01447 {
01448    return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
01449 }

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

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), AST_ALAW, ast_alloca, ast_channel_name(), ast_channel_softhangup_internal_flag_add(), 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_cache_is_slinear(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), 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_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, digit, ast_dsp::digit_state, digit_detect_state_t::digitlen, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame_subclass::format, ast_frame::frametype, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_frame_subclass::integer, ast_frame::len, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, NULL, ast_frame::ptr, ast_dsp::sample_rate, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

Referenced by chan_pjsip_read(), dahdi_read(), fax_detect_framehook(), mbl_read(), mgcp_rtp_read(), ooh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().

01453 {
01454    int silence;
01455    int res;
01456    int digit = 0, fax_digit = 0;
01457    int x;
01458    short *shortdata;
01459    unsigned char *odata;
01460    int len;
01461    struct ast_frame *outf = NULL;
01462 
01463    if (!af) {
01464       return NULL;
01465    }
01466    if (af->frametype != AST_FRAME_VOICE) {
01467       return af;
01468    }
01469 
01470    odata = af->data.ptr;
01471    len = af->datalen;
01472    /* Make sure we have short data */
01473    if (ast_format_cache_is_slinear(af->subclass.format)) {
01474       shortdata = af->data.ptr;
01475       len = af->datalen / 2;
01476    } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
01477       shortdata = ast_alloca(af->datalen * 2);
01478       for (x = 0; x < len; x++) {
01479          shortdata[x] = AST_MULAW(odata[x]);
01480       }
01481    } else if (ast_format_cmp(af->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
01482       shortdata = ast_alloca(af->datalen * 2);
01483       for (x = 0; x < len; x++) {
01484          shortdata[x] = AST_ALAW(odata[x]);
01485       }
01486    } else {
01487       /*Display warning only once. Otherwise you would get hundreds of warnings every second */
01488       if (dsp->display_inband_dtmf_warning) {
01489          ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_format_get_name(af->subclass.format));
01490       }
01491       dsp->display_inband_dtmf_warning = 0;
01492       return af;
01493    }
01494 
01495    /* Initially we do not want to mute anything */
01496    dsp->mute_fragments = 0;
01497 
01498    /* Need to run the silence detection stuff for silence suppression and busy detection */
01499    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
01500       res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
01501    }
01502 
01503    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01504       memset(&dsp->f, 0, sizeof(dsp->f));
01505       dsp->f.frametype = AST_FRAME_NULL;
01506       ast_frfree(af);
01507       return ast_frisolate(&dsp->f);
01508    }
01509    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01510       ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
01511       memset(&dsp->f, 0, sizeof(dsp->f));
01512       dsp->f.frametype = AST_FRAME_CONTROL;
01513       dsp->f.subclass.integer = AST_CONTROL_BUSY;
01514       ast_frfree(af);
01515       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
01516       return ast_frisolate(&dsp->f);
01517    }
01518 
01519    if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
01520       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
01521          fax_digit = 'f';
01522       }
01523 
01524       if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
01525          fax_digit = 'e';
01526       }
01527    }
01528 
01529    if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
01530       if (dsp->digitmode & DSP_DIGITMODE_MF) {
01531          digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01532       } else {
01533          digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
01534       }
01535 
01536       if (dsp->digit_state.current_digits) {
01537          int event = 0, event_len = 0;
01538          char event_digit = 0;
01539 
01540          if (!dsp->dtmf_began) {
01541             /* We have not reported DTMF_BEGIN for anything yet */
01542 
01543             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01544                event = AST_FRAME_DTMF_BEGIN;
01545                event_digit = dsp->digit_state.digits[0];
01546             }
01547             dsp->dtmf_began = 1;
01548 
01549          } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
01550             /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
01551             if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
01552                event = AST_FRAME_DTMF_END;
01553                event_digit = dsp->digit_state.digits[0];
01554                event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
01555             }
01556             memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
01557             memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
01558             dsp->digit_state.current_digits--;
01559             dsp->dtmf_began = 0;
01560 
01561             if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
01562                /* Reset Busy Detector as we have some confirmed activity */
01563                memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01564                memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01565                ast_debug(1, "DTMF Detected - Reset busydetector\n");
01566             }
01567          }
01568 
01569          if (event) {
01570             memset(&dsp->f, 0, sizeof(dsp->f));
01571             dsp->f.frametype = event;
01572             dsp->f.subclass.integer = event_digit;
01573             dsp->f.len = event_len;
01574             outf = &dsp->f;
01575             goto done;
01576          }
01577       }
01578    }
01579 
01580    if (fax_digit) {
01581       /* Fax was detected - digit is either 'f' or 'e' */
01582 
01583       memset(&dsp->f, 0, sizeof(dsp->f));
01584       dsp->f.frametype = AST_FRAME_DTMF;
01585       dsp->f.subclass.integer = fax_digit;
01586       outf = &dsp->f;
01587       goto done;
01588    }
01589 
01590    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01591       res = __ast_dsp_call_progress(dsp, shortdata, len);
01592       if (res) {
01593          switch (res) {
01594          case AST_CONTROL_ANSWER:
01595          case AST_CONTROL_BUSY:
01596          case AST_CONTROL_RINGING:
01597          case AST_CONTROL_CONGESTION:
01598          case AST_CONTROL_HANGUP:
01599             memset(&dsp->f, 0, sizeof(dsp->f));
01600             dsp->f.frametype = AST_FRAME_CONTROL;
01601             dsp->f.subclass.integer = res;
01602             dsp->f.src = "dsp_progress";
01603             if (chan) {
01604                ast_queue_frame(chan, &dsp->f);
01605             }
01606             break;
01607          default:
01608             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01609          }
01610       }
01611    } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
01612       res = __ast_dsp_call_progress(dsp, shortdata, len);
01613    }
01614 
01615 done:
01616    /* Mute fragment of the frame */
01617    for (x = 0; x < dsp->mute_fragments; x++) {
01618       memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
01619    }
01620 
01621    if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
01622       for (x = 0; x < len; x++) {
01623          odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
01624       }
01625    } else if (ast_format_cmp(af->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
01626       for (x = 0; x < len; x++) {
01627          odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
01628       }
01629    }
01630 
01631    if (outf) {
01632       if (chan) {
01633          ast_queue_frame(chan, af);
01634       }
01635       ast_frfree(af);
01636       return ast_frisolate(outf);
01637    } else {
01638       return af;
01639    }
01640 }

static void ast_dsp_prog_reset ( struct ast_dsp dsp  )  [static]

Definition at line 1642 of file dsp.c.

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

Referenced by __ast_dsp_new(), and ast_dsp_set_call_progress_zone().

01643 {
01644    int max = 0;
01645    int x;
01646 
01647    dsp->gsamp_size = modes[dsp->progmode].size;
01648    dsp->gsamps = 0;
01649    for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
01650       if (modes[dsp->progmode].freqs[x]) {
01651          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
01652          max = x + 1;
01653       }
01654    }
01655    dsp->freqcount = max;
01656    dsp->ringtimeout = 0;
01657 }

int ast_dsp_reload ( void   ) 

Reloads dsp settings from dsp.conf.

Since:
1.6.1

Definition at line 1937 of file dsp.c.

References _dsp_init().

01938 {
01939    return _dsp_init(1);
01940 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

Definition at line 1772 of file dsp.c.

References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::ringtimeout, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by debug_check_frame_for_silence().

01773 {
01774    int x;
01775 
01776    dsp->totalsilence = 0;
01777    dsp->gsamps = 0;
01778    for (x = 0; x < 4; x++) {
01779       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01780    }
01781    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01782    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01783    dsp->ringtimeout = 0;
01784 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1722 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01723 {
01724    if (cadences < 4) {
01725       cadences = 4;
01726    }
01727    if (cadences > DSP_HISTORY) {
01728       cadences = DSP_HISTORY;
01729    }
01730    dsp->busycount = cadences;
01731 }

void ast_dsp_set_busy_pattern ( struct ast_dsp dsp,
const struct ast_dsp_busy_pattern cadence 
)

Set expected lengths of the busy tone.

Definition at line 1733 of file dsp.c.

References ast_debug, ast_dsp::busy_cadence, ast_dsp_busy_pattern::length, and ast_dsp_busy_pattern::pattern.

Referenced by dahdi_new().

01734 {
01735    dsp->busy_cadence = *cadence;
01736    ast_debug(1, "dsp busy pattern set to %d,%d,%d,%d\n", cadence->pattern[0], cadence->pattern[1], (cadence->length == 4) ? cadence->pattern[2] : 0, (cadence->length == 4) ? cadence->pattern[3] : 0);
01737 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1810 of file dsp.c.

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

Referenced by dahdi_new().

01811 {
01812    int x;
01813 
01814    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01815       if (!strcasecmp(aliases[x].name, zone)) {
01816          dsp->progmode = aliases[x].mode;
01817          ast_dsp_prog_reset(dsp);
01818          return 0;
01819       }
01820    }
01821    return -1;
01822 }

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 1786 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, DSP_DIGITMODE_MUTEMAX, and ast_dsp::sample_rate.

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mbl_load_device(), mgcp_new(), mkintf(), my_dsp_set_digitmode(), and ooh323_new().

01787 {
01788    int new;
01789    int old;
01790 
01791    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01792    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01793    if (old != new) {
01794       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01795       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF, dsp->sample_rate);
01796    }
01797    dsp->digitmode = digitmode;
01798    return 0;
01799 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1801 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by fax_detect_new(), and ooh323_new().

01802 {
01803    if (dsp->faxmode != faxmode) {
01804       dsp->faxmode = faxmode;
01805       ast_fax_detect_init(dsp);
01806    }
01807    return 0;
01808 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1717 of file dsp.c.

References ast_dsp::threshold.

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

01718 {
01719    dsp->threshold = threshold;
01720 }

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

References ast_dsp_silence_noise_with_energy(), and NULL.

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

01442 {
01443    return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
01444 }

static int ast_dsp_silence_noise_with_energy ( struct ast_dsp dsp,
struct ast_frame f,
int *  total,
int *  frames_energy,
int  noise 
) [static]

Definition at line 1391 of file dsp.c.

References __ast_dsp_silence_noise(), AST_ALAW, ast_alloca, ast_format_alaw, ast_format_cache_is_slinear(), ast_format_cmp(), ast_format_ulaw, AST_FRAME_VOICE, ast_log, AST_MULAW, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, len(), LOG_WARNING, NULL, ast_frame::ptr, and ast_frame::subclass.

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

01392 {
01393    short *s;
01394    int len;
01395    int x;
01396    unsigned char *odata;
01397 
01398    if (!f) {
01399       return 0;
01400    }
01401 
01402    if (f->frametype != AST_FRAME_VOICE) {
01403       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01404       return 0;
01405    }
01406 
01407    if (ast_format_cache_is_slinear(f->subclass.format)) {
01408       s = f->data.ptr;
01409       len = f->datalen/2;
01410    } else {
01411       odata = f->data.ptr;
01412       len = f->datalen;
01413       if (ast_format_cmp(f->subclass.format, ast_format_ulaw)) {
01414          s = ast_alloca(len * 2);
01415          for (x = 0; x < len; x++) {
01416             s[x] = AST_MULAW(odata[x]);
01417          }
01418       } else if (ast_format_cmp(f->subclass.format, ast_format_alaw)) {
01419          s = ast_alloca(len * 2);
01420          for (x = 0; x < len; x++) {
01421             s[x] = AST_ALAW(odata[x]);
01422          }
01423       } else {
01424          ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
01425          return 0;
01426       }
01427    }
01428 
01429    if (noise) {
01430       return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
01431    } else {
01432       return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
01433    }
01434 }

int ast_dsp_silence_with_energy ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalsilence,
int *  frames_energy 
)

Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. Returns the average energy of the samples in the frame in frames_energy variable.

Definition at line 1436 of file dsp.c.

References ast_dsp_silence_noise_with_energy().

Referenced by softmix_bridge_write_voice().

01437 {
01438    return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
01439 }

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

01825 {
01826    return (dsp->mute_fragments > 0);
01827 }

static void ast_dtmf_detect_init ( dtmf_detect_state_t s,
unsigned int  sample_rate 
) [static]

Definition at line 496 of file dsp.c.

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

Referenced by ast_digit_detect_init().

00497 {
00498    int i;
00499 
00500    for (i = 0; i < 4; i++) {
00501       goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
00502       goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
00503    }
00504    s->lasthit = 0;
00505    s->current_hit = 0;
00506    s->energy = 0.0;
00507    s->current_sample = 0;
00508    s->hits = 0;
00509    s->misses = 0;
00510 }

static void ast_fax_detect_init ( struct ast_dsp s  )  [static]

static void ast_mf_detect_init ( mf_detect_state_t s,
unsigned int  sample_rate 
) [static]

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

00513 {
00514    int i;
00515 
00516    for (i = 0; i < 6; i++) {
00517       goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
00518    }
00519    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
00520    s->current_sample = 0;
00521    s->current_hit = 0;
00522 }

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

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

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

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

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

Referenced by ast_dsp_process().

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

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

Definition at line 353 of file dsp.c.

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

00354 {
00355    s->v2 = s->v3 = s->chunky = 0.0;
00356    s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
00357 }

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

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

00360 {
00361    s->v2 = s->v3 = s->chunky = 0.0;
00362 }

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

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

00345 {
00346    goertzel_result_t r;
00347    r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
00348    r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
00349    r.power = s->chunky * 2;
00350    return (float)r.value * (float)(1 << r.power);
00351 }

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

Definition at line 328 of file dsp.c.

References abs, 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(), mf_detect(), and tone_detect().

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

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

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

Referenced by ast_dsp_process().

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

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

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

00415 {
00416    if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
00417       ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
00418       return;
00419    }
00420 
00421    dsp->mute_data[dsp->mute_fragments++] = *fragment;
00422 }

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

Definition at line 1010 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

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

Definition at line 644 of file dsp.c.

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

Referenced by dtmf_detect(), and mf_detect().

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

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

Definition at line 538 of file dsp.c.

References ast_debug, tone_detect_state_t::block_size, fragment_t::end, end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute, mute_fragment(), tone_detect_state_t::mute_samples, 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().

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


Variable Documentation

struct progalias aliases[] [static]

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

Definition at line 319 of file dsp.c.

const int DEFAULT_SILENCE_THRESHOLD = 256 [static]

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

Definition at line 239 of file dsp.c.

const float dtmf_col[] [static]

Initial value:

 {
   1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 312 of file dsp.c.

int dtmf_hits_to_begin [static]

Definition at line 325 of file dsp.c.

int dtmf_misses_to_end [static]

Definition at line 326 of file dsp.c.

float dtmf_normal_twist [static]

Definition at line 321 of file dsp.c.

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

Definition at line 318 of file dsp.c.

float dtmf_reverse_twist [static]

Definition at line 322 of file dsp.c.

const float dtmf_row[] [static]

Initial value:

 {
   697.0,  770.0,  852.0,  941.0
}

Definition at line 309 of file dsp.c.

const float mf_tones[] [static]

Initial value:

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

Definition at line 315 of file dsp.c.

struct progress modes[] [static]

Referenced by ast_dsp_prog_reset().

float relax_dtmf_normal_twist [static]

Definition at line 323 of file dsp.c.

float relax_dtmf_reverse_twist [static]

Definition at line 324 of file dsp.c.

int thresholds[THRESHOLD_MAX] [static]

Definition at line 320 of file dsp.c.


Generated on Thu Apr 16 06:30:46 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6