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