Convenience Signal Processing routines. More...
#include "asterisk.h"
#include <math.h>
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
Go to the source code of this file.
Data Structures | |
struct | ast_dsp |
struct | digit_detect_state_t |
struct | dtmf_detect_state_t |
struct | fragment_t |
struct | goertzel_result_t |
struct | goertzel_state_t |
struct | mf_detect_state_t |
struct | progalias |
struct | progress |
struct | tone_detect_state_t |
Defines | |
#define | BELL_MF_RELATIVE_PEAK 12.6 |
#define | BELL_MF_THRESHOLD 1.6e9 |
#define | BELL_MF_TWIST 4.0 |
#define | CONFIG_FILE_NAME "dsp.conf" |
#define | 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_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 | MAX_DTMF_DIGITS 128 |
#define | MF_GSIZE 120 |
#define | SAMPLE_RATE 8000 |
#define | SAMPLES_IN_FRAME 160 |
#define | TONE_MIN_THRESH 1e8 |
#define | TONE_THRESH 10.0 |
Enumerations | |
enum | busy_detect { BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150, BUSY_MAX = 600 } |
enum | freq_index { HZ_350 = 0, HZ_440, HZ_480, HZ_620, HZ_950, HZ_1400, HZ_1800, HZ_425 = 0, HZ_350UK = 0, HZ_400UK, HZ_440UK } |
enum | gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 } |
enum | gsamp_thresh { THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4, THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300 } |
enum | prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK } |
Functions | |
static int | __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len) |
static int | __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise) |
static int | _dsp_init (int reload) |
static void | ast_digit_detect_init (digit_detect_state_t *s, int mf) |
int | ast_dsp_busydetect (struct ast_dsp *dsp) |
Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called. | |
int | ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf) |
Scans for progress indication in audio. | |
void | ast_dsp_digitreset (struct ast_dsp *dsp) |
Reset DTMF detector. | |
void | ast_dsp_free (struct ast_dsp *dsp) |
int | ast_dsp_get_tcount (struct ast_dsp *dsp) |
Get tcount (Threshold counter). | |
int | ast_dsp_get_threshold_from_settings (enum threshold which) |
Get silence threshold from dsp.conf. | |
int | ast_dsp_get_tstate (struct ast_dsp *dsp) |
Get tstate (Tone State). | |
int | ast_dsp_init (void) |
Load dsp settings from dsp.conf. | |
struct ast_dsp * | ast_dsp_new (void) |
int | ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise) |
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise. | |
struct ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af) |
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled. | |
static void | ast_dsp_prog_reset (struct ast_dsp *dsp) |
int | ast_dsp_reload (void) |
Reloads dsp settings from dsp.conf. | |
void | ast_dsp_reset (struct ast_dsp *dsp) |
Reset total silence count. | |
void | ast_dsp_set_busy_compare (struct ast_dsp *dsp, int compare) |
Set if silence and noice lengths must be compared for busy. | |
void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences) |
Set number of required cadences for busy. | |
void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy) |
Set expected lengths of the busy tones. | |
int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
Set zone for doing progress detection. | |
int | ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode) |
Set digit mode. | |
int | ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode) |
Set fax mode. | |
void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
Select feature set. | |
void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold) |
Set threshold value for silence. | |
int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. | |
int | ast_dsp_was_muted (struct ast_dsp *dsp) |
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio. | |
static void | ast_dtmf_detect_init (dtmf_detect_state_t *s) |
static void | ast_fax_detect_init (struct ast_dsp *s) |
static void | ast_mf_detect_init (mf_detect_state_t *s) |
static void | ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp) |
static int | dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
static void | goertzel_init (goertzel_state_t *s, float freq, int samples) |
static void | goertzel_reset (goertzel_state_t *s) |
static float | goertzel_result (goertzel_state_t *s) |
static void | goertzel_sample (goertzel_state_t *s, short sample) |
static void | goertzel_update (goertzel_state_t *s, short *samps, int count) |
static int | mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
static void | mute_fragment (struct ast_dsp *dsp, fragment_t *fragment) |
static int | pair_there (float p1, float p2, float i1, float i2, float e) |
static void | store_digit (digit_detect_state_t *s, char digit) |
static int | tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples) |
Variables | |
static struct progalias | aliases [] |
static const char | bell_mf_positions [] = "1247C-358A--69*---0B----#" |
static const int | DEFAULT_SILENCE_THRESHOLD = 256 |
The default silence threshold we will use if an alternate configured value is not present or is invalid. | |
static const float | dtmf_col [] |
static 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] |
Convenience Signal Processing routines.
Definition in file dsp.c.
#define BELL_MF_RELATIVE_PEAK 12.6 |
Definition at line 184 of file dsp.c.
Referenced by mf_detect().
#define BELL_MF_THRESHOLD 1.6e9 |
Definition at line 182 of file dsp.c.
Referenced by mf_detect().
#define BELL_MF_TWIST 4.0 |
Definition at line 183 of file dsp.c.
Referenced by mf_detect().
#define DEF_DTMF_HITS_TO_BEGIN 2 |
Definition at line 224 of file dsp.c.
Referenced by _dsp_init().
#define DEF_DTMF_MISSES_TO_END 3 |
Definition at line 229 of file dsp.c.
Referenced by _dsp_init().
#define DEF_DTMF_NORMAL_TWIST 6.31 |
Definition at line 165 of file dsp.c.
Referenced by _dsp_init().
#define DEF_DTMF_REVERSE_TWIST 2.51 |
Definition at line 172 of file dsp.c.
Referenced by _dsp_init().
#define DEF_RELAX_DTMF_NORMAL_TWIST 6.31 |
Definition at line 166 of file dsp.c.
Referenced by _dsp_init().
#define DEF_RELAX_DTMF_REVERSE_TWIST 3.98 |
Definition at line 173 of file dsp.c.
Referenced by _dsp_init().
#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 121 of file dsp.c.
Referenced by ast_dsp_new().
#define DSP_HISTORY 15 |
Remember last 15 units
Definition at line 132 of file dsp.c.
Referenced by __ast_dsp_silence_noise(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().
#define DTMF_GSIZE 102 |
Definition at line 219 of file dsp.c.
Referenced by ast_dtmf_detect_init(), and dtmf_detect().
#define DTMF_RELATIVE_PEAK_COL 6.3 |
Definition at line 177 of file dsp.c.
Referenced by dtmf_detect().
#define DTMF_RELATIVE_PEAK_ROW 6.3 |
Definition at line 176 of file dsp.c.
Referenced by dtmf_detect().
#define DTMF_THRESHOLD 8.0e7 |
Definition at line 161 of file dsp.c.
Referenced by dtmf_detect().
#define DTMF_TO_TOTAL_ENERGY 42.0 |
Definition at line 180 of file dsp.c.
Referenced by dtmf_detect().
#define FAX_TONE_CED_DB 16 |
Definition at line 203 of file dsp.c.
Referenced by ast_fax_detect_init().
#define FAX_TONE_CED_DURATION 2600 |
Definition at line 202 of file dsp.c.
Referenced by ast_fax_detect_init().
#define FAX_TONE_CED_FREQ 2100 |
Definition at line 201 of file dsp.c.
Referenced by ast_fax_detect_init().
#define FAX_TONE_CNG_DB 16 |
Definition at line 195 of file dsp.c.
Referenced by ast_fax_detect_init().
#define FAX_TONE_CNG_DURATION 500 |
Definition at line 194 of file dsp.c.
Referenced by ast_fax_detect_init().
#define FAX_TONE_CNG_FREQ 1100 |
Definition at line 193 of file dsp.c.
Referenced by ast_fax_detect_init().
#define MAX_DTMF_DIGITS 128 |
Definition at line 147 of file dsp.c.
Referenced by store_digit().
#define MF_GSIZE 120 |
Definition at line 216 of file dsp.c.
Referenced by ast_mf_detect_init(), and mf_detect().
#define SAMPLES_IN_FRAME 160 |
Definition at line 213 of file dsp.c.
Referenced by ast_tone_detect_init().
#define TONE_MIN_THRESH 1e8 |
How much tone there should be at least to attempt
Definition at line 135 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 134 of file dsp.c.
Referenced by __ast_dsp_call_progress(), and pair_there().
enum busy_detect |
BUSY_PERCENT |
The percentage difference between the two last tone periods |
BUSY_PAT_PERCENT |
The percentage difference between measured and actual pattern |
BUSY_THRESHOLD |
Max number of ms difference between max and min times in busy |
BUSY_MIN |
Busy must be at least 150 ms in half-cadence |
BUSY_MAX |
Busy can't be longer than 600 ms in half-cadence |
Definition at line 123 of file dsp.c.
00123 { 00124 BUSY_PERCENT = 10, /*!< The percentage difference between the two last tone periods */ 00125 BUSY_PAT_PERCENT = 8, /*!< The percentage difference between measured and actual pattern */ 00126 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */ 00127 BUSY_MIN = 150, /*!< Busy must be at least 150 ms in half-cadence */ 00128 BUSY_MAX = 600 /*!< Busy can't be longer than 600 ms in half-cadence */ 00129 };
enum freq_index |
enum gsamp_size |
Number of goertzels for progress detect
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 63 of file dsp.c.
00063 { 00064 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ 00065 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */ 00066 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */ 00067 };
enum gsamp_thresh |
All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)
Definition at line 138 of file dsp.c.
00138 { 00139 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */ 00140 THRESH_TALK = 2, /*!< Talk detection does not work continuously */ 00141 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */ 00142 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */ 00143 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */ 00144 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */ 00145 };
enum prog_mode |
Definition at line 69 of file dsp.c.
00069 { 00070 PROG_MODE_NA = 0, 00071 PROG_MODE_CR, 00072 PROG_MODE_UK 00073 };
static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len | |||
) | [static] |
Definition at line 1036 of file dsp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_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().
01037 { 01038 int x; 01039 int y; 01040 int pass; 01041 int newstate = DSP_TONE_STATE_SILENCE; 01042 int res = 0; 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 for (y = 0; y < dsp->freqcount; y++) { 01051 goertzel_sample(&dsp->freqs[y], s[x]); 01052 } 01053 dsp->genergy += s[x] * s[x]; 01054 } 01055 s += pass; 01056 dsp->gsamps += pass; 01057 len -= pass; 01058 if (dsp->gsamps == dsp->gsamp_size) { 01059 float hz[7]; 01060 for (y = 0; y < 7; y++) { 01061 hz[y] = goertzel_result(&dsp->freqs[y]); 01062 } 01063 switch (dsp->progmode) { 01064 case PROG_MODE_NA: 01065 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01066 newstate = DSP_TONE_STATE_BUSY; 01067 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01068 newstate = DSP_TONE_STATE_RINGING; 01069 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01070 newstate = DSP_TONE_STATE_DIALTONE; 01071 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01072 newstate = DSP_TONE_STATE_SPECIAL1; 01073 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01074 /* End of SPECIAL1 or middle of SPECIAL2 */ 01075 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) { 01076 newstate = DSP_TONE_STATE_SPECIAL2; 01077 } 01078 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01079 /* End of SPECIAL2 or middle of SPECIAL3 */ 01080 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01081 newstate = DSP_TONE_STATE_SPECIAL3; 01082 } 01083 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01084 newstate = DSP_TONE_STATE_TALKING; 01085 } else { 01086 newstate = DSP_TONE_STATE_SILENCE; 01087 } 01088 break; 01089 case PROG_MODE_CR: 01090 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01091 newstate = DSP_TONE_STATE_RINGING; 01092 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01093 newstate = DSP_TONE_STATE_TALKING; 01094 } else { 01095 newstate = DSP_TONE_STATE_SILENCE; 01096 } 01097 break; 01098 case PROG_MODE_UK: 01099 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { 01100 newstate = DSP_TONE_STATE_HUNGUP; 01101 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { 01102 newstate = DSP_TONE_STATE_DIALTONE; 01103 } 01104 break; 01105 default: 01106 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01107 } 01108 if (newstate == dsp->tstate) { 01109 dsp->tcount++; 01110 if (dsp->ringtimeout) { 01111 dsp->ringtimeout++; 01112 } 01113 switch (dsp->tstate) { 01114 case DSP_TONE_STATE_RINGING: 01115 if ((dsp->features & DSP_PROGRESS_RINGING) && 01116 (dsp->tcount == THRESH_RING)) { 01117 res = AST_CONTROL_RINGING; 01118 dsp->ringtimeout = 1; 01119 } 01120 break; 01121 case DSP_TONE_STATE_BUSY: 01122 if ((dsp->features & DSP_PROGRESS_BUSY) && 01123 (dsp->tcount == THRESH_BUSY)) { 01124 res = AST_CONTROL_BUSY; 01125 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01126 } 01127 break; 01128 case DSP_TONE_STATE_TALKING: 01129 if ((dsp->features & DSP_PROGRESS_TALK) && 01130 (dsp->tcount == THRESH_TALK)) { 01131 res = AST_CONTROL_ANSWER; 01132 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01133 } 01134 break; 01135 case DSP_TONE_STATE_SPECIAL3: 01136 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01137 (dsp->tcount == THRESH_CONGESTION)) { 01138 res = AST_CONTROL_CONGESTION; 01139 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01140 } 01141 break; 01142 case DSP_TONE_STATE_HUNGUP: 01143 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01144 (dsp->tcount == THRESH_HANGUP)) { 01145 res = AST_CONTROL_HANGUP; 01146 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01147 } 01148 break; 01149 } 01150 if (dsp->ringtimeout == THRESH_RING2ANSWER) { 01151 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 01152 res = AST_CONTROL_ANSWER; 01153 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01154 } 01155 } else { 01156 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01157 ast_debug(5, "Start state %d\n", newstate); 01158 dsp->tstate = newstate; 01159 dsp->tcount = 1; 01160 } 01161 01162 /* Reset goertzel */ 01163 for (x = 0; x < 7; x++) { 01164 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01165 } 01166 dsp->gsamps = 0; 01167 dsp->genergy = 0.0; 01168 } 01169 } 01170 01171 return res; 01172 }
static int __ast_dsp_silence_noise | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence, | |||
int * | totalnoise | |||
) | [static] |
Definition at line 1187 of file dsp.c.
References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalnoise, and ast_dsp::totalsilence.
Referenced by ast_dsp_noise(), ast_dsp_process(), and ast_dsp_silence().
01188 { 01189 int accum; 01190 int x; 01191 int res = 0; 01192 01193 if (!len) { 01194 return 0; 01195 } 01196 accum = 0; 01197 for (x = 0; x < len; x++) { 01198 accum += abs(s[x]); 01199 } 01200 accum /= len; 01201 if (accum < dsp->threshold) { 01202 /* Silent */ 01203 dsp->totalsilence += len / 8; 01204 #ifdef DEBUG_DSP_BUSYDETECT 01205 fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum); 01206 #endif 01207 if (dsp->totalnoise) { 01208 /* Move and save history */ 01209 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0])); 01210 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01211 /* check if previous tone differs BUSY_PERCENT from the one before it */ 01212 int tone1 = dsp->historicnoise[DSP_HISTORY - 1]; 01213 int tone2 = dsp->historicnoise[DSP_HISTORY - 2]; 01214 if (tone1 < tone2) { 01215 if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2) 01216 dsp->busymaybe = 1; 01217 else 01218 dsp->busymaybe = 0; 01219 } else { 01220 if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2) 01221 dsp->busymaybe = 1; 01222 else 01223 dsp->busymaybe = 0; 01224 } 01225 } 01226 dsp->totalnoise = 0; 01227 res = 1; 01228 } else { 01229 /* Not silent */ 01230 dsp->totalnoise += len / 8; 01231 #ifdef DEBUG_DSP_BUSYDETECT 01232 fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum); 01233 #endif 01234 if (dsp->totalsilence) { 01235 /* Move and save history */ 01236 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0])); 01237 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01238 } 01239 dsp->totalsilence = 0; 01240 } 01241 if (totalsilence) { 01242 *totalsilence = dsp->totalsilence; 01243 } 01244 if (totalnoise) { 01245 *totalnoise = dsp->totalnoise; 01246 } 01247 return res; 01248 }
static int _dsp_init | ( | int | reload | ) | [static] |
Definition at line 1792 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().
01793 { 01794 struct ast_config *cfg; 01795 struct ast_variable *v; 01796 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01797 int cfg_threshold; 01798 float cfg_twist; 01799 01800 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 01801 return 0; 01802 } 01803 01804 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01805 dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST; 01806 dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST; 01807 relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST; 01808 relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST; 01809 dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN; 01810 dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END; 01811 01812 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01813 return 0; 01814 } 01815 01816 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) { 01817 if (!strcasecmp(v->name, "silencethreshold")) { 01818 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01819 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01820 } else if (cfg_threshold < 0) { 01821 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold); 01822 } else { 01823 thresholds[THRESHOLD_SILENCE] = cfg_threshold; 01824 } 01825 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) { 01826 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01827 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01828 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01829 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist); 01830 } else { 01831 dtmf_normal_twist = cfg_twist; 01832 } 01833 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) { 01834 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01835 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01836 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01837 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist); 01838 } else { 01839 dtmf_reverse_twist = cfg_twist; 01840 } 01841 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) { 01842 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01843 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01844 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01845 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist); 01846 } else { 01847 relax_dtmf_normal_twist = cfg_twist; 01848 } 01849 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) { 01850 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01851 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01852 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01853 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist); 01854 } else { 01855 relax_dtmf_reverse_twist = cfg_twist; 01856 } 01857 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) { 01858 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01859 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01860 } else if (cfg_threshold < 1) { /* must be 1 or greater */ 01861 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin); 01862 } else { 01863 dtmf_hits_to_begin = cfg_threshold; 01864 } 01865 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) { 01866 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01867 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01868 } else if (cfg_threshold < 1) { /* must be 1 or greater */ 01869 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end); 01870 } else { 01871 dtmf_misses_to_end = cfg_threshold; 01872 } 01873 } 01874 } 01875 ast_config_destroy(cfg); 01876 01877 return 0; 01878 }
static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
int | mf | |||
) | [static] |
Definition at line 528 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().
00529 { 00530 s->current_digits = 0; 00531 s->detected_digits = 0; 00532 s->lost_digits = 0; 00533 s->digits[0] = '\0'; 00534 00535 if (mf) { 00536 ast_mf_detect_init(&s->td.mf); 00537 } else { 00538 ast_dtmf_detect_init(&s->td.dtmf); 00539 } 00540 }
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 1250 of file dsp.c.
References ast_debug, ast_log(), BUSY_MAX, BUSY_MIN, ast_dsp::busy_pattern_fuzzy, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busymaybe, ast_dsp::busytoneonly, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_ERROR, LOG_NOTICE, MAX, and option_debug.
Referenced by ast_dsp_process().
01251 { 01252 int res = 0, x; 01253 int avgsilence = 0, hitsilence = 0; 01254 int avgtone = 0, hittone = 0; 01255 #ifdef DEBUG_DSP_BUSYDETECT 01256 char buf[16]; 01257 char silence_list[64]="", tone_list[64]=""; 01258 #endif 01259 01260 if (!dsp->busymaybe) { 01261 return res; 01262 } 01263 dsp->busymaybe = 0; 01264 01265 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01266 avgsilence += dsp->historicsilence[x]; 01267 avgtone += dsp->historicnoise[x]; 01268 } 01269 avgsilence /= dsp->busycount; 01270 avgtone /= dsp->busycount; 01271 #ifdef DEBUG_DSP_BUSYDETECT 01272 sprintf(silence_list,"Silences: "); 01273 sprintf(tone_list,"Tones: "); 01274 #endif 01275 for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) { 01276 #ifdef DEBUG_DSP_BUSYDETECT 01277 snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]); 01278 strcat(silence_list, buf); 01279 snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]); 01280 strcat(tone_list, buf); 01281 #endif 01282 if (!dsp->busytoneonly) { 01283 if (avgsilence > dsp->historicsilence[x]) { 01284 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01285 hitsilence++; 01286 } else { 01287 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01288 hitsilence++; 01289 } 01290 } 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 #ifdef DEBUG_DSP_BUSYDETECT 01302 fprintf(stderr, "BUSY DETECTOR\n"); 01303 fprintf(stderr, "%s\n", tone_list); 01304 fprintf(stderr, "%s\n", silence_list) 01305 #endif 01306 if ((dsp->busytoneonly || 01307 (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) && 01308 (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01309 if (dsp->busycompare) { 01310 if (dsp->busytoneonly) { 01311 res = 1; 01312 ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare"); 01313 } else { 01314 if (avgtone > avgsilence) { 01315 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01316 res = 1; 01317 } else { 01318 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01319 res = 1; 01320 } 01321 } 01322 } else { 01323 res = 1; 01324 } 01325 } 01326 /* If we know the expected busy tone length, check we are in the range */ 01327 if (res && (dsp->busy_tonelength > 0)) { 01328 if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) { 01329 #ifdef BUSYDETECT_DEBUG 01330 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01331 avgtone, dsp->busy_tonelength); 01332 #endif 01333 res = 0; 01334 } 01335 } 01336 /* If we know the expected busy tone silent-period length, check we are in the range */ 01337 if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) { 01338 if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) { 01339 #ifdef BUSYDETECT_DEBUG 01340 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01341 avgsilence, dsp->busy_quietlength); 01342 #endif 01343 res = 0; 01344 } 01345 } 01346 if (res) { 01347 if (option_debug) 01348 ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01349 } else { 01350 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01351 } 01352 return res; 01353 }
Scans for progress indication in audio.
Definition at line 1174 of file dsp.c.
References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
01175 { 01176 if (inf->frametype != AST_FRAME_VOICE) { 01177 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01178 return 0; 01179 } 01180 if (inf->subclass.codec != AST_FORMAT_SLINEAR) { 01181 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01182 return 0; 01183 } 01184 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); 01185 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1694 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(), and my_dsp_reset_and_flush_digits().
01695 { 01696 int i; 01697 01698 dsp->dtmf_began = 0; 01699 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01700 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01701 /* Reinitialise the detector for the next block */ 01702 for (i = 0; i < 6; i++) { 01703 goertzel_reset(&s->tone_out[i]); 01704 } 01705 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01706 s->current_sample = 0; 01707 } else { 01708 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01709 /* Reinitialise the detector for the next block */ 01710 for (i = 0; i < 4; i++) { 01711 goertzel_reset(&s->row_out[i]); 01712 goertzel_reset(&s->col_out[i]); 01713 } 01714 s->lasthit = s->current_hit = 0; 01715 s->energy = 0.0; 01716 s->current_sample = 0; 01717 s->hits = 0; 01718 s->misses = 0; 01719 } 01720 01721 dsp->digit_state.digits[0] = '\0'; 01722 dsp->digit_state.current_digits = 0; 01723 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1650 of file dsp.c.
References ast_free.
Referenced by __ast_play_and_record(), __oh323_destroy(), analog_ss_thread(), background_detect_exec(), chan_list_destructor(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_endpoint(), destroy_session(), disable_dsp_detect(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), my_all_subchannels_hungup(), my_dsp_set_digitmode(), record_exec(), and sip_rtp_read().
01651 { 01652 ast_free(dsp); 01653 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1787 of file dsp.c.
References ast_dsp::tcount.
Referenced by dahdi_read().
01788 { 01789 return dsp->tcount; 01790 }
int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1880 of file dsp.c.
Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), and setup_privacy_args().
01881 { 01882 return thresholds[which]; 01883 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1782 of file dsp.c.
References ast_dsp::tstate.
Referenced by dahdi_read().
01783 { 01784 return dsp->tstate; 01785 }
int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1885 of file dsp.c.
References _dsp_init().
Referenced by main().
01886 { 01887 return _dsp_init(0); 01888 }
struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1607 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, ast_dsp::busy_pattern_fuzzy, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busytoneonly, 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, and ast_dsp::threshold.
Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), enable_dsp_detect(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), my_dsp_set_digitmode(), read_config(), and record_exec().
01608 { 01609 struct ast_dsp *dsp; 01610 01611 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01612 dsp->threshold = DEFAULT_THRESHOLD; 01613 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01614 dsp->busycount = DSP_HISTORY; 01615 dsp->digitmode = DSP_DIGITMODE_DTMF; 01616 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01617 dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT; 01618 #ifdef BUSYDETECT_TONEONLY 01619 dsp->busytoneonly = 1; 01620 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01621 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE"); 01622 #endif 01623 #else 01624 dsp->busytoneonly = 0; 01625 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01626 dsp->busycompare = 1; 01627 #else 01628 dsp->busycompare = 0; 01629 #endif 01630 #endif 01631 /* Initialize digit detector */ 01632 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01633 dsp->display_inband_dtmf_warning = 1; 01634 /* Initialize initial DSP progress detect parameters */ 01635 ast_dsp_prog_reset(dsp); 01636 /* Initialize fax detector */ 01637 ast_fax_detect_init(dsp); 01638 } 01639 return dsp; 01640 }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1373 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
Referenced by do_waiting().
01374 { 01375 short *s; 01376 int len; 01377 01378 if (f->frametype != AST_FRAME_VOICE) { 01379 ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); 01380 return 0; 01381 } 01382 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01383 ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); 01384 return 0; 01385 } 01386 s = f->data.ptr; 01387 len = f->datalen/2; 01388 return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); 01389 }
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 1392 of file dsp.c.
References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), ast_channel::_softhangup, AST_ALAW, ast_alloca, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_frisolate(), ast_getformatname(), AST_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_frame_subclass::codec, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, 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::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, ast_frame::ptr, SAMPLE_RATE, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().
Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().
01393 { 01394 int silence; 01395 int res; 01396 int digit = 0, fax_digit = 0; 01397 int x; 01398 short *shortdata; 01399 unsigned char *odata; 01400 int len; 01401 struct ast_frame *outf = NULL; 01402 01403 if (!af) { 01404 return NULL; 01405 } 01406 if (af->frametype != AST_FRAME_VOICE) { 01407 return af; 01408 } 01409 01410 odata = af->data.ptr; 01411 len = af->datalen; 01412 /* Make sure we have short data */ 01413 switch (af->subclass.codec) { 01414 case AST_FORMAT_SLINEAR: 01415 shortdata = af->data.ptr; 01416 len = af->datalen / 2; 01417 break; 01418 case AST_FORMAT_ULAW: 01419 case AST_FORMAT_TESTLAW: 01420 shortdata = ast_alloca(af->datalen * 2); 01421 for (x = 0;x < len; x++) { 01422 shortdata[x] = AST_MULAW(odata[x]); 01423 } 01424 break; 01425 case AST_FORMAT_ALAW: 01426 shortdata = ast_alloca(af->datalen * 2); 01427 for (x = 0; x < len; x++) { 01428 shortdata[x] = AST_ALAW(odata[x]); 01429 } 01430 break; 01431 default: 01432 /*Display warning only once. Otherwise you would get hundreds of warnings every second */ 01433 if (dsp->display_inband_dtmf_warning) 01434 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec)); 01435 dsp->display_inband_dtmf_warning = 0; 01436 return af; 01437 } 01438 01439 /* Initially we do not want to mute anything */ 01440 dsp->mute_fragments = 0; 01441 01442 /* Need to run the silence detection stuff for silence suppression and busy detection */ 01443 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { 01444 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); 01445 } 01446 01447 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01448 memset(&dsp->f, 0, sizeof(dsp->f)); 01449 dsp->f.frametype = AST_FRAME_NULL; 01450 ast_frfree(af); 01451 return ast_frisolate(&dsp->f); 01452 } 01453 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01454 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01455 memset(&dsp->f, 0, sizeof(dsp->f)); 01456 dsp->f.frametype = AST_FRAME_CONTROL; 01457 /* Signal this as it was a channel hangup, to avoid msg "channel.c:3473 ast_waitfordigit_full: Unexpected control subclass '5'" */ 01458 dsp->f.subclass.integer = AST_CONTROL_HANGUP; 01459 ast_frfree(af); 01460 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01461 return ast_frisolate(&dsp->f); 01462 } 01463 01464 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { 01465 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { 01466 fax_digit = 'f'; 01467 } 01468 01469 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { 01470 fax_digit = 'e'; 01471 } 01472 } 01473 01474 if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { 01475 if (dsp->digitmode & DSP_DIGITMODE_MF) 01476 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01477 else 01478 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01479 01480 if (dsp->digit_state.current_digits) { 01481 int event = 0, event_len = 0; 01482 char event_digit = 0; 01483 01484 if (!dsp->dtmf_began) { 01485 /* We have not reported DTMF_BEGIN for anything yet */ 01486 01487 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01488 event = AST_FRAME_DTMF_BEGIN; 01489 event_digit = dsp->digit_state.digits[0]; 01490 } 01491 dsp->dtmf_began = 1; 01492 01493 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { 01494 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ 01495 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01496 event = AST_FRAME_DTMF_END; 01497 event_digit = dsp->digit_state.digits[0]; 01498 event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; 01499 } 01500 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); 01501 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0])); 01502 dsp->digit_state.current_digits--; 01503 dsp->dtmf_began = 0; 01504 01505 if (dsp->features & DSP_FEATURE_BUSY_DETECT) { 01506 /* Reset Busy Detector as we have some confirmed activity */ 01507 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01508 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01509 ast_debug(1, "DTMF Detected - Reset busydetector\n"); 01510 } 01511 } 01512 01513 if (event) { 01514 memset(&dsp->f, 0, sizeof(dsp->f)); 01515 dsp->f.frametype = event; 01516 dsp->f.subclass.integer = event_digit; 01517 dsp->f.len = event_len; 01518 outf = &dsp->f; 01519 goto done; 01520 } 01521 } 01522 } 01523 01524 if (fax_digit) { 01525 /* Fax was detected - digit is either 'f' or 'e' */ 01526 01527 memset(&dsp->f, 0, sizeof(dsp->f)); 01528 dsp->f.frametype = AST_FRAME_DTMF; 01529 dsp->f.subclass.integer = fax_digit; 01530 outf = &dsp->f; 01531 goto done; 01532 } 01533 01534 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01535 res = __ast_dsp_call_progress(dsp, shortdata, len); 01536 if (res) { 01537 switch (res) { 01538 case AST_CONTROL_ANSWER: 01539 case AST_CONTROL_BUSY: 01540 case AST_CONTROL_RINGING: 01541 case AST_CONTROL_CONGESTION: 01542 case AST_CONTROL_HANGUP: 01543 memset(&dsp->f, 0, sizeof(dsp->f)); 01544 dsp->f.frametype = AST_FRAME_CONTROL; 01545 dsp->f.subclass.integer = res; 01546 dsp->f.src = "dsp_progress"; 01547 if (chan) 01548 ast_queue_frame(chan, &dsp->f); 01549 break; 01550 default: 01551 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01552 } 01553 } 01554 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { 01555 res = __ast_dsp_call_progress(dsp, shortdata, len); 01556 } 01557 01558 done: 01559 /* Mute fragment of the frame */ 01560 for (x = 0; x < dsp->mute_fragments; x++) { 01561 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); 01562 } 01563 01564 switch (af->subclass.codec) { 01565 case AST_FORMAT_SLINEAR: 01566 break; 01567 case AST_FORMAT_ULAW: 01568 for (x = 0; x < len; x++) { 01569 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); 01570 } 01571 break; 01572 case AST_FORMAT_ALAW: 01573 for (x = 0; x < len; x++) { 01574 odata[x] = AST_LIN2A((unsigned short) shortdata[x]); 01575 } 01576 break; 01577 } 01578 01579 if (outf) { 01580 if (chan) { 01581 ast_queue_frame(chan, af); 01582 } 01583 ast_frfree(af); 01584 return ast_frisolate(outf); 01585 } else { 01586 return af; 01587 } 01588 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1590 of file dsp.c.
References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, ast_dsp::ringtimeout, and progress::size.
Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().
01591 { 01592 int max = 0; 01593 int x; 01594 01595 dsp->gsamp_size = modes[dsp->progmode].size; 01596 dsp->gsamps = 0; 01597 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01598 if (modes[dsp->progmode].freqs[x]) { 01599 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01600 max = x + 1; 01601 } 01602 } 01603 dsp->freqcount = max; 01604 dsp->ringtimeout= 0; 01605 }
int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1890 of file dsp.c.
References _dsp_init().
01891 { 01892 return _dsp_init(1); 01893 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1725 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().
01726 { 01727 int x; 01728 01729 dsp->totalsilence = 0; 01730 dsp->gsamps = 0; 01731 for (x = 0; x < 4; x++) { 01732 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01733 } 01734 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01735 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01736 dsp->ringtimeout= 0; 01737 }
void ast_dsp_set_busy_compare | ( | struct ast_dsp * | dsp, | |
int | compare | |||
) |
Set if silence and noice lengths must be compared for busy.
Definition at line 1674 of file dsp.c.
References ast_dsp::busycompare.
Referenced by dahdi_new().
01675 { 01676 if (compare > 0) 01677 dsp->busycompare = 1; 01678 else 01679 dsp->busycompare = 0; 01680 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1663 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01664 { 01665 if (cadences < 4) { 01666 cadences = 4; 01667 } 01668 if (cadences > DSP_HISTORY) { 01669 cadences = DSP_HISTORY; 01670 } 01671 dsp->busycount = cadences; 01672 }
void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
int | tonelength, | |||
int | quietlength, | |||
int | fuzzy | |||
) |
Set expected lengths of the busy tones.
Definition at line 1682 of file dsp.c.
References ast_debug, ast_dsp::busy_pattern_fuzzy, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and ast_dsp::busytoneonly.
Referenced by dahdi_new().
01683 { 01684 dsp->busy_tonelength = tonelength; 01685 if (quietlength > 0) 01686 dsp->busy_quietlength = quietlength; 01687 else 01688 dsp->busytoneonly = 1; 01689 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01690 if( fuzzy > 0 && fuzzy < 50 ) 01691 dsp->busy_pattern_fuzzy = fuzzy; 01692 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1763 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
int ast_dsp_set_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1739 of file dsp.c.
References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.
Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), mkintf(), and my_dsp_set_digitmode().
01740 { 01741 int new; 01742 int old; 01743 01744 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01745 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01746 if (old != new) { 01747 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01748 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01749 } 01750 dsp->digitmode = digitmode; 01751 return 0; 01752 }
int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
int | faxmode | |||
) |
Set fax mode.
Definition at line 1754 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01755 { 01756 if (dsp->faxmode != faxmode) { 01757 ast_fax_detect_init(dsp); 01758 } 01759 dsp->faxmode = faxmode; 01760 return 0; 01761 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1642 of file dsp.c.
References ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_DIGIT_DETECT, and ast_dsp::features.
Referenced by __oh323_new(), dahdi_handle_dtmf(), dahdi_new(), dahdi_read(), dahdi_setoption(), disable_dtmf_detect(), enable_dsp_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), my_handle_dtmf(), read_config(), and sip_rtp_read().
01643 { 01644 dsp->features = features; 01645 if (!(features & DSP_FEATURE_DIGIT_DETECT)) { 01646 dsp->display_inband_dtmf_warning = 0; 01647 } 01648 }
void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
int | threshold | |||
) |
Set threshold value for silence.
Definition at line 1655 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), dahdi_new(), do_waiting(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), and record_exec().
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1355 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), debug_check_frame_for_silence(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
01356 { 01357 short *s; 01358 int len; 01359 01360 if (f->frametype != AST_FRAME_VOICE) { 01361 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01362 return 0; 01363 } 01364 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01365 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01366 return 0; 01367 } 01368 s = f->data.ptr; 01369 len = f->datalen/2; 01370 return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); 01371 }
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.
Definition at line 1777 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
01778 { 01779 return (dsp->mute_fragments > 0); 01780 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 501 of file dsp.c.
References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, DTMF_GSIZE, dtmf_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().
00502 { 00503 int i; 00504 00505 s->lasthit = 0; 00506 s->current_hit = 0; 00507 for (i = 0; i < 4; i++) { 00508 goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE); 00509 goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE); 00510 s->energy = 0.0; 00511 } 00512 s->current_sample = 0; 00513 s->hits = 0; 00514 s->misses = 0; 00515 }
static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 495 of file dsp.c.
References ast_tone_detect_init(), ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, and FAX_TONE_CNG_FREQ.
Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().
00496 { 00497 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00498 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00499 }
static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 517 of file dsp.c.
References mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, goertzel_init(), mf_detect_state_t::hits, MF_GSIZE, and mf_detect_state_t::tone_out.
Referenced by ast_digit_detect_init().
00518 { 00519 int i; 00520 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00521 for (i = 0; i < 6; i++) { 00522 goertzel_init (&s->tone_out[i], mf_tones[i], MF_GSIZE); 00523 } 00524 s->current_sample = 0; 00525 s->current_hit = 0; 00526 }
static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
int | freq, | |||
int | duration, | |||
int | amp | |||
) | [static] |
Definition at line 435 of file dsp.c.
References ast_debug, tone_detect_state_t::block_size, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_init(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, SAMPLE_RATE, SAMPLES_IN_FRAME, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, tone_detect_state_t::threshold, and tone_detect_state_t::tone.
Referenced by ast_fax_detect_init().
00436 { 00437 int duration_samples; 00438 float x; 00439 int periods_in_block; 00440 00441 s->freq = freq; 00442 00443 /* Desired tone duration in samples */ 00444 duration_samples = duration * SAMPLE_RATE / 1000; 00445 /* We want to allow 10% deviation of tone duration */ 00446 duration_samples = duration_samples * 9 / 10; 00447 00448 /* If we want to remove tone, it is important to have block size not 00449 to exceed frame size. Otherwise by the moment tone is detected it is too late 00450 to squelch it from previous frames */ 00451 s->block_size = SAMPLES_IN_FRAME; 00452 00453 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00454 00455 /* Make sure we will have at least 5 periods at target frequency for analisys. 00456 This may make block larger than expected packet and will make squelching impossible 00457 but at least we will be detecting the tone */ 00458 if (periods_in_block < 5) 00459 periods_in_block = 5; 00460 00461 /* Now calculate final block size. It will contain integer number of periods */ 00462 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00463 00464 /* tone_detect is currently only used to detect fax tones and we 00465 do not need squelching the fax tones */ 00466 s->squelch = 0; 00467 00468 /* Account for the first and the last block to be incomplete 00469 and thus no tone will be detected in them */ 00470 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00471 00472 goertzel_init(&s->tone, freq, s->block_size); 00473 00474 s->samples_pending = s->block_size; 00475 s->hit_count = 0; 00476 s->last_hit = 0; 00477 s->energy = 0.0; 00478 00479 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00480 According to Parseval's theorem the energy computed in time domain equals to energy 00481 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00482 from the energy in the time domain we will get energy of the remaining signal (without the tone 00483 we are detecting). We will be checking that 00484 10*log(Ew / (Et - Ew)) > amp 00485 Calculate threshold so that we will be actually checking 00486 Ew > Et * threshold 00487 */ 00488 00489 x = pow(10.0, amp / 10.0); 00490 s->threshold = x / (x + 1); 00491 00492 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00493 }
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 661 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().
00662 { 00663 float row_energy[4]; 00664 float col_energy[4]; 00665 int i; 00666 int j; 00667 int sample; 00668 short samp; 00669 int best_row; 00670 int best_col; 00671 int hit; 00672 int limit; 00673 fragment_t mute = {0, 0}; 00674 00675 if (squelch && s->td.dtmf.mute_samples > 0) { 00676 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples; 00677 s->td.dtmf.mute_samples -= mute.end; 00678 } 00679 00680 hit = 0; 00681 for (sample = 0; sample < samples; sample = limit) { 00682 /* DTMF_GSIZE is optimised to meet the DTMF specs. */ 00683 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) { 00684 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample); 00685 } else { 00686 limit = samples; 00687 } 00688 /* The following unrolled loop takes only 35% (rough estimate) of the 00689 time of a rolled loop on the machine on which it was developed */ 00690 for (j = sample; j < limit; j++) { 00691 samp = amp[j]; 00692 s->td.dtmf.energy += (int32_t) samp * (int32_t) samp; 00693 /* With GCC 2.95, the following unrolled code seems to take about 35% 00694 (rough estimate) as long as a neat little 0-3 loop */ 00695 goertzel_sample(s->td.dtmf.row_out, samp); 00696 goertzel_sample(s->td.dtmf.col_out, samp); 00697 goertzel_sample(s->td.dtmf.row_out + 1, samp); 00698 goertzel_sample(s->td.dtmf.col_out + 1, samp); 00699 goertzel_sample(s->td.dtmf.row_out + 2, samp); 00700 goertzel_sample(s->td.dtmf.col_out + 2, samp); 00701 goertzel_sample(s->td.dtmf.row_out + 3, samp); 00702 goertzel_sample(s->td.dtmf.col_out + 3, samp); 00703 } 00704 s->td.dtmf.current_sample += (limit - sample); 00705 if (s->td.dtmf.current_sample < DTMF_GSIZE) { 00706 continue; 00707 } 00708 /* We are at the end of a DTMF detection block */ 00709 /* Find the peak row and the peak column */ 00710 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00711 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00712 00713 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00714 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00715 if (row_energy[i] > row_energy[best_row]) { 00716 best_row = i; 00717 } 00718 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00719 if (col_energy[i] > col_energy[best_col]) { 00720 best_col = i; 00721 } 00722 } 00723 hit = 0; 00724 /* Basic signal level test and the twist test */ 00725 if (row_energy[best_row] >= DTMF_THRESHOLD && 00726 col_energy[best_col] >= DTMF_THRESHOLD && 00727 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) && 00728 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) { 00729 /* Relative peak test */ 00730 for (i = 0; i < 4; i++) { 00731 if ((i != best_col && 00732 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00733 (i != best_row 00734 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00735 break; 00736 } 00737 } 00738 /* ... and fraction of total energy test */ 00739 if (i >= 4 && 00740 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) { 00741 /* Got a hit */ 00742 hit = dtmf_positions[(best_row << 2) + best_col]; 00743 } 00744 } 00745 00746 /* 00747 * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03) 00748 * (40ms reference is tunable with hits_to_begin and misses_to_end) 00749 * each hit/miss is 12.75ms with DTMF_GSIZE at 102 00750 * 00751 * Character recognition: When not DRC *(1) and then 00752 * Shall exist VSC > 40 ms (hits_to_begin) 00753 * May exist 20 ms <= VSC <= 40 ms 00754 * Shall not exist VSC < 20 ms 00755 * 00756 * Character recognition: When DRC and then 00757 * Shall cease Not VSC > 40 ms (misses_to_end) 00758 * May cease 20 ms >= Not VSC >= 40 ms 00759 * Shall not cease Not VSC < 20 ms 00760 * 00761 * *(1) or optionally a different digit recognition condition 00762 * 00763 * Legend: VSC The continuous existence of a valid signal condition. 00764 * Not VSC The continuous non-existence of valid signal condition. 00765 * DRC The existence of digit recognition condition. 00766 * Not DRC The non-existence of digit recognition condition. 00767 */ 00768 00769 /* 00770 * Example: hits_to_begin=2 misses_to_end=3 00771 * -------A last_hit=A hits=0&1 00772 * ------AA hits=2 current_hit=A misses=0 BEGIN A 00773 * -----AA- misses=1 last_hit=' ' hits=0 00774 * ----AA-- misses=2 00775 * ---AA--- misses=3 current_hit=' ' END A 00776 * --AA---B last_hit=B hits=0&1 00777 * -AA---BC last_hit=C hits=0&1 00778 * AA---BCC hits=2 current_hit=C misses=0 BEGIN C 00779 * A---BCC- misses=1 last_hit=' ' hits=0 00780 * ---BCC-C misses=0 last_hit=C hits=0&1 00781 * --BCC-CC misses=0 00782 * 00783 * Example: hits_to_begin=3 misses_to_end=2 00784 * -------A last_hit=A hits=0&1 00785 * ------AA hits=2 00786 * -----AAA hits=3 current_hit=A misses=0 BEGIN A 00787 * ----AAAB misses=1 last_hit=B hits=0&1 00788 * ---AAABB misses=2 current_hit=' ' hits=2 END A 00789 * --AAABBB hits=3 current_hit=B misses=0 BEGIN B 00790 * -AAABBBB misses=0 00791 * 00792 * Example: hits_to_begin=2 misses_to_end=2 00793 * -------A last_hit=A hits=0&1 00794 * ------AA hits=2 current_hit=A misses=0 BEGIN A 00795 * -----AAB misses=1 hits=0&1 00796 * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B 00797 * ---AABBB misses=0 00798 */ 00799 00800 if (s->td.dtmf.current_hit) { 00801 /* We are in the middle of a digit already */ 00802 if (hit != s->td.dtmf.current_hit) { 00803 s->td.dtmf.misses++; 00804 if (s->td.dtmf.misses == dtmf_misses_to_end) { 00805 /* There were enough misses to consider digit ended */ 00806 s->td.dtmf.current_hit = 0; 00807 } 00808 } else { 00809 s->td.dtmf.misses = 0; 00810 /* Current hit was same as last, so increment digit duration (of last digit) */ 00811 s->digitlen[s->current_digits - 1] += DTMF_GSIZE; 00812 } 00813 } 00814 00815 /* Look for a start of a new digit no matter if we are already in the middle of some 00816 digit or not. This is because hits_to_begin may be smaller than misses_to_end 00817 and we may find begin of new digit before we consider last one ended. */ 00818 00819 if (hit != s->td.dtmf.lasthit) { 00820 s->td.dtmf.lasthit = hit; 00821 s->td.dtmf.hits = 0; 00822 } 00823 if (hit && hit != s->td.dtmf.current_hit) { 00824 s->td.dtmf.hits++; 00825 if (s->td.dtmf.hits == dtmf_hits_to_begin) { 00826 store_digit(s, hit); 00827 s->digitlen[s->current_digits - 1] = dtmf_hits_to_begin * DTMF_GSIZE; 00828 s->td.dtmf.current_hit = hit; 00829 s->td.dtmf.misses = 0; 00830 } 00831 } 00832 00833 /* If we had a hit in this block, include it into mute fragment */ 00834 if (squelch && hit) { 00835 if (mute.end < sample - DTMF_GSIZE) { 00836 /* There is a gap between fragments */ 00837 mute_fragment(dsp, &mute); 00838 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0; 00839 } 00840 mute.end = limit + DTMF_GSIZE; 00841 } 00842 00843 /* Reinitialise the detector for the next block */ 00844 for (i = 0; i < 4; i++) { 00845 goertzel_reset(&s->td.dtmf.row_out[i]); 00846 goertzel_reset(&s->td.dtmf.col_out[i]); 00847 } 00848 s->td.dtmf.energy = 0.0; 00849 s->td.dtmf.current_sample = 0; 00850 } 00851 00852 if (squelch && mute.end) { 00853 if (mute.end > samples) { 00854 s->td.dtmf.mute_samples = mute.end - samples; 00855 mute.end = samples; 00856 } 00857 mute_fragment(dsp, &mute); 00858 } 00859 00860 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00861 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 360 of file dsp.c.
References goertzel_state_t::chunky, cos, goertzel_state_t::fac, M_PI, SAMPLE_RATE, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().
static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 367 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().
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 351 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().
static void goertzel_sample | ( | goertzel_state_t * | s, | |
short | sample | |||
) | [inline, static] |
Definition at line 325 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), goertzel_update(), mf_detect(), and tone_detect().
static void goertzel_update | ( | goertzel_state_t * | s, | |
short * | samps, | |||
int | count | |||
) | [inline, static] |
Definition at line 341 of file dsp.c.
References goertzel_sample().
00342 { 00343 int i; 00344 00345 for (i = 0; i < count; i++) { 00346 goertzel_sample(s, samps[i]); 00347 } 00348 }
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 863 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().
00865 { 00866 float energy[6]; 00867 int best; 00868 int second_best; 00869 int i; 00870 int j; 00871 int sample; 00872 short samp; 00873 int hit; 00874 int limit; 00875 fragment_t mute = {0, 0}; 00876 00877 if (squelch && s->td.mf.mute_samples > 0) { 00878 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples; 00879 s->td.mf.mute_samples -= mute.end; 00880 } 00881 00882 hit = 0; 00883 for (sample = 0; sample < samples; sample = limit) { 00884 /* 80 is optimised to meet the MF specs. */ 00885 /* XXX So then why is MF_GSIZE defined as 120? */ 00886 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) { 00887 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00888 } else { 00889 limit = samples; 00890 } 00891 /* The following unrolled loop takes only 35% (rough estimate) of the 00892 time of a rolled loop on the machine on which it was developed */ 00893 for (j = sample; j < limit; j++) { 00894 /* With GCC 2.95, the following unrolled code seems to take about 35% 00895 (rough estimate) as long as a neat little 0-3 loop */ 00896 samp = amp[j]; 00897 goertzel_sample(s->td.mf.tone_out, samp); 00898 goertzel_sample(s->td.mf.tone_out + 1, samp); 00899 goertzel_sample(s->td.mf.tone_out + 2, samp); 00900 goertzel_sample(s->td.mf.tone_out + 3, samp); 00901 goertzel_sample(s->td.mf.tone_out + 4, samp); 00902 goertzel_sample(s->td.mf.tone_out + 5, samp); 00903 } 00904 s->td.mf.current_sample += (limit - sample); 00905 if (s->td.mf.current_sample < MF_GSIZE) { 00906 continue; 00907 } 00908 /* We're at the end of an MF detection block. */ 00909 /* Find the two highest energies. The spec says to look for 00910 two tones and two tones only. Taking this literally -ie 00911 only two tones pass the minimum threshold - doesn't work 00912 well. The sinc function mess, due to rectangular windowing 00913 ensure that! Find the two highest energies and ensure they 00914 are considerably stronger than any of the others. */ 00915 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00916 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00917 if (energy[0] > energy[1]) { 00918 best = 0; 00919 second_best = 1; 00920 } else { 00921 best = 1; 00922 second_best = 0; 00923 } 00924 /*endif*/ 00925 for (i = 2; i < 6; i++) { 00926 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00927 if (energy[i] >= energy[best]) { 00928 second_best = best; 00929 best = i; 00930 } else if (energy[i] >= energy[second_best]) { 00931 second_best = i; 00932 } 00933 } 00934 /* Basic signal level and twist tests */ 00935 hit = 0; 00936 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00937 && energy[best] < energy[second_best]*BELL_MF_TWIST 00938 && energy[best] * BELL_MF_TWIST > energy[second_best]) { 00939 /* Relative peak test */ 00940 hit = -1; 00941 for (i = 0; i < 6; i++) { 00942 if (i != best && i != second_best) { 00943 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00944 /* The best two are not clearly the best */ 00945 hit = 0; 00946 break; 00947 } 00948 } 00949 } 00950 } 00951 if (hit) { 00952 /* Get the values into ascending order */ 00953 if (second_best < best) { 00954 i = best; 00955 best = second_best; 00956 second_best = i; 00957 } 00958 best = best * 5 + second_best - 1; 00959 hit = bell_mf_positions[best]; 00960 /* Look for two successive similar results */ 00961 /* The logic in the next test is: 00962 For KP we need 4 successive identical clean detects, with 00963 two blocks of something different preceeding it. For anything 00964 else we need two successive identical clean detects, with 00965 two blocks of something different preceeding it. */ 00966 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00967 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00968 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00969 hit != s->td.mf.hits[0]))) { 00970 store_digit(s, hit); 00971 } 00972 } 00973 00974 00975 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00976 /* Two successive block without a hit terminate current digit */ 00977 s->td.mf.current_hit = 0; 00978 } 00979 00980 s->td.mf.hits[0] = s->td.mf.hits[1]; 00981 s->td.mf.hits[1] = s->td.mf.hits[2]; 00982 s->td.mf.hits[2] = s->td.mf.hits[3]; 00983 s->td.mf.hits[3] = s->td.mf.hits[4]; 00984 s->td.mf.hits[4] = hit; 00985 00986 /* If we had a hit in this block, include it into mute fragment */ 00987 if (squelch && hit) { 00988 if (mute.end < sample - MF_GSIZE) { 00989 /* There is a gap between fragments */ 00990 mute_fragment(dsp, &mute); 00991 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0; 00992 } 00993 mute.end = limit + MF_GSIZE; 00994 } 00995 00996 /* Reinitialise the detector for the next block */ 00997 for (i = 0; i < 6; i++) 00998 goertzel_reset(&s->td.mf.tone_out[i]); 00999 s->td.mf.current_sample = 0; 01000 } 01001 01002 if (squelch && mute.end) { 01003 if (mute.end > samples) { 01004 s->td.mf.mute_samples = mute.end - samples; 01005 mute.end = samples; 01006 } 01007 mute_fragment(dsp, &mute); 01008 } 01009 01010 return (s->td.mf.current_hit); /* return the debounced hit */ 01011 }
static void mute_fragment | ( | struct ast_dsp * | dsp, | |
fragment_t * | fragment | |||
) | [static] |
Definition at line 425 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().
00426 { 00427 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) { 00428 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n"); 00429 return; 00430 } 00431 00432 dsp->mute_data[dsp->mute_fragments++] = *fragment; 00433 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 1013 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
01014 { 01015 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 01016 /* Make sure absolute levels are high enough */ 01017 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) { 01018 return 0; 01019 } 01020 /* Amplify ignored stuff */ 01021 i2 *= TONE_THRESH; 01022 i1 *= TONE_THRESH; 01023 e *= TONE_THRESH; 01024 /* Check first tone */ 01025 if ((p1 < i1) || (p1 < i2) || (p1 < e)) { 01026 return 0; 01027 } 01028 /* And second */ 01029 if ((p2 < i1) || (p2 < i2) || (p2 < e)) { 01030 return 0; 01031 } 01032 /* Guess it's there... */ 01033 return 1; 01034 }
static void store_digit | ( | digit_detect_state_t * | s, | |
char | digit | |||
) | [static] |
Definition at line 648 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().
00649 { 00650 s->detected_digits++; 00651 if (s->current_digits < MAX_DTMF_DIGITS) { 00652 s->digitlen[s->current_digits] = 0; 00653 s->digits[s->current_digits++] = digit; 00654 s->digits[s->current_digits] = '\0'; 00655 } else { 00656 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00657 s->lost_digits++; 00658 } 00659 }
static int tone_detect | ( | struct ast_dsp * | dsp, | |
tone_detect_state_t * | s, | |||
int16_t * | amp, | |||
int | samples | |||
) | [static] |
Definition at line 542 of file dsp.c.
References ast_debug, tone_detect_state_t::block_size, fragment_t::end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute, mute_fragment(), tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, and tone_detect_state_t::tone.
Referenced by ast_dsp_process().
00543 { 00544 float tone_energy; 00545 int i; 00546 int hit = 0; 00547 int limit; 00548 int res = 0; 00549 int16_t *ptr; 00550 short samp; 00551 int start, end; 00552 fragment_t mute = {0, 0}; 00553 00554 if (s->squelch && s->mute_samples > 0) { 00555 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples; 00556 s->mute_samples -= mute.end; 00557 } 00558 00559 for (start = 0; start < samples; start = end) { 00560 /* Process in blocks. */ 00561 limit = samples - start; 00562 if (limit > s->samples_pending) { 00563 limit = s->samples_pending; 00564 } 00565 end = start + limit; 00566 00567 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00568 samp = *ptr; 00569 /* signed 32 bit int should be enough to square any possible signed 16 bit value */ 00570 s->energy += (int32_t) samp * (int32_t) samp; 00571 00572 goertzel_sample(&s->tone, samp); 00573 } 00574 00575 s->samples_pending -= limit; 00576 00577 if (s->samples_pending) { 00578 /* Finished incomplete (last) block */ 00579 break; 00580 } 00581 00582 tone_energy = goertzel_result(&s->tone); 00583 00584 /* Scale to make comparable */ 00585 tone_energy *= 2.0; 00586 s->energy *= s->block_size; 00587 00588 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)); 00589 hit = 0; 00590 if (tone_energy > s->energy * s->threshold) { 00591 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00592 hit = 1; 00593 } 00594 00595 if (s->hit_count) { 00596 s->hit_count++; 00597 } 00598 00599 if (hit == s->last_hit) { 00600 if (!hit) { 00601 /* Two successive misses. Tone ended */ 00602 s->hit_count = 0; 00603 } else if (!s->hit_count) { 00604 s->hit_count++; 00605 } 00606 00607 } 00608 00609 if (s->hit_count == s->hits_required) { 00610 ast_debug(1, "%d Hz done detected\n", s->freq); 00611 res = 1; 00612 } 00613 00614 s->last_hit = hit; 00615 00616 /* If we had a hit in this block, include it into mute fragment */ 00617 if (s->squelch && hit) { 00618 if (mute.end < start - s->block_size) { 00619 /* There is a gap between fragments */ 00620 mute_fragment(dsp, &mute); 00621 mute.start = (start > s->block_size) ? (start - s->block_size) : 0; 00622 } 00623 mute.end = end + s->block_size; 00624 } 00625 00626 /* Reinitialise the detector for the next block */ 00627 /* Reset for the next block */ 00628 goertzel_reset(&s->tone); 00629 00630 /* Advance to the next block */ 00631 s->energy = 0.0; 00632 s->samples_pending = s->block_size; 00633 00634 amp += limit; 00635 } 00636 00637 if (s->squelch && mute.end) { 00638 if (mute.end > samples) { 00639 s->mute_samples = mute.end - samples; 00640 mute.end = samples; 00641 } 00642 mute_fragment(dsp, &mute); 00643 } 00644 00645 return res; 00646 }
Referenced by ast_dsp_set_call_progress_zone(), and find_alias().
const char bell_mf_positions[] = "1247C-358A--69*---0B----#" [static] |
const int DEFAULT_SILENCE_THRESHOLD = 256 [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] |
Referenced by ast_dsp_prog_reset().
float relax_dtmf_normal_twist [static] |
float relax_dtmf_reverse_twist [static] |
int thresholds[THRESHOLD_MAX] [static] |