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 = 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 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_count (struct ast_dsp *dsp, int cadences) |
| Set number of required cadences for busy. | |
| void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength) |
| Set expected lengths of the busy tone. | |
| int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
| Set zone for doing progress detection. | |
| int | ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode) |
| Set digit mode. | |
| int | ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode) |
| Set fax mode. | |
| void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
| Select feature set. | |
| void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold) |
| Set threshold value for silence. | |
| int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
| Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. | |
| int | ast_dsp_was_muted (struct ast_dsp *dsp) |
| Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio. | |
| static void | ast_dtmf_detect_init (dtmf_detect_state_t *s) |
| static void | ast_fax_detect_init (struct ast_dsp *s) |
| static void | ast_mf_detect_init (mf_detect_state_t *s) |
| static void | ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp) |
| static int | dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
| static void | goertzel_init (goertzel_state_t *s, float freq, int samples) |
| static void | goertzel_reset (goertzel_state_t *s) |
| static float | goertzel_result (goertzel_state_t *s) |
| static void | goertzel_sample (goertzel_state_t *s, short sample) |
| static void | goertzel_update (goertzel_state_t *s, short *samps, int count) |
| static int | mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
| static void | mute_fragment (struct ast_dsp *dsp, fragment_t *fragment) |
| static int | pair_there (float p1, float p2, float i1, float i2, float e) |
| static void | store_digit (digit_detect_state_t *s, char digit) |
| static int | tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples) |
Variables | |
| static struct progalias | aliases [] |
| static 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 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 123 of file dsp.c.
00123 { 00124 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */ 00125 BUSY_PAT_PERCENT = 7, /*!< 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 = 75, /*!< Busy must be at least 80 ms in half-cadence */ 00128 BUSY_MAX =3100 /*!< Busy can't be longer than 3100 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 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, 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 int x; 01036 int y; 01037 int pass; 01038 int newstate = DSP_TONE_STATE_SILENCE; 01039 int res = 0; 01040 while (len) { 01041 /* Take the lesser of the number of samples we need and what we have */ 01042 pass = len; 01043 if (pass > dsp->gsamp_size - dsp->gsamps) { 01044 pass = dsp->gsamp_size - dsp->gsamps; 01045 } 01046 for (x = 0; x < pass; x++) { 01047 for (y = 0; y < dsp->freqcount; y++) { 01048 goertzel_sample(&dsp->freqs[y], s[x]); 01049 } 01050 dsp->genergy += s[x] * s[x]; 01051 } 01052 s += pass; 01053 dsp->gsamps += pass; 01054 len -= pass; 01055 if (dsp->gsamps == dsp->gsamp_size) { 01056 float hz[7]; 01057 for (y = 0; y < 7; y++) { 01058 hz[y] = goertzel_result(&dsp->freqs[y]); 01059 } 01060 switch (dsp->progmode) { 01061 case PROG_MODE_NA: 01062 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01063 newstate = DSP_TONE_STATE_BUSY; 01064 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01065 newstate = DSP_TONE_STATE_RINGING; 01066 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01067 newstate = DSP_TONE_STATE_DIALTONE; 01068 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01069 newstate = DSP_TONE_STATE_SPECIAL1; 01070 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01071 /* End of SPECIAL1 or middle of SPECIAL2 */ 01072 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) { 01073 newstate = DSP_TONE_STATE_SPECIAL2; 01074 } 01075 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01076 /* End of SPECIAL2 or middle of SPECIAL3 */ 01077 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01078 newstate = DSP_TONE_STATE_SPECIAL3; 01079 } 01080 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01081 newstate = DSP_TONE_STATE_TALKING; 01082 } else { 01083 newstate = DSP_TONE_STATE_SILENCE; 01084 } 01085 break; 01086 case PROG_MODE_CR: 01087 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01088 newstate = DSP_TONE_STATE_RINGING; 01089 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01090 newstate = DSP_TONE_STATE_TALKING; 01091 } else { 01092 newstate = DSP_TONE_STATE_SILENCE; 01093 } 01094 break; 01095 case PROG_MODE_UK: 01096 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { 01097 newstate = DSP_TONE_STATE_HUNGUP; 01098 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { 01099 newstate = DSP_TONE_STATE_DIALTONE; 01100 } 01101 break; 01102 default: 01103 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode); 01104 } 01105 if (newstate == dsp->tstate) { 01106 dsp->tcount++; 01107 if (dsp->ringtimeout) { 01108 dsp->ringtimeout++; 01109 } 01110 switch (dsp->tstate) { 01111 case DSP_TONE_STATE_RINGING: 01112 if ((dsp->features & DSP_PROGRESS_RINGING) && 01113 (dsp->tcount == THRESH_RING)) { 01114 res = AST_CONTROL_RINGING; 01115 dsp->ringtimeout = 1; 01116 } 01117 break; 01118 case DSP_TONE_STATE_BUSY: 01119 if ((dsp->features & DSP_PROGRESS_BUSY) && 01120 (dsp->tcount == THRESH_BUSY)) { 01121 res = AST_CONTROL_BUSY; 01122 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01123 } 01124 break; 01125 case DSP_TONE_STATE_TALKING: 01126 if ((dsp->features & DSP_PROGRESS_TALK) && 01127 (dsp->tcount == THRESH_TALK)) { 01128 res = AST_CONTROL_ANSWER; 01129 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01130 } 01131 break; 01132 case DSP_TONE_STATE_SPECIAL3: 01133 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01134 (dsp->tcount == THRESH_CONGESTION)) { 01135 res = AST_CONTROL_CONGESTION; 01136 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01137 } 01138 break; 01139 case DSP_TONE_STATE_HUNGUP: 01140 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01141 (dsp->tcount == THRESH_HANGUP)) { 01142 res = AST_CONTROL_HANGUP; 01143 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01144 } 01145 break; 01146 } 01147 if (dsp->ringtimeout == THRESH_RING2ANSWER) { 01148 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 01149 res = AST_CONTROL_ANSWER; 01150 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01151 } 01152 } else { 01153 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01154 ast_debug(5, "Start state %d\n", newstate); 01155 dsp->tstate = newstate; 01156 dsp->tcount = 1; 01157 } 01158 01159 /* Reset goertzel */ 01160 for (x = 0; x < 7; x++) { 01161 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01162 } 01163 dsp->gsamps = 0; 01164 dsp->genergy = 0.0; 01165 } 01166 } 01167 01168 return res; 01169 }
| static int __ast_dsp_silence_noise | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len, | |||
| int * | totalsilence, | |||
| int * | totalnoise | |||
| ) | [static] |
Definition at line 1184 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().
01185 { 01186 int accum; 01187 int x; 01188 int res = 0; 01189 01190 if (!len) { 01191 return 0; 01192 } 01193 accum = 0; 01194 for (x = 0; x < len; x++) { 01195 accum += abs(s[x]); 01196 } 01197 accum /= len; 01198 if (accum < dsp->threshold) { 01199 /* Silent */ 01200 dsp->totalsilence += len / 8; 01201 if (dsp->totalnoise) { 01202 /* Move and save history */ 01203 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0])); 01204 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01205 /* we don't want to check for busydetect that frequently */ 01206 #if 0 01207 dsp->busymaybe = 1; 01208 #endif 01209 } 01210 dsp->totalnoise = 0; 01211 res = 1; 01212 } else { 01213 /* Not silent */ 01214 dsp->totalnoise += len / 8; 01215 if (dsp->totalsilence) { 01216 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01217 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01218 /* Move and save history */ 01219 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0])); 01220 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01221 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01222 if (silence1 < silence2) { 01223 if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) { 01224 dsp->busymaybe = 1; 01225 } else { 01226 dsp->busymaybe = 0; 01227 } 01228 } else { 01229 if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) { 01230 dsp->busymaybe = 1; 01231 } else { 01232 dsp->busymaybe = 0; 01233 } 01234 } 01235 } 01236 dsp->totalsilence = 0; 01237 } 01238 if (totalsilence) { 01239 *totalsilence = dsp->totalsilence; 01240 } 01241 if (totalnoise) { 01242 *totalnoise = dsp->totalnoise; 01243 } 01244 return res; 01245 }
| static int _dsp_init | ( | int | reload | ) | [static] |
Definition at line 1748 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().
01749 { 01750 struct ast_config *cfg; 01751 struct ast_variable *v; 01752 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01753 int cfg_threshold; 01754 float cfg_twist; 01755 01756 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 01757 return 0; 01758 } 01759 01760 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01761 dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST; 01762 dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST; 01763 relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST; 01764 relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST; 01765 dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN; 01766 dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END; 01767 01768 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01769 return 0; 01770 } 01771 01772 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) { 01773 if (!strcasecmp(v->name, "silencethreshold")) { 01774 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01775 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01776 } else if (cfg_threshold < 0) { 01777 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold); 01778 } else { 01779 thresholds[THRESHOLD_SILENCE] = cfg_threshold; 01780 } 01781 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) { 01782 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01783 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01784 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01785 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist); 01786 } else { 01787 dtmf_normal_twist = cfg_twist; 01788 } 01789 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) { 01790 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01791 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01792 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01793 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist); 01794 } else { 01795 dtmf_reverse_twist = cfg_twist; 01796 } 01797 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) { 01798 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01799 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01800 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01801 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist); 01802 } else { 01803 relax_dtmf_normal_twist = cfg_twist; 01804 } 01805 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) { 01806 if (sscanf(v->value, "%30f", &cfg_twist) < 1) { 01807 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01808 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */ 01809 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist); 01810 } else { 01811 relax_dtmf_reverse_twist = cfg_twist; 01812 } 01813 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) { 01814 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01815 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01816 } else if (cfg_threshold < 1) { /* must be 1 or greater */ 01817 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin); 01818 } else { 01819 dtmf_hits_to_begin = cfg_threshold; 01820 } 01821 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) { 01822 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) { 01823 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value); 01824 } else if (cfg_threshold < 1) { /* must be 1 or greater */ 01825 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end); 01826 } else { 01827 dtmf_misses_to_end = cfg_threshold; 01828 } 01829 } 01830 } 01831 ast_config_destroy(cfg); 01832 01833 return 0; 01834 }
| static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
| int | mf | |||
| ) | [static] |
Definition at line 525 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().
00526 { 00527 s->current_digits = 0; 00528 s->detected_digits = 0; 00529 s->lost_digits = 0; 00530 s->digits[0] = '\0'; 00531 00532 if (mf) { 00533 ast_mf_detect_init(&s->td.mf); 00534 } else { 00535 ast_dtmf_detect_init(&s->td.dtmf); 00536 } 00537 }
| 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 1247 of file dsp.c.
References ast_debug, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, and MAX.
Referenced by ast_dsp_process().
01248 { 01249 int res = 0, x; 01250 #ifndef BUSYDETECT_TONEONLY 01251 int avgsilence = 0, hitsilence = 0; 01252 #endif 01253 int avgtone = 0, hittone = 0; 01254 if (!dsp->busymaybe) { 01255 return res; 01256 } 01257 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01258 #ifndef BUSYDETECT_TONEONLY 01259 avgsilence += dsp->historicsilence[x]; 01260 #endif 01261 avgtone += dsp->historicnoise[x]; 01262 } 01263 #ifndef BUSYDETECT_TONEONLY 01264 avgsilence /= dsp->busycount; 01265 #endif 01266 avgtone /= dsp->busycount; 01267 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01268 #ifndef BUSYDETECT_TONEONLY 01269 if (avgsilence > dsp->historicsilence[x]) { 01270 if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) { 01271 hitsilence++; 01272 } 01273 } else { 01274 if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) { 01275 hitsilence++; 01276 } 01277 } 01278 #endif 01279 if (avgtone > dsp->historicnoise[x]) { 01280 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) { 01281 hittone++; 01282 } 01283 } else { 01284 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) { 01285 hittone++; 01286 } 01287 } 01288 } 01289 #ifndef BUSYDETECT_TONEONLY 01290 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01291 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01292 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01293 #else 01294 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01295 #endif 01296 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01297 if (avgtone > avgsilence) { 01298 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) { 01299 res = 1; 01300 } 01301 } else { 01302 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) { 01303 res = 1; 01304 } 01305 } 01306 #else 01307 res = 1; 01308 #endif 01309 } 01310 /* If we know the expected busy tone length, check we are in the range */ 01311 if (res && (dsp->busy_tonelength > 0)) { 01312 if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*BUSY_PAT_PERCENT/100, 20)) { 01313 #ifdef BUSYDETECT_DEBUG 01314 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01315 avgtone, dsp->busy_tonelength); 01316 #endif 01317 res = 0; 01318 } 01319 } 01320 #ifndef BUSYDETECT_TONEONLY 01321 /* If we know the expected busy tone silent-period length, check we are in the range */ 01322 if (res && (dsp->busy_quietlength > 0)) { 01323 if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*BUSY_PAT_PERCENT/100, 20)) { 01324 #ifdef BUSYDETECT_DEBUG 01325 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01326 avgsilence, dsp->busy_quietlength); 01327 #endif 01328 res = 0; 01329 } 01330 } 01331 #endif 01332 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG) 01333 if (res) { 01334 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01335 } else { 01336 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01337 } 01338 #endif 01339 return res; 01340 }
Scans for progress indication in audio.
Definition at line 1171 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.
01172 { 01173 if (inf->frametype != AST_FRAME_VOICE) { 01174 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01175 return 0; 01176 } 01177 if (inf->subclass.codec != AST_FORMAT_SLINEAR) { 01178 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01179 return 0; 01180 } 01181 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); 01182 }
| void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1650 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().
01651 { 01652 int i; 01653 01654 dsp->dtmf_began = 0; 01655 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01656 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01657 /* Reinitialise the detector for the next block */ 01658 for (i = 0; i < 6; i++) { 01659 goertzel_reset(&s->tone_out[i]); 01660 } 01661 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01662 s->current_sample = 0; 01663 } else { 01664 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01665 /* Reinitialise the detector for the next block */ 01666 for (i = 0; i < 4; i++) { 01667 goertzel_reset(&s->row_out[i]); 01668 goertzel_reset(&s->col_out[i]); 01669 } 01670 s->lasthit = s->current_hit = 0; 01671 s->energy = 0.0; 01672 s->current_sample = 0; 01673 s->hits = 0; 01674 s->misses = 0; 01675 } 01676 01677 dsp->digit_state.digits[0] = '\0'; 01678 dsp->digit_state.current_digits = 0; 01679 }
| void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1622 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().
01623 { 01624 ast_free(dsp); 01625 }
| int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1743 of file dsp.c.
References ast_dsp::tcount.
Referenced by dahdi_read().
01744 { 01745 return dsp->tcount; 01746 }
| int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1836 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().
01837 { 01838 return thresholds[which]; 01839 }
| int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1738 of file dsp.c.
References ast_dsp::tstate.
Referenced by dahdi_read().
01739 { 01740 return dsp->tstate; 01741 }
| int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1841 of file dsp.c.
References _dsp_init().
Referenced by main().
01842 { 01843 return _dsp_init(0); 01844 }
| struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1593 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, 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().
01594 { 01595 struct ast_dsp *dsp; 01596 01597 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01598 dsp->threshold = DEFAULT_THRESHOLD; 01599 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01600 dsp->busycount = DSP_HISTORY; 01601 dsp->digitmode = DSP_DIGITMODE_DTMF; 01602 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01603 /* Initialize digit detector */ 01604 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01605 dsp->display_inband_dtmf_warning = 1; 01606 /* Initialize initial DSP progress detect parameters */ 01607 ast_dsp_prog_reset(dsp); 01608 /* Initialize fax detector */ 01609 ast_fax_detect_init(dsp); 01610 } 01611 return dsp; 01612 }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1360 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().
01361 { 01362 short *s; 01363 int len; 01364 01365 if (f->frametype != AST_FRAME_VOICE) { 01366 ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); 01367 return 0; 01368 } 01369 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01370 ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); 01371 return 0; 01372 } 01373 s = f->data.ptr; 01374 len = f->datalen/2; 01375 return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); 01376 }
| 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 1379 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().
01380 { 01381 int silence; 01382 int res; 01383 int digit = 0, fax_digit = 0; 01384 int x; 01385 short *shortdata; 01386 unsigned char *odata; 01387 int len; 01388 struct ast_frame *outf = NULL; 01389 01390 if (!af) { 01391 return NULL; 01392 } 01393 if (af->frametype != AST_FRAME_VOICE) { 01394 return af; 01395 } 01396 01397 odata = af->data.ptr; 01398 len = af->datalen; 01399 /* Make sure we have short data */ 01400 switch (af->subclass.codec) { 01401 case AST_FORMAT_SLINEAR: 01402 shortdata = af->data.ptr; 01403 len = af->datalen / 2; 01404 break; 01405 case AST_FORMAT_ULAW: 01406 case AST_FORMAT_TESTLAW: 01407 shortdata = ast_alloca(af->datalen * 2); 01408 for (x = 0;x < len; x++) { 01409 shortdata[x] = AST_MULAW(odata[x]); 01410 } 01411 break; 01412 case AST_FORMAT_ALAW: 01413 shortdata = ast_alloca(af->datalen * 2); 01414 for (x = 0; x < len; x++) { 01415 shortdata[x] = AST_ALAW(odata[x]); 01416 } 01417 break; 01418 default: 01419 /*Display warning only once. Otherwise you would get hundreds of warnings every second */ 01420 if (dsp->display_inband_dtmf_warning) 01421 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec)); 01422 dsp->display_inband_dtmf_warning = 0; 01423 return af; 01424 } 01425 01426 /* Initially we do not want to mute anything */ 01427 dsp->mute_fragments = 0; 01428 01429 /* Need to run the silence detection stuff for silence suppression and busy detection */ 01430 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { 01431 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); 01432 } 01433 01434 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01435 memset(&dsp->f, 0, sizeof(dsp->f)); 01436 dsp->f.frametype = AST_FRAME_NULL; 01437 ast_frfree(af); 01438 return ast_frisolate(&dsp->f); 01439 } 01440 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01441 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01442 memset(&dsp->f, 0, sizeof(dsp->f)); 01443 dsp->f.frametype = AST_FRAME_CONTROL; 01444 dsp->f.subclass.integer = AST_CONTROL_BUSY; 01445 ast_frfree(af); 01446 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01447 return ast_frisolate(&dsp->f); 01448 } 01449 01450 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { 01451 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { 01452 fax_digit = 'f'; 01453 } 01454 01455 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { 01456 fax_digit = 'e'; 01457 } 01458 } 01459 01460 if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { 01461 if (dsp->digitmode & DSP_DIGITMODE_MF) 01462 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01463 else 01464 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01465 01466 if (dsp->digit_state.current_digits) { 01467 int event = 0, event_len = 0; 01468 char event_digit = 0; 01469 01470 if (!dsp->dtmf_began) { 01471 /* We have not reported DTMF_BEGIN for anything yet */ 01472 01473 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01474 event = AST_FRAME_DTMF_BEGIN; 01475 event_digit = dsp->digit_state.digits[0]; 01476 } 01477 dsp->dtmf_began = 1; 01478 01479 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { 01480 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ 01481 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01482 event = AST_FRAME_DTMF_END; 01483 event_digit = dsp->digit_state.digits[0]; 01484 event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; 01485 } 01486 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); 01487 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0])); 01488 dsp->digit_state.current_digits--; 01489 dsp->dtmf_began = 0; 01490 01491 if (dsp->features & DSP_FEATURE_BUSY_DETECT) { 01492 /* Reset Busy Detector as we have some confirmed activity */ 01493 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01494 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01495 ast_debug(1, "DTMF Detected - Reset busydetector\n"); 01496 } 01497 } 01498 01499 if (event) { 01500 memset(&dsp->f, 0, sizeof(dsp->f)); 01501 dsp->f.frametype = event; 01502 dsp->f.subclass.integer = event_digit; 01503 dsp->f.len = event_len; 01504 outf = &dsp->f; 01505 goto done; 01506 } 01507 } 01508 } 01509 01510 if (fax_digit) { 01511 /* Fax was detected - digit is either 'f' or 'e' */ 01512 01513 memset(&dsp->f, 0, sizeof(dsp->f)); 01514 dsp->f.frametype = AST_FRAME_DTMF; 01515 dsp->f.subclass.integer = fax_digit; 01516 outf = &dsp->f; 01517 goto done; 01518 } 01519 01520 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01521 res = __ast_dsp_call_progress(dsp, shortdata, len); 01522 if (res) { 01523 switch (res) { 01524 case AST_CONTROL_ANSWER: 01525 case AST_CONTROL_BUSY: 01526 case AST_CONTROL_RINGING: 01527 case AST_CONTROL_CONGESTION: 01528 case AST_CONTROL_HANGUP: 01529 memset(&dsp->f, 0, sizeof(dsp->f)); 01530 dsp->f.frametype = AST_FRAME_CONTROL; 01531 dsp->f.subclass.integer = res; 01532 dsp->f.src = "dsp_progress"; 01533 if (chan) 01534 ast_queue_frame(chan, &dsp->f); 01535 break; 01536 default: 01537 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01538 } 01539 } 01540 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { 01541 res = __ast_dsp_call_progress(dsp, shortdata, len); 01542 } 01543 01544 done: 01545 /* Mute fragment of the frame */ 01546 for (x = 0; x < dsp->mute_fragments; x++) { 01547 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); 01548 } 01549 01550 switch (af->subclass.codec) { 01551 case AST_FORMAT_SLINEAR: 01552 break; 01553 case AST_FORMAT_ULAW: 01554 for (x = 0; x < len; x++) { 01555 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); 01556 } 01557 break; 01558 case AST_FORMAT_ALAW: 01559 for (x = 0; x < len; x++) { 01560 odata[x] = AST_LIN2A((unsigned short) shortdata[x]); 01561 } 01562 break; 01563 } 01564 01565 if (outf) { 01566 if (chan) { 01567 ast_queue_frame(chan, af); 01568 } 01569 ast_frfree(af); 01570 return ast_frisolate(outf); 01571 } else { 01572 return af; 01573 } 01574 }
| static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1576 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().
01577 { 01578 int max = 0; 01579 int x; 01580 01581 dsp->gsamp_size = modes[dsp->progmode].size; 01582 dsp->gsamps = 0; 01583 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01584 if (modes[dsp->progmode].freqs[x]) { 01585 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01586 max = x + 1; 01587 } 01588 } 01589 dsp->freqcount = max; 01590 dsp->ringtimeout= 0; 01591 }
| int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1846 of file dsp.c.
References _dsp_init().
01847 { 01848 return _dsp_init(1); 01849 }
| void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1681 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().
01682 { 01683 int x; 01684 01685 dsp->totalsilence = 0; 01686 dsp->gsamps = 0; 01687 for (x = 0; x < 4; x++) { 01688 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01689 } 01690 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01691 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01692 dsp->ringtimeout= 0; 01693 }
| void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
| int | cadences | |||
| ) |
Set number of required cadences for busy.
Definition at line 1632 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01633 { 01634 if (cadences < 4) { 01635 cadences = 4; 01636 } 01637 if (cadences > DSP_HISTORY) { 01638 cadences = DSP_HISTORY; 01639 } 01640 dsp->busycount = cadences; 01641 }
| void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
| int | tonelength, | |||
| int | quietlength | |||
| ) |
Set expected lengths of the busy tone.
Definition at line 1643 of file dsp.c.
References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.
Referenced by dahdi_new().
01644 { 01645 dsp->busy_tonelength = tonelength; 01646 dsp->busy_quietlength = quietlength; 01647 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01648 }
| int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
| char * | zone | |||
| ) |
Set zone for doing progress detection.
Definition at line 1719 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 1695 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().
01696 { 01697 int new; 01698 int old; 01699 01700 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01701 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01702 if (old != new) { 01703 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01704 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01705 } 01706 dsp->digitmode = digitmode; 01707 return 0; 01708 }
| int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
| int | faxmode | |||
| ) |
Set fax mode.
Definition at line 1710 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01711 { 01712 if (dsp->faxmode != faxmode) { 01713 ast_fax_detect_init(dsp); 01714 } 01715 dsp->faxmode = faxmode; 01716 return 0; 01717 }
| void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
| int | features | |||
| ) |
Select feature set.
Definition at line 1614 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().
01615 { 01616 dsp->features = features; 01617 if (!(features & DSP_FEATURE_DIGIT_DETECT)) { 01618 dsp->display_inband_dtmf_warning = 0; 01619 } 01620 }
| void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
| int | threshold | |||
| ) |
Set threshold value for silence.
Definition at line 1627 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), 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 1342 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().
01343 { 01344 short *s; 01345 int len; 01346 01347 if (f->frametype != AST_FRAME_VOICE) { 01348 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01349 return 0; 01350 } 01351 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01352 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01353 return 0; 01354 } 01355 s = f->data.ptr; 01356 len = f->datalen/2; 01357 return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); 01358 }
| 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 1733 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
01734 { 01735 return (dsp->mute_fragments > 0); 01736 }
| static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 498 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().
00499 { 00500 int i; 00501 00502 s->lasthit = 0; 00503 s->current_hit = 0; 00504 for (i = 0; i < 4; i++) { 00505 goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE); 00506 goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE); 00507 s->energy = 0.0; 00508 } 00509 s->current_sample = 0; 00510 s->hits = 0; 00511 s->misses = 0; 00512 }
| static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 492 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().
00493 { 00494 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00495 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00496 }
| static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 514 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().
00515 { 00516 int i; 00517 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00518 for (i = 0; i < 6; i++) { 00519 goertzel_init (&s->tone_out[i], mf_tones[i], MF_GSIZE); 00520 } 00521 s->current_sample = 0; 00522 s->current_hit = 0; 00523 }
| static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
| int | freq, | |||
| int | duration, | |||
| int | amp | |||
| ) | [static] |
Definition at line 432 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().
00433 { 00434 int duration_samples; 00435 float x; 00436 int periods_in_block; 00437 00438 s->freq = freq; 00439 00440 /* Desired tone duration in samples */ 00441 duration_samples = duration * SAMPLE_RATE / 1000; 00442 /* We want to allow 10% deviation of tone duration */ 00443 duration_samples = duration_samples * 9 / 10; 00444 00445 /* If we want to remove tone, it is important to have block size not 00446 to exceed frame size. Otherwise by the moment tone is detected it is too late 00447 to squelch it from previous frames */ 00448 s->block_size = SAMPLES_IN_FRAME; 00449 00450 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00451 00452 /* Make sure we will have at least 5 periods at target frequency for analisys. 00453 This may make block larger than expected packet and will make squelching impossible 00454 but at least we will be detecting the tone */ 00455 if (periods_in_block < 5) 00456 periods_in_block = 5; 00457 00458 /* Now calculate final block size. It will contain integer number of periods */ 00459 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00460 00461 /* tone_detect is currently only used to detect fax tones and we 00462 do not need squelching the fax tones */ 00463 s->squelch = 0; 00464 00465 /* Account for the first and the last block to be incomplete 00466 and thus no tone will be detected in them */ 00467 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00468 00469 goertzel_init(&s->tone, freq, s->block_size); 00470 00471 s->samples_pending = s->block_size; 00472 s->hit_count = 0; 00473 s->last_hit = 0; 00474 s->energy = 0.0; 00475 00476 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00477 According to Parseval's theorem the energy computed in time domain equals to energy 00478 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00479 from the energy in the time domain we will get energy of the remaining signal (without the tone 00480 we are detecting). We will be checking that 00481 10*log(Ew / (Et - Ew)) > amp 00482 Calculate threshold so that we will be actually checking 00483 Ew > Et * threshold 00484 */ 00485 00486 x = pow(10.0, amp / 10.0); 00487 s->threshold = x / (x + 1); 00488 00489 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00490 }
| 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 658 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().
00659 { 00660 float row_energy[4]; 00661 float col_energy[4]; 00662 int i; 00663 int j; 00664 int sample; 00665 short samp; 00666 int best_row; 00667 int best_col; 00668 int hit; 00669 int limit; 00670 fragment_t mute = {0, 0}; 00671 00672 if (squelch && s->td.dtmf.mute_samples > 0) { 00673 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples; 00674 s->td.dtmf.mute_samples -= mute.end; 00675 } 00676 00677 hit = 0; 00678 for (sample = 0; sample < samples; sample = limit) { 00679 /* DTMF_GSIZE is optimised to meet the DTMF specs. */ 00680 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) { 00681 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample); 00682 } else { 00683 limit = samples; 00684 } 00685 /* The following unrolled loop takes only 35% (rough estimate) of the 00686 time of a rolled loop on the machine on which it was developed */ 00687 for (j = sample; j < limit; j++) { 00688 samp = amp[j]; 00689 s->td.dtmf.energy += (int32_t) samp * (int32_t) samp; 00690 /* With GCC 2.95, the following unrolled code seems to take about 35% 00691 (rough estimate) as long as a neat little 0-3 loop */ 00692 goertzel_sample(s->td.dtmf.row_out, samp); 00693 goertzel_sample(s->td.dtmf.col_out, samp); 00694 goertzel_sample(s->td.dtmf.row_out + 1, samp); 00695 goertzel_sample(s->td.dtmf.col_out + 1, samp); 00696 goertzel_sample(s->td.dtmf.row_out + 2, samp); 00697 goertzel_sample(s->td.dtmf.col_out + 2, samp); 00698 goertzel_sample(s->td.dtmf.row_out + 3, samp); 00699 goertzel_sample(s->td.dtmf.col_out + 3, samp); 00700 } 00701 s->td.dtmf.current_sample += (limit - sample); 00702 if (s->td.dtmf.current_sample < DTMF_GSIZE) { 00703 continue; 00704 } 00705 /* We are at the end of a DTMF detection block */ 00706 /* Find the peak row and the peak column */ 00707 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00708 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00709 00710 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00711 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00712 if (row_energy[i] > row_energy[best_row]) { 00713 best_row = i; 00714 } 00715 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00716 if (col_energy[i] > col_energy[best_col]) { 00717 best_col = i; 00718 } 00719 } 00720 hit = 0; 00721 /* Basic signal level test and the twist test */ 00722 if (row_energy[best_row] >= DTMF_THRESHOLD && 00723 col_energy[best_col] >= DTMF_THRESHOLD && 00724 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) && 00725 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) { 00726 /* Relative peak test */ 00727 for (i = 0; i < 4; i++) { 00728 if ((i != best_col && 00729 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00730 (i != best_row 00731 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00732 break; 00733 } 00734 } 00735 /* ... and fraction of total energy test */ 00736 if (i >= 4 && 00737 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) { 00738 /* Got a hit */ 00739 hit = dtmf_positions[(best_row << 2) + best_col]; 00740 } 00741 } 00742 00743 /* 00744 * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03) 00745 * (40ms reference is tunable with hits_to_begin and misses_to_end) 00746 * each hit/miss is 12.75ms with DTMF_GSIZE at 102 00747 * 00748 * Character recognition: When not DRC *(1) and then 00749 * Shall exist VSC > 40 ms (hits_to_begin) 00750 * May exist 20 ms <= VSC <= 40 ms 00751 * Shall not exist VSC < 20 ms 00752 * 00753 * Character recognition: When DRC and then 00754 * Shall cease Not VSC > 40 ms (misses_to_end) 00755 * May cease 20 ms >= Not VSC >= 40 ms 00756 * Shall not cease Not VSC < 20 ms 00757 * 00758 * *(1) or optionally a different digit recognition condition 00759 * 00760 * Legend: VSC The continuous existence of a valid signal condition. 00761 * Not VSC The continuous non-existence of valid signal condition. 00762 * DRC The existence of digit recognition condition. 00763 * Not DRC The non-existence of digit recognition condition. 00764 */ 00765 00766 /* 00767 * Example: hits_to_begin=2 misses_to_end=3 00768 * -------A last_hit=A hits=0&1 00769 * ------AA hits=2 current_hit=A misses=0 BEGIN A 00770 * -----AA- misses=1 last_hit=' ' hits=0 00771 * ----AA-- misses=2 00772 * ---AA--- misses=3 current_hit=' ' END A 00773 * --AA---B last_hit=B hits=0&1 00774 * -AA---BC last_hit=C hits=0&1 00775 * AA---BCC hits=2 current_hit=C misses=0 BEGIN C 00776 * A---BCC- misses=1 last_hit=' ' hits=0 00777 * ---BCC-C misses=0 last_hit=C hits=0&1 00778 * --BCC-CC misses=0 00779 * 00780 * Example: hits_to_begin=3 misses_to_end=2 00781 * -------A last_hit=A hits=0&1 00782 * ------AA hits=2 00783 * -----AAA hits=3 current_hit=A misses=0 BEGIN A 00784 * ----AAAB misses=1 last_hit=B hits=0&1 00785 * ---AAABB misses=2 current_hit=' ' hits=2 END A 00786 * --AAABBB hits=3 current_hit=B misses=0 BEGIN B 00787 * -AAABBBB misses=0 00788 * 00789 * Example: hits_to_begin=2 misses_to_end=2 00790 * -------A last_hit=A hits=0&1 00791 * ------AA hits=2 current_hit=A misses=0 BEGIN A 00792 * -----AAB misses=1 hits=0&1 00793 * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B 00794 * ---AABBB misses=0 00795 */ 00796 00797 if (s->td.dtmf.current_hit) { 00798 /* We are in the middle of a digit already */ 00799 if (hit != s->td.dtmf.current_hit) { 00800 s->td.dtmf.misses++; 00801 if (s->td.dtmf.misses == dtmf_misses_to_end) { 00802 /* There were enough misses to consider digit ended */ 00803 s->td.dtmf.current_hit = 0; 00804 } 00805 } else { 00806 s->td.dtmf.misses = 0; 00807 /* Current hit was same as last, so increment digit duration (of last digit) */ 00808 s->digitlen[s->current_digits - 1] += DTMF_GSIZE; 00809 } 00810 } 00811 00812 /* Look for a start of a new digit no matter if we are already in the middle of some 00813 digit or not. This is because hits_to_begin may be smaller than misses_to_end 00814 and we may find begin of new digit before we consider last one ended. */ 00815 00816 if (hit != s->td.dtmf.lasthit) { 00817 s->td.dtmf.lasthit = hit; 00818 s->td.dtmf.hits = 0; 00819 } 00820 if (hit && hit != s->td.dtmf.current_hit) { 00821 s->td.dtmf.hits++; 00822 if (s->td.dtmf.hits == dtmf_hits_to_begin) { 00823 store_digit(s, hit); 00824 s->digitlen[s->current_digits - 1] = dtmf_hits_to_begin * DTMF_GSIZE; 00825 s->td.dtmf.current_hit = hit; 00826 s->td.dtmf.misses = 0; 00827 } 00828 } 00829 00830 /* If we had a hit in this block, include it into mute fragment */ 00831 if (squelch && hit) { 00832 if (mute.end < sample - DTMF_GSIZE) { 00833 /* There is a gap between fragments */ 00834 mute_fragment(dsp, &mute); 00835 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0; 00836 } 00837 mute.end = limit + DTMF_GSIZE; 00838 } 00839 00840 /* Reinitialise the detector for the next block */ 00841 for (i = 0; i < 4; i++) { 00842 goertzel_reset(&s->td.dtmf.row_out[i]); 00843 goertzel_reset(&s->td.dtmf.col_out[i]); 00844 } 00845 s->td.dtmf.energy = 0.0; 00846 s->td.dtmf.current_sample = 0; 00847 } 00848 00849 if (squelch && mute.end) { 00850 if (mute.end > samples) { 00851 s->td.dtmf.mute_samples = mute.end - samples; 00852 mute.end = samples; 00853 } 00854 mute_fragment(dsp, &mute); 00855 } 00856 00857 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00858 }
| 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 860 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().
00862 { 00863 float energy[6]; 00864 int best; 00865 int second_best; 00866 int i; 00867 int j; 00868 int sample; 00869 short samp; 00870 int hit; 00871 int limit; 00872 fragment_t mute = {0, 0}; 00873 00874 if (squelch && s->td.mf.mute_samples > 0) { 00875 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples; 00876 s->td.mf.mute_samples -= mute.end; 00877 } 00878 00879 hit = 0; 00880 for (sample = 0; sample < samples; sample = limit) { 00881 /* 80 is optimised to meet the MF specs. */ 00882 /* XXX So then why is MF_GSIZE defined as 120? */ 00883 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) { 00884 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00885 } else { 00886 limit = samples; 00887 } 00888 /* The following unrolled loop takes only 35% (rough estimate) of the 00889 time of a rolled loop on the machine on which it was developed */ 00890 for (j = sample; j < limit; j++) { 00891 /* With GCC 2.95, the following unrolled code seems to take about 35% 00892 (rough estimate) as long as a neat little 0-3 loop */ 00893 samp = amp[j]; 00894 goertzel_sample(s->td.mf.tone_out, samp); 00895 goertzel_sample(s->td.mf.tone_out + 1, samp); 00896 goertzel_sample(s->td.mf.tone_out + 2, samp); 00897 goertzel_sample(s->td.mf.tone_out + 3, samp); 00898 goertzel_sample(s->td.mf.tone_out + 4, samp); 00899 goertzel_sample(s->td.mf.tone_out + 5, samp); 00900 } 00901 s->td.mf.current_sample += (limit - sample); 00902 if (s->td.mf.current_sample < MF_GSIZE) { 00903 continue; 00904 } 00905 /* We're at the end of an MF detection block. */ 00906 /* Find the two highest energies. The spec says to look for 00907 two tones and two tones only. Taking this literally -ie 00908 only two tones pass the minimum threshold - doesn't work 00909 well. The sinc function mess, due to rectangular windowing 00910 ensure that! Find the two highest energies and ensure they 00911 are considerably stronger than any of the others. */ 00912 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00913 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00914 if (energy[0] > energy[1]) { 00915 best = 0; 00916 second_best = 1; 00917 } else { 00918 best = 1; 00919 second_best = 0; 00920 } 00921 /*endif*/ 00922 for (i = 2; i < 6; i++) { 00923 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00924 if (energy[i] >= energy[best]) { 00925 second_best = best; 00926 best = i; 00927 } else if (energy[i] >= energy[second_best]) { 00928 second_best = i; 00929 } 00930 } 00931 /* Basic signal level and twist tests */ 00932 hit = 0; 00933 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00934 && energy[best] < energy[second_best]*BELL_MF_TWIST 00935 && energy[best] * BELL_MF_TWIST > energy[second_best]) { 00936 /* Relative peak test */ 00937 hit = -1; 00938 for (i = 0; i < 6; i++) { 00939 if (i != best && i != second_best) { 00940 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00941 /* The best two are not clearly the best */ 00942 hit = 0; 00943 break; 00944 } 00945 } 00946 } 00947 } 00948 if (hit) { 00949 /* Get the values into ascending order */ 00950 if (second_best < best) { 00951 i = best; 00952 best = second_best; 00953 second_best = i; 00954 } 00955 best = best * 5 + second_best - 1; 00956 hit = bell_mf_positions[best]; 00957 /* Look for two successive similar results */ 00958 /* The logic in the next test is: 00959 For KP we need 4 successive identical clean detects, with 00960 two blocks of something different preceeding it. For anything 00961 else we need two successive identical clean detects, with 00962 two blocks of something different preceeding it. */ 00963 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00964 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00965 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00966 hit != s->td.mf.hits[0]))) { 00967 store_digit(s, hit); 00968 } 00969 } 00970 00971 00972 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00973 /* Two successive block without a hit terminate current digit */ 00974 s->td.mf.current_hit = 0; 00975 } 00976 00977 s->td.mf.hits[0] = s->td.mf.hits[1]; 00978 s->td.mf.hits[1] = s->td.mf.hits[2]; 00979 s->td.mf.hits[2] = s->td.mf.hits[3]; 00980 s->td.mf.hits[3] = s->td.mf.hits[4]; 00981 s->td.mf.hits[4] = hit; 00982 00983 /* If we had a hit in this block, include it into mute fragment */ 00984 if (squelch && hit) { 00985 if (mute.end < sample - MF_GSIZE) { 00986 /* There is a gap between fragments */ 00987 mute_fragment(dsp, &mute); 00988 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0; 00989 } 00990 mute.end = limit + MF_GSIZE; 00991 } 00992 00993 /* Reinitialise the detector for the next block */ 00994 for (i = 0; i < 6; i++) 00995 goertzel_reset(&s->td.mf.tone_out[i]); 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 422 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().
00423 { 00424 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) { 00425 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n"); 00426 return; 00427 } 00428 00429 dsp->mute_data[dsp->mute_fragments++] = *fragment; 00430 }
| 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 645 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().
00646 { 00647 s->detected_digits++; 00648 if (s->current_digits < MAX_DTMF_DIGITS) { 00649 s->digitlen[s->current_digits] = 0; 00650 s->digits[s->current_digits++] = digit; 00651 s->digits[s->current_digits] = '\0'; 00652 } else { 00653 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00654 s->lost_digits++; 00655 } 00656 }
| static int tone_detect | ( | struct ast_dsp * | dsp, | |
| tone_detect_state_t * | s, | |||
| int16_t * | amp, | |||
| int | samples | |||
| ) | [static] |
Definition at line 539 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().
00540 { 00541 float tone_energy; 00542 int i; 00543 int hit = 0; 00544 int limit; 00545 int res = 0; 00546 int16_t *ptr; 00547 short samp; 00548 int start, end; 00549 fragment_t mute = {0, 0}; 00550 00551 if (s->squelch && s->mute_samples > 0) { 00552 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples; 00553 s->mute_samples -= mute.end; 00554 } 00555 00556 for (start = 0; start < samples; start = end) { 00557 /* Process in blocks. */ 00558 limit = samples - start; 00559 if (limit > s->samples_pending) { 00560 limit = s->samples_pending; 00561 } 00562 end = start + limit; 00563 00564 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00565 samp = *ptr; 00566 /* signed 32 bit int should be enough to square any possible signed 16 bit value */ 00567 s->energy += (int32_t) samp * (int32_t) samp; 00568 00569 goertzel_sample(&s->tone, samp); 00570 } 00571 00572 s->samples_pending -= limit; 00573 00574 if (s->samples_pending) { 00575 /* Finished incomplete (last) block */ 00576 break; 00577 } 00578 00579 tone_energy = goertzel_result(&s->tone); 00580 00581 /* Scale to make comparable */ 00582 tone_energy *= 2.0; 00583 s->energy *= s->block_size; 00584 00585 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)); 00586 hit = 0; 00587 if (tone_energy > s->energy * s->threshold) { 00588 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00589 hit = 1; 00590 } 00591 00592 if (s->hit_count) { 00593 s->hit_count++; 00594 } 00595 00596 if (hit == s->last_hit) { 00597 if (!hit) { 00598 /* Two successive misses. Tone ended */ 00599 s->hit_count = 0; 00600 } else if (!s->hit_count) { 00601 s->hit_count++; 00602 } 00603 00604 } 00605 00606 if (s->hit_count == s->hits_required) { 00607 ast_debug(1, "%d Hz done detected\n", s->freq); 00608 res = 1; 00609 } 00610 00611 s->last_hit = hit; 00612 00613 /* If we had a hit in this block, include it into mute fragment */ 00614 if (s->squelch && hit) { 00615 if (mute.end < start - s->block_size) { 00616 /* There is a gap between fragments */ 00617 mute_fragment(dsp, &mute); 00618 mute.start = (start > s->block_size) ? (start - s->block_size) : 0; 00619 } 00620 mute.end = end + s->block_size; 00621 } 00622 00623 /* Reinitialise the detector for the next block */ 00624 /* Reset for the next block */ 00625 goertzel_reset(&s->tone); 00626 00627 /* Advance to the next block */ 00628 s->energy = 0.0; 00629 s->samples_pending = s->block_size; 00630 00631 amp += limit; 00632 } 00633 00634 if (s->squelch && mute.end) { 00635 if (mute.end > samples) { 00636 s->mute_samples = mute.end - samples; 00637 mute.end = samples; 00638 } 00639 mute_fragment(dsp, &mute); 00640 } 00641 00642 return res; 00643 }
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] |
1.6.1