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