#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 | DEFAULT_THRESHOLD 512 |
This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767. | |
#define | DSP_HISTORY 15 |
#define | DTMF_2ND_HARMONIC_COL 63.1 |
#define | DTMF_2ND_HARMONIC_ROW (relax ? 1.7 : 2.5) |
#define | DTMF_GSIZE 102 |
#define | DTMF_HITS_TO_BEGIN 4 |
#define | DTMF_MISSES_TO_END 4 |
#define | DTMF_NORMAL_TWIST 6.3 |
#define | DTMF_RELATIVE_PEAK_COL 6.3 |
#define | DTMF_RELATIVE_PEAK_ROW 6.3 |
#define | DTMF_REVERSE_TWIST (relax ? 4.0 : 2.5) |
#define | DTMF_THRESHOLD 8.0e7 |
#define | DTMF_TO_TOTAL_ENERGY 42.0 |
#define | FAX_2ND_HARMONIC 2.0 |
#define | FAX_THRESHOLD 8.0e7 |
#define | FAX_TONE_CED_DB 16 |
#define | FAX_TONE_CED_DURATION 2600 |
#define | FAX_TONE_CED_FREQ 2100 |
#define | FAX_TONE_CNG_DB 16 |
#define | FAX_TONE_CNG_DURATION 500 |
#define | FAX_TONE_CNG_FREQ 1100 |
#define | MAX_DTMF_DIGITS 128 |
#define | MF_GSIZE 120 |
#define | SAMPLE_RATE 8000 |
#define | SAMPLES_IN_FRAME 160 |
#define | TONE_MIN_THRESH 1e8 |
#define | TONE_THRESH 10.0 |
Enumerations | |
enum | busy_detect { BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 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. | |
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. | |
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 const char | dtmf_positions [] = "123A" "456B" "789C" "*0#D" |
static const float | dtmf_row [] |
static const float | mf_tones [] |
static struct progress | modes [] |
static int | thresholds [THRESHOLD_MAX] |
Steve Underwood <steveu@coppice.org>
Definition in file dsp.c.
#define DEFAULT_THRESHOLD 512 |
This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
Definition at line 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 |
#define DTMF_HITS_TO_BEGIN 4 |
#define DTMF_MISSES_TO_END 4 |
#define DTMF_NORMAL_TWIST 6.3 |
#define DTMF_RELATIVE_PEAK_COL 6.3 |
#define DTMF_RELATIVE_PEAK_ROW 6.3 |
#define DTMF_REVERSE_TWIST (relax ? 4.0 : 2.5) |
#define DTMF_THRESHOLD 8.0e7 |
#define DTMF_TO_TOTAL_ENERGY 42.0 |
#define FAX_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 SAMPLES_IN_FRAME 160 |
#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 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 pair_there().
enum busy_detect |
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 |
HZ_350 | For US modes { |
HZ_440 | |
HZ_480 | |
HZ_620 | |
HZ_950 | |
HZ_1400 | |
HZ_1800 | } |
HZ_425 | For CR/BR modes |
HZ_350UK | For UK mode |
HZ_400UK | |
HZ_440UK |
Definition at line 75 of file dsp.c.
00075 { 00076 /*! For US modes { */ 00077 HZ_350 = 0, 00078 HZ_440, 00079 HZ_480, 00080 HZ_620, 00081 HZ_950, 00082 HZ_1400, 00083 HZ_1800, /*!< } */ 00084 00085 /*! For CR/BR modes */ 00086 HZ_425 = 0, 00087 00088 /*! For UK mode */ 00089 HZ_350UK = 0, 00090 HZ_400UK, 00091 HZ_440UK 00092 };
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 969 of file dsp.c.
References DSP_TONE_STATE_BUSY, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_350, HZ_440, HZ_480, HZ_620, pair_there(), pass, PROG_MODE_NA, and ast_dsp::progmode.
Referenced by ast_dsp_call_progress().
00970 { 00971 int x; 00972 int y; 00973 int pass; 00974 int newstate = DSP_TONE_STATE_SILENCE; 00975 int res = 0; 00976 while (len) { 00977 /* Take the lesser of the number of samples we need and what we have */ 00978 pass = len; 00979 if (pass > dsp->gsamp_size - dsp->gsamps) { 00980 pass = dsp->gsamp_size - dsp->gsamps; 00981 } 00982 for (x = 0; x < pass; x++) { 00983 for (y = 0; y < dsp->freqcount; y++) { 00984 goertzel_sample(&dsp->freqs[y], s[x]); 00985 } 00986 dsp->genergy += s[x] * s[x]; 00987 } 00988 s += pass; 00989 dsp->gsamps += pass; 00990 len -= pass; 00991 if (dsp->gsamps == dsp->gsamp_size) { 00992 float hz[7]; 00993 for (y = 0; y < 7; y++) { 00994 hz[y] = goertzel_result(&dsp->freqs[y]); 00995 } 00996 switch (dsp->progmode) { 00997 case PROG_MODE_NA: 00998 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 00999 newstate = DSP_TONE_STATE_BUSY; 01000 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01001 newstate = DSP_TONE_STATE_RINGING; 01002 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01003 newstate = DSP_TONE_STATE_DIALTONE; 01004 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01005 newstate = DSP_TONE_STATE_SPECIAL1; 01006 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01007 /* End of SPECIAL1 or middle of SPECIAL2 */ 01008 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) { 01009 newstate = DSP_TONE_STATE_SPECIAL2; 01010 } 01011 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01012 /* End of SPECIAL2 or middle of SPECIAL3 */ 01013 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01014 newstate = DSP_TONE_STATE_SPECIAL3; 01015 } 01016 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01017 newstate = DSP_TONE_STATE_TALKING; 01018 } else { 01019 newstate = DSP_TONE_STATE_SILENCE; 01020 } 01021 break; 01022 case PROG_MODE_CR: 01023 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01024 newstate = DSP_TONE_STATE_RINGING; 01025 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01026 newstate = DSP_TONE_STATE_TALKING; 01027 } else { 01028 newstate = DSP_TONE_STATE_SILENCE; 01029 } 01030 break; 01031 case PROG_MODE_UK: 01032 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { 01033 newstate = DSP_TONE_STATE_HUNGUP; 01034 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { 01035 newstate = DSP_TONE_STATE_DIALTONE; 01036 } 01037 break; 01038 default: 01039 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01040 } 01041 if (newstate == dsp->tstate) { 01042 dsp->tcount++; 01043 if (dsp->ringtimeout) { 01044 dsp->ringtimeout++; 01045 } 01046 switch (dsp->tstate) { 01047 case DSP_TONE_STATE_RINGING: 01048 if ((dsp->features & DSP_PROGRESS_RINGING) && 01049 (dsp->tcount == THRESH_RING)) { 01050 res = AST_CONTROL_RINGING; 01051 dsp->ringtimeout = 1; 01052 } 01053 break; 01054 case DSP_TONE_STATE_BUSY: 01055 if ((dsp->features & DSP_PROGRESS_BUSY) && 01056 (dsp->tcount == THRESH_BUSY)) { 01057 res = AST_CONTROL_BUSY; 01058 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01059 } 01060 break; 01061 case DSP_TONE_STATE_TALKING: 01062 if ((dsp->features & DSP_PROGRESS_TALK) && 01063 (dsp->tcount == THRESH_TALK)) { 01064 res = AST_CONTROL_ANSWER; 01065 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01066 } 01067 break; 01068 case DSP_TONE_STATE_SPECIAL3: 01069 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01070 (dsp->tcount == THRESH_CONGESTION)) { 01071 res = AST_CONTROL_CONGESTION; 01072 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01073 } 01074 break; 01075 case DSP_TONE_STATE_HUNGUP: 01076 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01077 (dsp->tcount == THRESH_HANGUP)) { 01078 res = AST_CONTROL_HANGUP; 01079 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01080 } 01081 break; 01082 } 01083 if (dsp->ringtimeout == THRESH_RING2ANSWER) { 01084 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 01085 res = AST_CONTROL_ANSWER; 01086 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01087 } 01088 } else { 01089 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01090 ast_debug(5, "Start state %d\n", newstate); 01091 dsp->tstate = newstate; 01092 dsp->tcount = 1; 01093 } 01094 01095 /* Reset goertzel */ 01096 for (x = 0; x < 7; x++) { 01097 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01098 } 01099 dsp->gsamps = 0; 01100 dsp->genergy = 0.0; 01101 } 01102 } 01103 01104 return res; 01105 }
static int __ast_dsp_silence_noise | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence, | |||
int * | totalnoise | |||
) | [static] |
Definition at line 1120 of file dsp.c.
References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::totalnoise, and ast_dsp::totalsilence.
Referenced by ast_dsp_noise(), ast_dsp_process(), and ast_dsp_silence().
01121 { 01122 int accum; 01123 int x; 01124 int res = 0; 01125 01126 if (!len) { 01127 return 0; 01128 } 01129 accum = 0; 01130 for (x = 0; x < len; x++) { 01131 accum += abs(s[x]); 01132 } 01133 accum /= len; 01134 if (accum < dsp->threshold) { 01135 /* Silent */ 01136 dsp->totalsilence += len / 8; 01137 #ifdef DEBUG_DSP_BUSYDETECT 01138 fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum); 01139 #endif 01140 if (dsp->totalnoise) { 01141 /* Move and save history */ 01142 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicnoise[0])); 01143 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01144 /* check if previous tone differs BUSY_PERCENT from the one before it */ 01145 int tone1 = dsp->historicnoise[DSP_HISTORY - 1]; 01146 int tone2 = dsp->historicnoise[DSP_HISTORY - 2]; 01147 if (tone1 < tone2) { 01148 if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2) 01149 dsp->busymaybe = 1; 01150 else 01151 dsp->busymaybe = 0; 01152 } else { 01153 if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2) 01154 dsp->busymaybe = 1; 01155 else 01156 dsp->busymaybe = 0; 01157 } 01158 } 01159 dsp->totalnoise = 0; 01160 res = 1; 01161 } else { 01162 /* Not silent */ 01163 dsp->totalnoise += len / 8; 01164 #ifdef DEBUG_DSP_BUSYDETECT 01165 fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum); 01166 #endif 01167 if (dsp->totalsilence) { 01168 /* Move and save history */ 01169 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1) * sizeof(dsp->historicsilence[0])); 01170 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01171 } 01172 dsp->totalsilence = 0; 01173 } 01174 if (totalsilence) { 01175 *totalsilence = dsp->totalsilence; 01176 } 01177 if (totalnoise) { 01178 *totalnoise = dsp->totalnoise; 01179 } 01180 return res; 01181 }
static int _dsp_init | ( | int | reload | ) | [static] |
Definition at line 1725 of file dsp.c.
References ast_config_destroy(), ast_config_load2(), ast_variable_retrieve(), ast_verb, CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, THRESHOLD_SILENCE, and value.
Referenced by ast_dsp_init(), and ast_dsp_reload().
01726 { 01727 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01728 struct ast_config *cfg; 01729 01730 cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags); 01731 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01732 ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD); 01733 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01734 return 0; 01735 } 01736 01737 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 01738 return 0; 01739 } 01740 01741 if (cfg) { 01742 const char *value; 01743 01744 value = ast_variable_retrieve(cfg, "default", "silencethreshold"); 01745 if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) { 01746 ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value); 01747 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01748 } else if (!value) { 01749 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01750 } 01751 01752 ast_config_destroy(cfg); 01753 } 01754 return 0; 01755 }
static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
int | mf | |||
) | [static] |
Definition at line 517 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().
00518 { 00519 s->current_digits = 0; 00520 s->detected_digits = 0; 00521 s->lost_digits = 0; 00522 s->digits[0] = '\0'; 00523 00524 if (mf) { 00525 ast_mf_detect_init(&s->td.mf); 00526 } else { 00527 ast_dtmf_detect_init(&s->td.dtmf); 00528 } 00529 }
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 1183 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.
01184 { 01185 int res = 0, x; 01186 int avgsilence = 0, hitsilence = 0; 01187 int avgtone = 0, hittone = 0; 01188 #ifdef DEBUG_DSP_BUSYDETECT 01189 char buf[16]; 01190 char silence_list[64]="", tone_list[64]=""; 01191 #endif 01192 01193 if (!dsp->busymaybe) { 01194 return res; 01195 } 01196 dsp->busymaybe = 0; 01197 01198 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01199 avgsilence += dsp->historicsilence[x]; 01200 avgtone += dsp->historicnoise[x]; 01201 } 01202 avgsilence /= dsp->busycount; 01203 avgtone /= dsp->busycount; 01204 #ifdef DEBUG_DSP_BUSYDETECT 01205 sprintf(silence_list,"Silences: "); 01206 sprintf(tone_list,"Tones: "); 01207 #endif 01208 for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) { 01209 #ifdef DEBUG_DSP_BUSYDETECT 01210 snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]); 01211 strcat(silence_list, buf); 01212 snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]); 01213 strcat(tone_list, buf); 01214 #endif 01215 if (!dsp->busytoneonly) { 01216 if (avgsilence > dsp->historicsilence[x]) { 01217 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01218 hitsilence++; 01219 } else { 01220 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01221 hitsilence++; 01222 } 01223 } 01224 if (avgtone > dsp->historicnoise[x]) { 01225 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) { 01226 hittone++; 01227 } 01228 } else { 01229 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) { 01230 hittone++; 01231 } 01232 } 01233 } 01234 #ifdef DEBUG_DSP_BUSYDETECT 01235 fprintf(stderr, "BUSY DETECTOR\n"); 01236 fprintf(stderr, "%s\n", tone_list); 01237 fprintf(stderr, "%s\n", silence_list) 01238 #endif 01239 if ((dsp->busytoneonly || 01240 (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) && 01241 (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01242 if (dsp->busycompare) { 01243 if (dsp->busytoneonly) { 01244 res = 1; 01245 ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare"); 01246 } else { 01247 if (avgtone > avgsilence) { 01248 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01249 res = 1; 01250 } else { 01251 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01252 res = 1; 01253 } 01254 } 01255 } else { 01256 res = 1; 01257 } 01258 } 01259 /* If we know the expected busy tone length, check we are in the range */ 01260 if (res && (dsp->busy_tonelength > 0)) { 01261 if (abs(avgtone - dsp->busy_tonelength) > MAX(dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100, 20)) { 01262 #ifdef BUSYDETECT_DEBUG 01263 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01264 avgtone, dsp->busy_tonelength); 01265 #endif 01266 res = 0; 01267 } 01268 } 01269 /* If we know the expected busy tone silent-period length, check we are in the range */ 01270 if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) { 01271 if (abs(avgsilence - dsp->busy_quietlength) > MAX(dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100, 20)) { 01272 #ifdef BUSYDETECT_DEBUG 01273 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01274 avgsilence, dsp->busy_quietlength); 01275 #endif 01276 res = 0; 01277 } 01278 } 01279 if (res) { 01280 if (option_debug) 01281 ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01282 } else { 01283 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01284 } 01285 return res; 01286 }
Scans for progress indication in audio.
Definition at line 1107 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.
01108 { 01109 if (inf->frametype != AST_FRAME_VOICE) { 01110 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01111 return 0; 01112 } 01113 if (inf->subclass.codec != AST_FORMAT_SLINEAR) { 01114 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01115 return 0; 01116 } 01117 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); 01118 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1627 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, 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().
01628 { 01629 int i; 01630 01631 dsp->dtmf_began = 0; 01632 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01633 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01634 /* Reinitialise the detector for the next block */ 01635 for (i = 0; i < 6; i++) { 01636 goertzel_reset(&s->tone_out[i]); 01637 } 01638 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01639 s->current_sample = 0; 01640 } else { 01641 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01642 /* Reinitialise the detector for the next block */ 01643 for (i = 0; i < 4; i++) { 01644 goertzel_reset(&s->row_out[i]); 01645 goertzel_reset(&s->col_out[i]); 01646 } 01647 s->lasthit = s->current_hit = 0; 01648 s->energy = 0.0; 01649 s->current_sample = 0; 01650 s->hits = 0; 01651 s->misses = 0; 01652 } 01653 01654 dsp->digit_state.digits[0] = '\0'; 01655 dsp->digit_state.current_digits = 0; 01656 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1583 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_session(), disable_dsp_detect(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), my_all_subchannels_hungup(), my_dsp_set_digitmode(), and sip_rtp_read().
01584 { 01585 ast_free(dsp); 01586 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1720 of file dsp.c.
References ast_dsp::tcount.
Referenced by dahdi_read().
01721 { 01722 return dsp->tcount; 01723 }
int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1757 of file dsp.c.
Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), and setup_privacy_args().
01758 { 01759 return thresholds[which]; 01760 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1715 of file dsp.c.
References ast_dsp::tstate.
Referenced by dahdi_read().
01716 { 01717 return dsp->tstate; 01718 }
int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1762 of file dsp.c.
References _dsp_init().
Referenced by main().
01763 { 01764 return _dsp_init(0); 01765 }
struct ast_dsp* ast_dsp_new | ( | void | ) |
Definition at line 1540 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_HISTORY, 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(), and read_config().
01541 { 01542 struct ast_dsp *dsp; 01543 01544 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01545 dsp->threshold = DEFAULT_THRESHOLD; 01546 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01547 dsp->busycount = DSP_HISTORY; 01548 dsp->digitmode = DSP_DIGITMODE_DTMF; 01549 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01550 dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT; 01551 #ifdef BUSYDETECT_TONEONLY 01552 dsp->busytoneonly = 1; 01553 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01554 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE"); 01555 #endif 01556 #else 01557 dsp->busytoneonly = 0; 01558 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01559 dsp->busycompare = 1; 01560 #else 01561 dsp->busycompare = 0; 01562 #endif 01563 #endif 01564 /* Initialize digit detector */ 01565 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01566 dsp->display_inband_dtmf_warning = 1; 01567 /* Initialize initial DSP progress detect parameters */ 01568 ast_dsp_prog_reset(dsp); 01569 /* Initialize fax detector */ 01570 ast_fax_detect_init(dsp); 01571 } 01572 return dsp; 01573 }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1306 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len(), and LOG_WARNING.
Referenced by do_waiting().
01307 { 01308 short *s; 01309 int len; 01310 01311 if (f->frametype != AST_FRAME_VOICE) { 01312 ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); 01313 return 0; 01314 } 01315 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01316 ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); 01317 return 0; 01318 } 01319 s = f->data.ptr; 01320 len = f->datalen/2; 01321 return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); 01322 }
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.
Definition at line 1325 of file dsp.c.
References __ast_dsp_silence_noise(), AST_ALAW, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_getformatname(), ast_log(), AST_MULAW, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_dsp::display_inband_dtmf_warning, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::features, ast_frame::frametype, len(), LOG_WARNING, ast_dsp::mute_fragments, ast_frame::ptr, and ast_frame::subclass.
Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().
01326 { 01327 int silence; 01328 int res; 01329 int digit = 0, fax_digit = 0; 01330 int x; 01331 short *shortdata; 01332 unsigned char *odata; 01333 int len; 01334 struct ast_frame *outf = NULL; 01335 01336 if (!af) { 01337 return NULL; 01338 } 01339 if (af->frametype != AST_FRAME_VOICE) { 01340 return af; 01341 } 01342 01343 odata = af->data.ptr; 01344 len = af->datalen; 01345 /* Make sure we have short data */ 01346 switch (af->subclass.codec) { 01347 case AST_FORMAT_SLINEAR: 01348 shortdata = af->data.ptr; 01349 len = af->datalen / 2; 01350 break; 01351 case AST_FORMAT_ULAW: 01352 case AST_FORMAT_TESTLAW: 01353 shortdata = alloca(af->datalen * 2); 01354 for (x = 0;x < len; x++) { 01355 shortdata[x] = AST_MULAW(odata[x]); 01356 } 01357 break; 01358 case AST_FORMAT_ALAW: 01359 shortdata = alloca(af->datalen * 2); 01360 for (x = 0; x < len; x++) { 01361 shortdata[x] = AST_ALAW(odata[x]); 01362 } 01363 break; 01364 default: 01365 /*Display warning only once. Otherwise you would get hundreds of warnings every second */ 01366 if (dsp->display_inband_dtmf_warning) 01367 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec)); 01368 dsp->display_inband_dtmf_warning = 0; 01369 return af; 01370 } 01371 01372 /* Initially we do not want to mute anything */ 01373 dsp->mute_fragments = 0; 01374 01375 /* Need to run the silence detection stuff for silence suppression and busy detection */ 01376 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { 01377 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); 01378 } 01379 01380 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01381 memset(&dsp->f, 0, sizeof(dsp->f)); 01382 dsp->f.frametype = AST_FRAME_NULL; 01383 ast_frfree(af); 01384 return ast_frisolate(&dsp->f); 01385 } 01386 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01387 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01388 memset(&dsp->f, 0, sizeof(dsp->f)); 01389 dsp->f.frametype = AST_FRAME_CONTROL; 01390 /* Signal this as it was a channel hangup, to avoid msg "channel.c:3473 ast_waitfordigit_full: Unexpected control subclass '5'" */ 01391 dsp->f.subclass.integer = AST_CONTROL_HANGUP; 01392 ast_frfree(af); 01393 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01394 return ast_frisolate(&dsp->f); 01395 } 01396 01397 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { 01398 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { 01399 fax_digit = 'f'; 01400 } 01401 01402 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { 01403 fax_digit = 'e'; 01404 } 01405 } 01406 01407 if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { 01408 if (dsp->digitmode & DSP_DIGITMODE_MF) 01409 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01410 else 01411 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01412 01413 if (dsp->digit_state.current_digits) { 01414 int event = 0, event_len = 0; 01415 char event_digit = 0; 01416 01417 if (!dsp->dtmf_began) { 01418 /* We have not reported DTMF_BEGIN for anything yet */ 01419 01420 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01421 event = AST_FRAME_DTMF_BEGIN; 01422 event_digit = dsp->digit_state.digits[0]; 01423 } 01424 dsp->dtmf_began = 1; 01425 01426 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { 01427 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ 01428 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01429 event = AST_FRAME_DTMF_END; 01430 event_digit = dsp->digit_state.digits[0]; 01431 event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; 01432 } 01433 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); 01434 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0])); 01435 dsp->digit_state.current_digits--; 01436 dsp->dtmf_began = 0; 01437 01438 if (dsp->features & DSP_FEATURE_BUSY_DETECT) { 01439 /* Reset Busy Detector as we have some confirmed activity */ 01440 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01441 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01442 ast_debug(1, "DTMF Detected - Reset busydetector\n"); 01443 } 01444 } 01445 01446 if (event) { 01447 memset(&dsp->f, 0, sizeof(dsp->f)); 01448 dsp->f.frametype = event; 01449 dsp->f.subclass.integer = event_digit; 01450 dsp->f.len = event_len; 01451 outf = &dsp->f; 01452 goto done; 01453 } 01454 } 01455 } 01456 01457 if (fax_digit) { 01458 /* Fax was detected - digit is either 'f' or 'e' */ 01459 01460 memset(&dsp->f, 0, sizeof(dsp->f)); 01461 dsp->f.frametype = AST_FRAME_DTMF; 01462 dsp->f.subclass.integer = fax_digit; 01463 outf = &dsp->f; 01464 goto done; 01465 } 01466 01467 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01468 res = __ast_dsp_call_progress(dsp, shortdata, len); 01469 if (res) { 01470 switch (res) { 01471 case AST_CONTROL_ANSWER: 01472 case AST_CONTROL_BUSY: 01473 case AST_CONTROL_RINGING: 01474 case AST_CONTROL_CONGESTION: 01475 case AST_CONTROL_HANGUP: 01476 memset(&dsp->f, 0, sizeof(dsp->f)); 01477 dsp->f.frametype = AST_FRAME_CONTROL; 01478 dsp->f.subclass.integer = res; 01479 dsp->f.src = "dsp_progress"; 01480 if (chan) 01481 ast_queue_frame(chan, &dsp->f); 01482 break; 01483 default: 01484 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01485 } 01486 } 01487 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { 01488 res = __ast_dsp_call_progress(dsp, shortdata, len); 01489 } 01490 01491 done: 01492 /* Mute fragment of the frame */ 01493 for (x = 0; x < dsp->mute_fragments; x++) { 01494 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); 01495 } 01496 01497 switch (af->subclass.codec) { 01498 case AST_FORMAT_SLINEAR: 01499 break; 01500 case AST_FORMAT_ULAW: 01501 for (x = 0; x < len; x++) { 01502 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); 01503 } 01504 break; 01505 case AST_FORMAT_ALAW: 01506 for (x = 0; x < len; x++) { 01507 odata[x] = AST_LIN2A((unsigned short) shortdata[x]); 01508 } 01509 break; 01510 } 01511 01512 if (outf) { 01513 if (chan) { 01514 ast_queue_frame(chan, af); 01515 } 01516 ast_frfree(af); 01517 return ast_frisolate(outf); 01518 } else { 01519 return af; 01520 } 01521 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1523 of file dsp.c.
References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::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().
01524 { 01525 int max = 0; 01526 int x; 01527 01528 dsp->gsamp_size = modes[dsp->progmode].size; 01529 dsp->gsamps = 0; 01530 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01531 if (modes[dsp->progmode].freqs[x]) { 01532 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01533 max = x + 1; 01534 } 01535 } 01536 dsp->freqcount = max; 01537 dsp->ringtimeout= 0; 01538 }
int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1767 of file dsp.c.
References _dsp_init().
01768 { 01769 return _dsp_init(1); 01770 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1658 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().
01659 { 01660 int x; 01661 01662 dsp->totalsilence = 0; 01663 dsp->gsamps = 0; 01664 for (x = 0; x < 4; x++) { 01665 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01666 } 01667 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01668 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01669 dsp->ringtimeout= 0; 01670 }
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 1607 of file dsp.c.
References ast_dsp::busycompare.
Referenced by dahdi_new().
01608 { 01609 if (compare > 0) 01610 dsp->busycompare = 1; 01611 else 01612 dsp->busycompare = 0; 01613 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1596 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01597 { 01598 if (cadences < 4) { 01599 cadences = 4; 01600 } 01601 if (cadences > DSP_HISTORY) { 01602 cadences = DSP_HISTORY; 01603 } 01604 dsp->busycount = cadences; 01605 }
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 1615 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().
01616 { 01617 dsp->busy_tonelength = tonelength; 01618 if (quietlength > 0) 01619 dsp->busy_quietlength = quietlength; 01620 else 01621 dsp->busytoneonly = 1; 01622 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01623 if( fuzzy > 0 && fuzzy < 50 ) 01624 dsp->busy_pattern_fuzzy = fuzzy; 01625 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1696 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
01697 { 01698 int x; 01699 01700 for (x = 0; x < ARRAY_LEN(aliases); x++) { 01701 if (!strcasecmp(aliases[x].name, zone)) { 01702 dsp->progmode = aliases[x].mode; 01703 ast_dsp_prog_reset(dsp); 01704 return 0; 01705 } 01706 } 01707 return -1; 01708 }
int ast_dsp_set_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1672 of file dsp.c.
References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.
Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), and my_dsp_set_digitmode().
01673 { 01674 int new; 01675 int old; 01676 01677 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01678 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01679 if (old != new) { 01680 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01681 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01682 } 01683 dsp->digitmode = digitmode; 01684 return 0; 01685 }
int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
int | faxmode | |||
) |
Set fax mode.
Definition at line 1687 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01688 { 01689 if (dsp->faxmode != faxmode) { 01690 ast_fax_detect_init(dsp); 01691 } 01692 dsp->faxmode = faxmode; 01693 return 0; 01694 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1575 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(), my_pri_ss7_open_media(), read_config(), and sip_rtp_read().
01576 { 01577 dsp->features = features; 01578 if (!(features & DSP_FEATURE_DIGIT_DETECT)) { 01579 dsp->display_inband_dtmf_warning = 0; 01580 } 01581 }
void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
int | threshold | |||
) |
Set threshold value for silence.
Definition at line 1588 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), dahdi_new(), do_waiting(), fax_session_new(), handle_recordfile(), and isAnsweringMachine().
01589 { 01590 if (threshold < 256) 01591 dsp->threshold = 256; 01592 else 01593 dsp->threshold = threshold; 01594 }
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1288 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len(), and LOG_WARNING.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), debug_check_frame_for_silence(), do_waiting(), handle_recordfile(), and isAnsweringMachine().
01289 { 01290 short *s; 01291 int len; 01292 01293 if (f->frametype != AST_FRAME_VOICE) { 01294 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01295 return 0; 01296 } 01297 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01298 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01299 return 0; 01300 } 01301 s = f->data.ptr; 01302 len = f->datalen/2; 01303 return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); 01304 }
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 1710 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
01711 { 01712 return (dsp->mute_fragments > 0); 01713 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 487 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_HITS_TO_BEGIN, DTMF_MISSES_TO_END, dtmf_detect_state_t::energy, goertzel_init(), dtmf_detect_state_t::hits, dtmf_detect_state_t::hits_to_begin, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, dtmf_detect_state_t::misses_to_end, and dtmf_detect_state_t::row_out.
Referenced by ast_digit_detect_init().
00488 { 00489 int i; 00490 00491 s->lasthit = 0; 00492 s->current_hit = 0; 00493 for (i = 0; i < 4; i++) { 00494 goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE); 00495 goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE); 00496 s->energy = 0.0; 00497 } 00498 s->current_sample = 0; 00499 s->hits = 0; 00500 s->misses = 0; 00501 00502 s->hits_to_begin = DTMF_HITS_TO_BEGIN; 00503 s->misses_to_end = DTMF_MISSES_TO_END; 00504 }
static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 481 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().
00482 { 00483 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00484 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00485 }
static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 506 of file dsp.c.
References mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, goertzel_init(), mf_detect_state_t::hits, and mf_detect_state_t::tone_out.
Referenced by ast_digit_detect_init().
00507 { 00508 int i; 00509 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00510 for (i = 0; i < 6; i++) { 00511 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00512 } 00513 s->current_sample = 0; 00514 s->current_hit = 0; 00515 }
static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
int | freq, | |||
int | duration, | |||
int | amp | |||
) | [static] |
Definition at line 421 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().
00422 { 00423 int duration_samples; 00424 float x; 00425 int periods_in_block; 00426 00427 s->freq = freq; 00428 00429 /* Desired tone duration in samples */ 00430 duration_samples = duration * SAMPLE_RATE / 1000; 00431 /* We want to allow 10% deviation of tone duration */ 00432 duration_samples = duration_samples * 9 / 10; 00433 00434 /* If we want to remove tone, it is important to have block size not 00435 to exceed frame size. Otherwise by the moment tone is detected it is too late 00436 to squelch it from previous frames */ 00437 s->block_size = SAMPLES_IN_FRAME; 00438 00439 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00440 00441 /* Make sure we will have at least 5 periods at target frequency for analisys. 00442 This may make block larger than expected packet and will make squelching impossible 00443 but at least we will be detecting the tone */ 00444 if (periods_in_block < 5) 00445 periods_in_block = 5; 00446 00447 /* Now calculate final block size. It will contain integer number of periods */ 00448 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00449 00450 /* tone_detect is currently only used to detect fax tones and we 00451 do not need suqlching the fax tones */ 00452 s->squelch = 0; 00453 00454 /* Account for the first and the last block to be incomplete 00455 and thus no tone will be detected in them */ 00456 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00457 00458 goertzel_init(&s->tone, freq, s->block_size); 00459 00460 s->samples_pending = s->block_size; 00461 s->hit_count = 0; 00462 s->last_hit = 0; 00463 s->energy = 0.0; 00464 00465 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00466 According to Parseval's theorem the energy computed in time domain equals to energy 00467 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00468 from the energy in the time domain we will get energy of the remaining signal (without the tone 00469 we are detecting). We will be checking that 00470 10*log(Ew / (Et - Ew)) > amp 00471 Calculate threshold so that we will be actually checking 00472 Ew > Et * threshold 00473 */ 00474 00475 x = pow(10.0, amp / 10.0); 00476 s->threshold = x / (x + 1); 00477 00478 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00479 }
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 648 of file dsp.c.
References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_sample, digit_detect_state_t::dtmf, DTMF_GSIZE, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, dtmf_detect_state_t::energy, goertzel_result(), goertzel_sample(), mute, dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, and digit_detect_state_t::td.
00649 { 00650 float row_energy[4]; 00651 float col_energy[4]; 00652 float famp; 00653 int i; 00654 int j; 00655 int sample; 00656 int best_row; 00657 int best_col; 00658 int hit; 00659 int limit; 00660 fragment_t mute = {0, 0}; 00661 00662 if (squelch && s->td.dtmf.mute_samples > 0) { 00663 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples; 00664 s->td.dtmf.mute_samples -= mute.end; 00665 } 00666 00667 hit = 0; 00668 for (sample = 0; sample < samples; sample = limit) { 00669 /* DTMF_GSIZE is optimised to meet the DTMF specs. */ 00670 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) { 00671 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample); 00672 } else { 00673 limit = samples; 00674 } 00675 /* The following unrolled loop takes only 35% (rough estimate) of the 00676 time of a rolled loop on the machine on which it was developed */ 00677 for (j = sample; j < limit; j++) { 00678 famp = amp[j]; 00679 s->td.dtmf.energy += famp*famp; 00680 /* With GCC 2.95, the following unrolled code seems to take about 35% 00681 (rough estimate) as long as a neat little 0-3 loop */ 00682 goertzel_sample(s->td.dtmf.row_out, amp[j]); 00683 goertzel_sample(s->td.dtmf.col_out, amp[j]); 00684 goertzel_sample(s->td.dtmf.row_out + 1, amp[j]); 00685 goertzel_sample(s->td.dtmf.col_out + 1, amp[j]); 00686 goertzel_sample(s->td.dtmf.row_out + 2, amp[j]); 00687 goertzel_sample(s->td.dtmf.col_out + 2, amp[j]); 00688 goertzel_sample(s->td.dtmf.row_out + 3, amp[j]); 00689 goertzel_sample(s->td.dtmf.col_out + 3, amp[j]); 00690 } 00691 s->td.dtmf.current_sample += (limit - sample); 00692 if (s->td.dtmf.current_sample < DTMF_GSIZE) { 00693 continue; 00694 } 00695 /* We are at the end of a DTMF detection block */ 00696 /* Find the peak row and the peak column */ 00697 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00698 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00699 00700 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00701 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00702 if (row_energy[i] > row_energy[best_row]) { 00703 best_row = i; 00704 } 00705 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00706 if (col_energy[i] > col_energy[best_col]) { 00707 best_col = i; 00708 } 00709 } 00710 hit = 0; 00711 /* Basic signal level test and the twist test */ 00712 if (row_energy[best_row] >= DTMF_THRESHOLD && 00713 col_energy[best_col] >= DTMF_THRESHOLD && 00714 col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST && 00715 col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) { 00716 /* Relative peak test */ 00717 for (i = 0; i < 4; i++) { 00718 if ((i != best_col && 00719 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00720 (i != best_row 00721 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00722 break; 00723 } 00724 } 00725 /* ... and fraction of total energy test */ 00726 if (i >= 4 && 00727 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) { 00728 /* Got a hit */ 00729 hit = dtmf_positions[(best_row << 2) + best_col]; 00730 } 00731 } 00732 00733 if (hit == s->td.dtmf.lasthit) { 00734 if (s->td.dtmf.current_hit) { 00735 /* We are in the middle of a digit already */ 00736 if (hit) { 00737 if (hit != s->td.dtmf.current_hit) { 00738 /* Look for a start of a new digit. 00739 This is because hits_to_begin may be smaller than misses_to_end 00740 and we may find the beginning of new digit before we consider last one ended. */ 00741 s->td.dtmf.current_hit = 0; 00742 } else { 00743 /* Current hit was same as last, so increment digit duration (of last digit) */ 00744 s->digitlen[s->current_digits - 1] += DTMF_GSIZE; 00745 } 00746 } else { 00747 /* No Digit */ 00748 s->td.dtmf.misses++; 00749 if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) { 00750 /* There were enough misses to consider digit ended */ 00751 s->td.dtmf.current_hit = 0; 00752 } 00753 } 00754 } else if (hit) { 00755 /* Detecting new digit */ 00756 s->td.dtmf.hits++; 00757 if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin) { 00758 store_digit(s, hit); 00759 s->td.dtmf.current_hit = hit; 00760 } 00761 } 00762 } else { 00763 s->td.dtmf.hits = 1; 00764 s->td.dtmf.misses = 1; 00765 s->td.dtmf.lasthit = hit; 00766 } 00767 00768 /* If we had a hit in this block, include it into mute fragment */ 00769 if (squelch && hit) { 00770 if (mute.end < sample - DTMF_GSIZE) { 00771 /* There is a gap between fragments */ 00772 mute_fragment(dsp, &mute); 00773 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0; 00774 } 00775 mute.end = limit + DTMF_GSIZE; 00776 } 00777 00778 /* Reinitialise the detector for the next block */ 00779 for (i = 0; i < 4; i++) { 00780 goertzel_reset(&s->td.dtmf.row_out[i]); 00781 goertzel_reset(&s->td.dtmf.col_out[i]); 00782 } 00783 s->td.dtmf.energy = 0.0; 00784 s->td.dtmf.current_sample = 0; 00785 } 00786 00787 if (squelch && mute.end) { 00788 if (mute.end > samples) { 00789 s->td.dtmf.mute_samples = mute.end - samples; 00790 mute.end = samples; 00791 } 00792 mute_fragment(dsp, &mute); 00793 } 00794 00795 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00796 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 346 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().
00347 { 00348 s->v2 = s->v3 = s->chunky = 0.0; 00349 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE)); 00350 s->samples = samples; 00351 }
static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 353 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_digitreset().
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 337 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(), and dtmf_detect().
00338 { 00339 goertzel_result_t r; 00340 r.value = (s->v3 * s->v3) + (s->v2 * s->v2); 00341 r.value -= ((s->v2 * s->v3) >> 15) * s->fac; 00342 r.power = s->chunky * 2; 00343 return (float)r.value * (float)(1 << r.power); 00344 }
static void goertzel_sample | ( | goertzel_state_t * | s, | |
short | sample | |||
) | [inline, static] |
Definition at line 310 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().
00311 { 00312 int v1; 00313 00314 v1 = s->v2; 00315 s->v2 = s->v3; 00316 00317 s->v3 = (s->fac * s->v2) >> 15; 00318 s->v3 = s->v3 - v1 + (sample >> s->chunky); 00319 if (abs(s->v3) > 32768) { 00320 s->chunky++; 00321 s->v3 = s->v3 >> 1; 00322 s->v2 = s->v2 >> 1; 00323 v1 = v1 >> 1; 00324 } 00325 }
static void goertzel_update | ( | goertzel_state_t * | s, | |
short * | samps, | |||
int | count | |||
) | [inline, static] |
Definition at line 327 of file dsp.c.
References goertzel_sample().
00328 { 00329 int i; 00330 00331 for (i = 0; i < count; i++) { 00332 goertzel_sample(s, samps[i]); 00333 } 00334 }
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 798 of file dsp.c.
References mf_detect_state_t::current_sample, goertzel_sample(), digit_detect_state_t::mf, MF_GSIZE, mute, mf_detect_state_t::mute_samples, digit_detect_state_t::td, and mf_detect_state_t::tone_out.
00800 { 00801 float energy[6]; 00802 int best; 00803 int second_best; 00804 int i; 00805 int j; 00806 int sample; 00807 int hit; 00808 int limit; 00809 fragment_t mute = {0, 0}; 00810 00811 if (squelch && s->td.mf.mute_samples > 0) { 00812 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples; 00813 s->td.mf.mute_samples -= mute.end; 00814 } 00815 00816 hit = 0; 00817 for (sample = 0; sample < samples; sample = limit) { 00818 /* 80 is optimised to meet the MF specs. */ 00819 /* XXX So then why is MF_GSIZE defined as 120? */ 00820 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) { 00821 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00822 } else { 00823 limit = samples; 00824 } 00825 /* The following unrolled loop takes only 35% (rough estimate) of the 00826 time of a rolled loop on the machine on which it was developed */ 00827 for (j = sample; j < limit; j++) { 00828 /* With GCC 2.95, the following unrolled code seems to take about 35% 00829 (rough estimate) as long as a neat little 0-3 loop */ 00830 goertzel_sample(s->td.mf.tone_out, amp[j]); 00831 goertzel_sample(s->td.mf.tone_out + 1, amp[j]); 00832 goertzel_sample(s->td.mf.tone_out + 2, amp[j]); 00833 goertzel_sample(s->td.mf.tone_out + 3, amp[j]); 00834 goertzel_sample(s->td.mf.tone_out + 4, amp[j]); 00835 goertzel_sample(s->td.mf.tone_out + 5, amp[j]); 00836 } 00837 s->td.mf.current_sample += (limit - sample); 00838 if (s->td.mf.current_sample < MF_GSIZE) { 00839 continue; 00840 } 00841 /* We're at the end of an MF detection block. */ 00842 /* Find the two highest energies. The spec says to look for 00843 two tones and two tones only. Taking this literally -ie 00844 only two tones pass the minimum threshold - doesn't work 00845 well. The sinc function mess, due to rectangular windowing 00846 ensure that! Find the two highest energies and ensure they 00847 are considerably stronger than any of the others. */ 00848 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00849 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00850 if (energy[0] > energy[1]) { 00851 best = 0; 00852 second_best = 1; 00853 } else { 00854 best = 1; 00855 second_best = 0; 00856 } 00857 /*endif*/ 00858 for (i = 2; i < 6; i++) { 00859 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00860 if (energy[i] >= energy[best]) { 00861 second_best = best; 00862 best = i; 00863 } else if (energy[i] >= energy[second_best]) { 00864 second_best = i; 00865 } 00866 } 00867 /* Basic signal level and twist tests */ 00868 hit = 0; 00869 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00870 && energy[best] < energy[second_best]*BELL_MF_TWIST 00871 && energy[best] * BELL_MF_TWIST > energy[second_best]) { 00872 /* Relative peak test */ 00873 hit = -1; 00874 for (i = 0; i < 6; i++) { 00875 if (i != best && i != second_best) { 00876 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00877 /* The best two are not clearly the best */ 00878 hit = 0; 00879 break; 00880 } 00881 } 00882 } 00883 } 00884 if (hit) { 00885 /* Get the values into ascending order */ 00886 if (second_best < best) { 00887 i = best; 00888 best = second_best; 00889 second_best = i; 00890 } 00891 best = best * 5 + second_best - 1; 00892 hit = bell_mf_positions[best]; 00893 /* Look for two successive similar results */ 00894 /* The logic in the next test is: 00895 For KP we need 4 successive identical clean detects, with 00896 two blocks of something different preceeding it. For anything 00897 else we need two successive identical clean detects, with 00898 two blocks of something different preceeding it. */ 00899 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00900 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00901 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00902 hit != s->td.mf.hits[0]))) { 00903 store_digit(s, hit); 00904 } 00905 } 00906 00907 00908 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00909 /* Two successive block without a hit terminate current digit */ 00910 s->td.mf.current_hit = 0; 00911 } 00912 00913 s->td.mf.hits[0] = s->td.mf.hits[1]; 00914 s->td.mf.hits[1] = s->td.mf.hits[2]; 00915 s->td.mf.hits[2] = s->td.mf.hits[3]; 00916 s->td.mf.hits[3] = s->td.mf.hits[4]; 00917 s->td.mf.hits[4] = hit; 00918 00919 /* If we had a hit in this block, include it into mute fragment */ 00920 if (squelch && hit) { 00921 if (mute.end < sample - MF_GSIZE) { 00922 /* There is a gap between fragments */ 00923 mute_fragment(dsp, &mute); 00924 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0; 00925 } 00926 mute.end = limit + DTMF_GSIZE; 00927 } 00928 00929 /* Reinitialise the detector for the next block */ 00930 for (i = 0; i < 6; i++) 00931 goertzel_reset(&s->td.mf.tone_out[i]); 00932 s->td.mf.current_sample = 0; 00933 } 00934 00935 if (squelch && mute.end) { 00936 if (mute.end > samples) { 00937 s->td.mf.mute_samples = mute.end - samples; 00938 mute.end = samples; 00939 } 00940 mute_fragment(dsp, &mute); 00941 } 00942 00943 return (s->td.mf.current_hit); /* return the debounced hit */ 00944 }
static void mute_fragment | ( | struct ast_dsp * | dsp, | |
fragment_t * | fragment | |||
) | [static] |
Definition at line 411 of file dsp.c.
References ARRAY_LEN, ast_log(), LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.
00412 { 00413 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) { 00414 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n"); 00415 return; 00416 } 00417 00418 dsp->mute_data[dsp->mute_fragments++] = *fragment; 00419 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 946 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00947 { 00948 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00949 /* Make sure absolute levels are high enough */ 00950 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) { 00951 return 0; 00952 } 00953 /* Amplify ignored stuff */ 00954 i2 *= TONE_THRESH; 00955 i1 *= TONE_THRESH; 00956 e *= TONE_THRESH; 00957 /* Check first tone */ 00958 if ((p1 < i1) || (p1 < i2) || (p1 < e)) { 00959 return 0; 00960 } 00961 /* And second */ 00962 if ((p2 < i1) || (p2 < i2) || (p2 < e)) { 00963 return 0; 00964 } 00965 /* Guess it's there... */ 00966 return 1; 00967 }
static void store_digit | ( | digit_detect_state_t * | s, | |
char | digit | |||
) | [static] |
Definition at line 635 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.
00636 { 00637 s->detected_digits++; 00638 if (s->current_digits < MAX_DTMF_DIGITS) { 00639 s->digitlen[s->current_digits] = 0; 00640 s->digits[s->current_digits++] = digit; 00641 s->digits[s->current_digits] = '\0'; 00642 } else { 00643 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00644 s->lost_digits++; 00645 } 00646 }
static int tone_detect | ( | struct ast_dsp * | dsp, | |
tone_detect_state_t * | s, | |||
int16_t * | amp, | |||
int | samples | |||
) | [static] |
Definition at line 531 of file dsp.c.
References tone_detect_state_t::energy, goertzel_sample(), mute, tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, and tone_detect_state_t::tone.
00532 { 00533 float tone_energy; 00534 int i; 00535 int hit = 0; 00536 int limit; 00537 int res = 0; 00538 int16_t *ptr; 00539 int start, end; 00540 fragment_t mute = {0, 0}; 00541 00542 if (s->squelch && s->mute_samples > 0) { 00543 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples; 00544 s->mute_samples -= mute.end; 00545 } 00546 00547 for (start = 0; start < samples; start = end) { 00548 /* Process in blocks. */ 00549 limit = samples - start; 00550 if (limit > s->samples_pending) { 00551 limit = s->samples_pending; 00552 } 00553 end = start + limit; 00554 00555 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00556 /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ 00557 s->energy += (int32_t) *ptr * (int32_t) *ptr; 00558 00559 goertzel_sample(&s->tone, *ptr); 00560 } 00561 00562 s->samples_pending -= limit; 00563 00564 if (s->samples_pending) { 00565 /* Finished incomplete (last) block */ 00566 break; 00567 } 00568 00569 tone_energy = goertzel_result(&s->tone); 00570 00571 /* Scale to make comparable */ 00572 tone_energy *= 2.0; 00573 s->energy *= s->block_size; 00574 00575 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)); 00576 hit = 0; 00577 if (tone_energy > s->energy * s->threshold) { 00578 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00579 hit = 1; 00580 } 00581 00582 if (s->hit_count) { 00583 s->hit_count++; 00584 } 00585 00586 if (hit == s->last_hit) { 00587 if (!hit) { 00588 /* Two successive misses. Tone ended */ 00589 s->hit_count = 0; 00590 } else if (!s->hit_count) { 00591 s->hit_count++; 00592 } 00593 00594 } 00595 00596 if (s->hit_count == s->hits_required) { 00597 ast_debug(1, "%d Hz done detected\n", s->freq); 00598 res = 1; 00599 } 00600 00601 s->last_hit = hit; 00602 00603 /* If we had a hit in this block, include it into mute fragment */ 00604 if (s->squelch && hit) { 00605 if (mute.end < start - s->block_size) { 00606 /* There is a gap between fragments */ 00607 mute_fragment(dsp, &mute); 00608 mute.start = (start > s->block_size) ? (start - s->block_size) : 0; 00609 } 00610 mute.end = end + s->block_size; 00611 } 00612 00613 /* Reinitialise the detector for the next block */ 00614 /* Reset for the next block */ 00615 goertzel_reset(&s->tone); 00616 00617 /* Advance to the next block */ 00618 s->energy = 0.0; 00619 s->samples_pending = s->block_size; 00620 00621 amp += limit; 00622 } 00623 00624 if (s->squelch && mute.end) { 00625 if (mute.end > samples) { 00626 s->mute_samples = mute.end - samples; 00627 mute.end = samples; 00628 } 00629 mute_fragment(dsp, &mute); 00630 } 00631 00632 return res; 00633 }
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] |
const char dtmf_positions[] = "123A" "456B" "789C" "*0#D" [static] |
const float dtmf_row[] [static] |
const float mf_tones[] [static] |
Referenced by ast_dsp_prog_reset().
int thresholds[THRESHOLD_MAX] [static] |