Convenience Signal Processing routines. More...
#include "asterisk.h"#include <math.h>#include "asterisk/frame.h"#include "asterisk/channel.h"#include "asterisk/dsp.h"#include "asterisk/ulaw.h"#include "asterisk/alaw.h"#include "asterisk/utils.h"#include "asterisk/options.h"#include "asterisk/config.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_dsp |
| struct | digit_detect_state_t |
| struct | dtmf_detect_state_t |
| struct | fragment_t |
| struct | goertzel_result_t |
| struct | goertzel_state_t |
| struct | mf_detect_state_t |
| struct | progalias |
| struct | progress |
| struct | tone_detect_state_t |
Defines | |
| #define | BELL_MF_RELATIVE_PEAK 12.6 |
| #define | BELL_MF_THRESHOLD 1.6e9 |
| #define | BELL_MF_TWIST 4.0 |
| #define | CONFIG_FILE_NAME "dsp.conf" |
| #define | 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 = 7, BUSY_THRESHOLD = 100, BUSY_MIN = 75, BUSY_MAX = 3100 } |
| enum | freq_index { HZ_350 = 0, HZ_440, HZ_480, HZ_620, HZ_950, HZ_1400, HZ_1800, HZ_425 = 0, HZ_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. | |
| struct ast_dsp * | ast_dsp_new (void) |
| int | ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise) |
| Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise. | |
| struct ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af) |
| Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled. | |
| static void | ast_dsp_prog_reset (struct ast_dsp *dsp) |
| int | ast_dsp_reload (void) |
| Reloads dsp settings from dsp.conf. | |
| void | ast_dsp_reset (struct ast_dsp *dsp) |
| Reset total silence count. | |
| void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences) |
| Set number of required cadences for busy. | |
| void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength) |
| Set expected lengths of the busy tone. | |
| int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
| Set zone for doing progress detection. | |
| int | ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode) |
| Set digit mode. | |
| int | ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode) |
| Set fax mode. | |
| void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
| Select feature set. | |
| void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold) |
| Set threshold value for silence. | |
| int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
| Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. | |
| int | ast_dsp_was_muted (struct ast_dsp *dsp) |
| Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio. | |
| static void | ast_dtmf_detect_init (dtmf_detect_state_t *s) |
| static void | ast_fax_detect_init (struct ast_dsp *s) |
| static void | ast_mf_detect_init (mf_detect_state_t *s) |
| static void | ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp) |
| static int | dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
| static void | goertzel_init (goertzel_state_t *s, float freq, int samples) |
| static void | goertzel_reset (goertzel_state_t *s) |
| static float | goertzel_result (goertzel_state_t *s) |
| static void | goertzel_sample (goertzel_state_t *s, short sample) |
| static void | goertzel_update (goertzel_state_t *s, short *samps, int count) |
| static int | mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax) |
| static void | mute_fragment (struct ast_dsp *dsp, fragment_t *fragment) |
| static int | pair_there (float p1, float p2, float i1, float i2, float e) |
| static void | store_digit (digit_detect_state_t *s, char digit) |
| static int | tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples) |
Variables | |
| static struct progalias | aliases [] |
| static 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] |
Convenience Signal Processing routines.
Definition in file dsp.c.
| #define BELL_MF_RELATIVE_PEAK 12.6 |
Definition at line 172 of file dsp.c.
Referenced by mf_detect().
| #define BELL_MF_THRESHOLD 1.6e9 |
Definition at line 170 of file dsp.c.
Referenced by mf_detect().
| #define BELL_MF_TWIST 4.0 |
Definition at line 171 of file dsp.c.
Referenced by mf_detect().
| #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 |
Definition at line 207 of file dsp.c.
Referenced by ast_dtmf_detect_init(), dtmf_detect(), and mf_detect().
| #define DTMF_HITS_TO_BEGIN 2 |
Definition at line 210 of file dsp.c.
Referenced by ast_dtmf_detect_init().
| #define DTMF_MISSES_TO_END 3 |
Definition at line 212 of file dsp.c.
Referenced by ast_dtmf_detect_init().
| #define DTMF_NORMAL_TWIST 6.3 |
Definition at line 158 of file dsp.c.
Referenced by dtmf_detect().
| #define DTMF_RELATIVE_PEAK_COL 6.3 |
Definition at line 165 of file dsp.c.
Referenced by dtmf_detect().
| #define DTMF_RELATIVE_PEAK_ROW 6.3 |
Definition at line 164 of file dsp.c.
Referenced by dtmf_detect().
| #define DTMF_REVERSE_TWIST (relax ? 4.0 : 2.5) |
Definition at line 162 of file dsp.c.
Referenced by dtmf_detect().
| #define DTMF_THRESHOLD 8.0e7 |
Definition at line 155 of file dsp.c.
Referenced by dtmf_detect().
| #define DTMF_TO_TOTAL_ENERGY 42.0 |
Definition at line 168 of file dsp.c.
Referenced by dtmf_detect().
| #define FAX_TONE_CED_DB 16 |
Definition at line 191 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define FAX_TONE_CED_DURATION 2600 |
Definition at line 190 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define FAX_TONE_CED_FREQ 2100 |
Definition at line 189 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define FAX_TONE_CNG_DB 16 |
Definition at line 183 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define FAX_TONE_CNG_DURATION 500 |
Definition at line 182 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define FAX_TONE_CNG_FREQ 1100 |
Definition at line 181 of file dsp.c.
Referenced by ast_fax_detect_init().
| #define MAX_DTMF_DIGITS 128 |
Definition at line 141 of file dsp.c.
Referenced by store_digit().
| #define MF_GSIZE 120 |
Definition at line 204 of file dsp.c.
Referenced by mf_detect().
| #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 |
Definition at line 201 of file dsp.c.
Referenced by ast_tone_detect_init().
| #define TONE_MIN_THRESH 1e8 |
How much tone there should be at least to attempt
Definition at line 129 of file dsp.c.
Referenced by __ast_dsp_call_progress(), and pair_there().
| #define TONE_THRESH 10.0 |
How much louder the tone should be than channel energy
Definition at line 128 of file dsp.c.
Referenced by __ast_dsp_call_progress(), and pair_there().
| enum busy_detect |
| BUSY_PERCENT |
The percentage difference between the two last silence periods |
| BUSY_PAT_PERCENT |
The percentage difference between measured and actual pattern |
| BUSY_THRESHOLD |
Max number of ms difference between max and min times in busy |
| BUSY_MIN |
Busy must be at least 80 ms in half-cadence |
| BUSY_MAX |
Busy can't be longer than 3100 ms in half-cadence |
Definition at line 117 of file dsp.c.
00117 { 00118 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */ 00119 BUSY_PAT_PERCENT = 7, /*!< 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 = 75, /*!< Busy must be at least 80 ms in half-cadence */ 00122 BUSY_MAX =3100 /*!< Busy can't be longer than 3100 ms in half-cadence */ 00123 };
| enum freq_index |
| enum gsamp_size |
Number of goertzels for progress detect
| GSAMP_SIZE_NA |
North America - 350, 440, 480, 620, 950, 1400, 1800 Hz |
| GSAMP_SIZE_CR |
Costa Rica, Brazil - Only care about 425 Hz |
| GSAMP_SIZE_UK |
UK disconnect goertzel feed - should trigger 400hz |
Definition at line 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 949 of file dsp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_call_progress(), and ast_dsp_process().
00950 { 00951 int x; 00952 int y; 00953 int pass; 00954 int newstate = DSP_TONE_STATE_SILENCE; 00955 int res = 0; 00956 while (len) { 00957 /* Take the lesser of the number of samples we need and what we have */ 00958 pass = len; 00959 if (pass > dsp->gsamp_size - dsp->gsamps) 00960 pass = dsp->gsamp_size - dsp->gsamps; 00961 for (x=0;x<pass;x++) { 00962 for (y=0;y<dsp->freqcount;y++) 00963 goertzel_sample(&dsp->freqs[y], s[x]); 00964 dsp->genergy += s[x] * s[x]; 00965 } 00966 s += pass; 00967 dsp->gsamps += pass; 00968 len -= pass; 00969 if (dsp->gsamps == dsp->gsamp_size) { 00970 float hz[7]; 00971 for (y=0;y<7;y++) 00972 hz[y] = goertzel_result(&dsp->freqs[y]); 00973 switch (dsp->progmode) { 00974 case PROG_MODE_NA: 00975 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 00976 newstate = DSP_TONE_STATE_BUSY; 00977 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 00978 newstate = DSP_TONE_STATE_RINGING; 00979 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 00980 newstate = DSP_TONE_STATE_DIALTONE; 00981 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 00982 newstate = DSP_TONE_STATE_SPECIAL1; 00983 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 00984 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 00985 newstate = DSP_TONE_STATE_SPECIAL2; 00986 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 00987 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 00988 newstate = DSP_TONE_STATE_SPECIAL3; 00989 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00990 newstate = DSP_TONE_STATE_TALKING; 00991 } else 00992 newstate = DSP_TONE_STATE_SILENCE; 00993 break; 00994 case PROG_MODE_CR: 00995 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 00996 newstate = DSP_TONE_STATE_RINGING; 00997 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00998 newstate = DSP_TONE_STATE_TALKING; 00999 } else 01000 newstate = DSP_TONE_STATE_SILENCE; 01001 break; 01002 case PROG_MODE_UK: 01003 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 01004 newstate = DSP_TONE_STATE_HUNGUP; 01005 } 01006 break; 01007 default: 01008 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01009 } 01010 if (newstate == dsp->tstate) { 01011 dsp->tcount++; 01012 if (dsp->ringtimeout) 01013 dsp->ringtimeout++; 01014 switch (dsp->tstate) { 01015 case DSP_TONE_STATE_RINGING: 01016 if ((dsp->features & DSP_PROGRESS_RINGING) && 01017 (dsp->tcount==THRESH_RING)) { 01018 res = AST_CONTROL_RINGING; 01019 dsp->ringtimeout= 1; 01020 } 01021 break; 01022 case DSP_TONE_STATE_BUSY: 01023 if ((dsp->features & DSP_PROGRESS_BUSY) && 01024 (dsp->tcount==THRESH_BUSY)) { 01025 res = AST_CONTROL_BUSY; 01026 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01027 } 01028 break; 01029 case DSP_TONE_STATE_TALKING: 01030 if ((dsp->features & DSP_PROGRESS_TALK) && 01031 (dsp->tcount==THRESH_TALK)) { 01032 res = AST_CONTROL_ANSWER; 01033 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01034 } 01035 break; 01036 case DSP_TONE_STATE_SPECIAL3: 01037 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01038 (dsp->tcount==THRESH_CONGESTION)) { 01039 res = AST_CONTROL_CONGESTION; 01040 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01041 } 01042 break; 01043 case DSP_TONE_STATE_HUNGUP: 01044 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01045 (dsp->tcount==THRESH_HANGUP)) { 01046 res = AST_CONTROL_HANGUP; 01047 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01048 } 01049 break; 01050 } 01051 if (dsp->ringtimeout==THRESH_RING2ANSWER) { 01052 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 01053 res = AST_CONTROL_ANSWER; 01054 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01055 } 01056 } else { 01057 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01058 ast_debug(5, "Start state %d\n", newstate); 01059 dsp->tstate = newstate; 01060 dsp->tcount = 1; 01061 } 01062 01063 /* Reset goertzel */ 01064 for (x=0;x<7;x++) 01065 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01066 dsp->gsamps = 0; 01067 dsp->genergy = 0.0; 01068 } 01069 } 01070 01071 return res; 01072 }
| static int __ast_dsp_silence_noise | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len, | |||
| int * | totalsilence, | |||
| int * | totalnoise | |||
| ) | [static] |
Definition at line 1087 of file dsp.c.
References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalnoise, and ast_dsp::totalsilence.
Referenced by ast_dsp_noise(), ast_dsp_process(), and ast_dsp_silence().
01088 { 01089 int accum; 01090 int x; 01091 int res = 0; 01092 01093 if (!len) 01094 return 0; 01095 accum = 0; 01096 for (x=0;x<len; x++) 01097 accum += abs(s[x]); 01098 accum /= len; 01099 if (accum < dsp->threshold) { 01100 /* Silent */ 01101 dsp->totalsilence += len/8; 01102 if (dsp->totalnoise) { 01103 /* Move and save history */ 01104 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); 01105 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01106 /* we don't want to check for busydetect that frequently */ 01107 #if 0 01108 dsp->busymaybe = 1; 01109 #endif 01110 } 01111 dsp->totalnoise = 0; 01112 res = 1; 01113 } else { 01114 /* Not silent */ 01115 dsp->totalnoise += len/8; 01116 if (dsp->totalsilence) { 01117 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01118 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01119 /* Move and save history */ 01120 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0])); 01121 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01122 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01123 if (silence1 < silence2) { 01124 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) 01125 dsp->busymaybe = 1; 01126 else 01127 dsp->busymaybe = 0; 01128 } else { 01129 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) 01130 dsp->busymaybe = 1; 01131 else 01132 dsp->busymaybe = 0; 01133 } 01134 } 01135 dsp->totalsilence = 0; 01136 } 01137 if (totalsilence) 01138 *totalsilence = dsp->totalsilence; 01139 if (totalnoise) 01140 *totalnoise = dsp->totalnoise; 01141 return res; 01142 }
| static int _dsp_init | ( | int | reload | ) | [static] |
Definition at line 1618 of file dsp.c.
References ast_config_destroy(), ast_config_load2(), ast_log(), ast_variable_retrieve(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, and THRESHOLD_SILENCE.
Referenced by ast_dsp_init(), and ast_dsp_reload().
01619 { 01620 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01621 struct ast_config *cfg; 01622 01623 cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags); 01624 01625 if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) { 01626 const char *value; 01627 01628 value = ast_variable_retrieve(cfg, "default", "silencethreshold"); 01629 if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) { 01630 ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value); 01631 thresholds[THRESHOLD_SILENCE] = 256; 01632 } else if (!value) 01633 thresholds[THRESHOLD_SILENCE] = 256; 01634 01635 ast_config_destroy(cfg); 01636 } 01637 return 0; 01638 }
| static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
| int | mf | |||
| ) | [static] |
Definition at line 507 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().
00508 { 00509 s->current_digits = 0; 00510 s->detected_digits = 0; 00511 s->lost_digits = 0; 00512 s->digits[0] = '\0'; 00513 00514 if (mf) 00515 ast_mf_detect_init(&s->td.mf); 00516 else 00517 ast_dtmf_detect_init(&s->td.dtmf); 00518 }
| 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 1144 of file dsp.c.
References ast_debug, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, and ast_dsp::historicsilence.
Referenced by ast_dsp_process().
01145 { 01146 int res = 0, x; 01147 #ifndef BUSYDETECT_TONEONLY 01148 int avgsilence = 0, hitsilence = 0; 01149 #endif 01150 int avgtone = 0, hittone = 0; 01151 if (!dsp->busymaybe) 01152 return res; 01153 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01154 #ifndef BUSYDETECT_TONEONLY 01155 avgsilence += dsp->historicsilence[x]; 01156 #endif 01157 avgtone += dsp->historicnoise[x]; 01158 } 01159 #ifndef BUSYDETECT_TONEONLY 01160 avgsilence /= dsp->busycount; 01161 #endif 01162 avgtone /= dsp->busycount; 01163 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01164 #ifndef BUSYDETECT_TONEONLY 01165 if (avgsilence > dsp->historicsilence[x]) { 01166 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01167 hitsilence++; 01168 } else { 01169 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01170 hitsilence++; 01171 } 01172 #endif 01173 if (avgtone > dsp->historicnoise[x]) { 01174 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01175 hittone++; 01176 } else { 01177 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01178 hittone++; 01179 } 01180 } 01181 #ifndef BUSYDETECT_TONEONLY 01182 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01183 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01184 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01185 #else 01186 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01187 #endif 01188 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01189 if (avgtone > avgsilence) { 01190 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01191 res = 1; 01192 } else { 01193 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01194 res = 1; 01195 } 01196 #else 01197 res = 1; 01198 #endif 01199 } 01200 /* If we know the expected busy tone length, check we are in the range */ 01201 if (res && (dsp->busy_tonelength > 0)) { 01202 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01203 #ifdef BUSYDETECT_DEBUG 01204 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01205 avgtone, dsp->busy_tonelength); 01206 #endif 01207 res = 0; 01208 } 01209 } 01210 #ifndef BUSYDETECT_TONEONLY 01211 /* If we know the expected busy tone silent-period length, check we are in the range */ 01212 if (res && (dsp->busy_quietlength > 0)) { 01213 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01214 #ifdef BUSYDETECT_DEBUG 01215 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01216 avgsilence, dsp->busy_quietlength); 01217 #endif 01218 res = 0; 01219 } 01220 } 01221 #endif 01222 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG) 01223 if (res) { 01224 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01225 } else { 01226 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01227 } 01228 #endif 01229 return res; 01230 }
Scans for progress indication in audio.
Definition at line 1074 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.
01075 { 01076 if (inf->frametype != AST_FRAME_VOICE) { 01077 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01078 return 0; 01079 } 01080 if (inf->subclass != AST_FORMAT_SLINEAR) { 01081 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01082 return 0; 01083 } 01084 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); 01085 }
| void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1521 of file dsp.c.
References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, mf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, ast_dsp::dtmf_began, dtmf_detect_state_t::energy, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::misses, dtmf_detect_state_t::row_out, s, digit_detect_state_t::td, and mf_detect_state_t::tone_out.
Referenced by ss_thread().
01522 { 01523 int i; 01524 01525 dsp->dtmf_began = 0; 01526 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01527 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01528 /* Reinitialise the detector for the next block */ 01529 for (i = 0; i < 6; i++) { 01530 goertzel_reset(&s->tone_out[i]); 01531 } 01532 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01533 s->current_sample = 0; 01534 } else { 01535 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01536 /* Reinitialise the detector for the next block */ 01537 for (i = 0; i < 4; i++) { 01538 goertzel_reset(&s->row_out[i]); 01539 goertzel_reset(&s->col_out[i]); 01540 } 01541 s->lasthit = s->current_hit = 0; 01542 s->energy = 0.0; 01543 s->current_sample = 0; 01544 s->hits = 0; 01545 s->misses = 0; 01546 } 01547 01548 dsp->digit_state.digits[0] = '\0'; 01549 dsp->digit_state.current_digits = 0; 01550 }
| 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 1655 of file dsp.c.
References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, ast_dsp::destroy, and f.
Referenced by __frame_free().
01656 { 01657 struct ast_dsp *dsp; 01658 01659 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP); 01660 01661 dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f)); 01662 01663 if (!dsp->destroy) 01664 return; 01665 01666 ast_dsp_free(dsp); 01667 }
| void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1485 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(), destroy_endpoint(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), and unload_module().
01486 { 01487 if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) { 01488 /* If this flag is still set, that means that the dsp's destruction 01489 * been torn down, while we still have a frame out there being used. 01490 * When ast_frfree() gets called on that frame, this ast_trans_pvt 01491 * will get destroyed, too. */ 01492 01493 dsp->destroy = 1; 01494 01495 return; 01496 } 01497 ast_free(dsp); 01498 }
| int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1613 of file dsp.c.
References ast_dsp::tcount.
01614 { 01615 return dsp->tcount; 01616 }
| int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1640 of file dsp.c.
Referenced by app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), and setup_privacy_args().
01641 { 01642 return thresholds[which]; 01643 }
| int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1608 of file dsp.c.
References ast_dsp::tstate.
01609 { 01610 return dsp->tstate; 01611 }
| int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1645 of file dsp.c.
References _dsp_init().
Referenced by main().
01646 { 01647 return _dsp_init(0); 01648 }
| struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1460 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::faxmode, ast_dsp::features, and ast_dsp::threshold.
Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), record_exec(), sip_dtmfmode(), sip_new(), and store_config().
01461 { 01462 struct ast_dsp *dsp; 01463 01464 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01465 dsp->threshold = DEFAULT_THRESHOLD; 01466 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01467 dsp->busycount = DSP_HISTORY; 01468 dsp->digitmode = DSP_DIGITMODE_DTMF; 01469 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01470 /* Initialize digit detector */ 01471 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01472 /* Initialize initial DSP progress detect parameters */ 01473 ast_dsp_prog_reset(dsp); 01474 /* Initialize fax detector */ 01475 ast_fax_detect_init(dsp); 01476 } 01477 return dsp; 01478 }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1250 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, s, and ast_frame::subclass.
Referenced by do_waiting().
01251 { 01252 short *s; 01253 int len; 01254 01255 if (f->frametype != AST_FRAME_VOICE) { 01256 ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); 01257 return 0; 01258 } 01259 if (f->subclass != AST_FORMAT_SLINEAR) { 01260 ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); 01261 return 0; 01262 } 01263 s = f->data.ptr; 01264 len = f->datalen/2; 01265 return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); 01266 }
| struct ast_frame* ast_dsp_process | ( | struct ast_channel * | chan, | |
| struct ast_dsp * | dsp, | |||
| struct ast_frame * | af | |||
| ) | [read] |
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
Definition at line 1269 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, 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_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(), and usbradio_read().
01270 { 01271 int silence; 01272 int res; 01273 int digit = 0, fax_digit = 0; 01274 int x; 01275 short *shortdata; 01276 unsigned char *odata; 01277 int len; 01278 struct ast_frame *outf = NULL; 01279 01280 if (!af) 01281 return NULL; 01282 if (af->frametype != AST_FRAME_VOICE) 01283 return af; 01284 01285 odata = af->data.ptr; 01286 len = af->datalen; 01287 /* Make sure we have short data */ 01288 switch (af->subclass) { 01289 case AST_FORMAT_SLINEAR: 01290 shortdata = af->data.ptr; 01291 len = af->datalen / 2; 01292 break; 01293 case AST_FORMAT_ULAW: 01294 shortdata = alloca(af->datalen * 2); 01295 for (x = 0;x < len; x++) 01296 shortdata[x] = AST_MULAW(odata[x]); 01297 break; 01298 case AST_FORMAT_ALAW: 01299 shortdata = alloca(af->datalen * 2); 01300 for (x = 0; x < len; x++) 01301 shortdata[x] = AST_ALAW(odata[x]); 01302 break; 01303 default: 01304 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01305 return af; 01306 } 01307 01308 /* Initially we do not want to mute anything */ 01309 dsp->mute_fragments = 0; 01310 01311 /* Need to run the silence detection stuff for silence suppression and busy detection */ 01312 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { 01313 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); 01314 } 01315 01316 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01317 memset(&dsp->f, 0, sizeof(dsp->f)); 01318 dsp->f.frametype = AST_FRAME_NULL; 01319 ast_frfree(af); 01320 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01321 return &dsp->f; 01322 } 01323 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01324 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01325 memset(&dsp->f, 0, sizeof(dsp->f)); 01326 dsp->f.frametype = AST_FRAME_CONTROL; 01327 dsp->f.subclass = AST_CONTROL_BUSY; 01328 ast_frfree(af); 01329 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01330 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01331 return &dsp->f; 01332 } 01333 01334 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { 01335 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { 01336 fax_digit = 'f'; 01337 } 01338 01339 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { 01340 fax_digit = 'e'; 01341 } 01342 } 01343 01344 if ((dsp->features & DSP_FEATURE_DIGIT_DETECT)) { 01345 if ((dsp->digitmode & DSP_DIGITMODE_MF)) 01346 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01347 else 01348 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01349 01350 if (dsp->digit_state.current_digits) { 01351 int event = 0; 01352 char event_digit = 0; 01353 01354 if (!dsp->dtmf_began) { 01355 /* We have not reported DTMF_BEGIN for anything yet */ 01356 01357 event = AST_FRAME_DTMF_BEGIN; 01358 event_digit = dsp->digit_state.digits[0]; 01359 dsp->dtmf_began = 1; 01360 01361 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { 01362 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ 01363 01364 event = AST_FRAME_DTMF_END; 01365 event_digit = dsp->digit_state.digits[0]; 01366 memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits); 01367 dsp->digit_state.current_digits--; 01368 dsp->dtmf_began = 0; 01369 } 01370 01371 if (event) { 01372 memset(&dsp->f, 0, sizeof(dsp->f)); 01373 dsp->f.frametype = event; 01374 dsp->f.subclass = event_digit; 01375 outf = &dsp->f; 01376 goto done; 01377 } 01378 } 01379 } 01380 01381 if (fax_digit) { 01382 /* Fax was detected - digit is either 'f' or 'e' */ 01383 01384 memset(&dsp->f, 0, sizeof(dsp->f)); 01385 dsp->f.frametype = AST_FRAME_DTMF; 01386 dsp->f.subclass = fax_digit; 01387 outf = &dsp->f; 01388 goto done; 01389 } 01390 01391 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01392 res = __ast_dsp_call_progress(dsp, shortdata, len); 01393 if (res) { 01394 switch (res) { 01395 case AST_CONTROL_ANSWER: 01396 case AST_CONTROL_BUSY: 01397 case AST_CONTROL_RINGING: 01398 case AST_CONTROL_CONGESTION: 01399 case AST_CONTROL_HANGUP: 01400 memset(&dsp->f, 0, sizeof(dsp->f)); 01401 dsp->f.frametype = AST_FRAME_CONTROL; 01402 dsp->f.subclass = res; 01403 dsp->f.src = "dsp_progress"; 01404 if (chan) 01405 ast_queue_frame(chan, &dsp->f); 01406 break; 01407 default: 01408 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01409 } 01410 } 01411 } 01412 01413 done: 01414 /* Mute fragment of the frame */ 01415 for (x = 0; x < dsp->mute_fragments; x++) { 01416 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); 01417 } 01418 01419 switch (af->subclass) { 01420 case AST_FORMAT_SLINEAR: 01421 break; 01422 case AST_FORMAT_ULAW: 01423 for (x = 0; x < len; x++) 01424 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); 01425 break; 01426 case AST_FORMAT_ALAW: 01427 for (x = 0; x < len; x++) 01428 odata[x] = AST_LIN2A((unsigned short) shortdata[x]); 01429 break; 01430 } 01431 01432 if (outf) { 01433 if (chan) 01434 ast_queue_frame(chan, af); 01435 ast_frfree(af); 01436 ast_set_flag(outf, AST_FRFLAG_FROM_DSP); 01437 return outf; 01438 } else { 01439 return af; 01440 } 01441 }
| static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1443 of file dsp.c.
References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, ast_dsp::ringtimeout, and progress::size.
Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().
01444 { 01445 int max = 0; 01446 int x; 01447 01448 dsp->gsamp_size = modes[dsp->progmode].size; 01449 dsp->gsamps = 0; 01450 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01451 if (modes[dsp->progmode].freqs[x]) { 01452 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01453 max = x + 1; 01454 } 01455 } 01456 dsp->freqcount = max; 01457 dsp->ringtimeout= 0; 01458 }
| int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1650 of file dsp.c.
References _dsp_init().
01651 { 01652 return _dsp_init(1); 01653 }
| void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1552 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.
01553 { 01554 int x; 01555 01556 dsp->totalsilence = 0; 01557 dsp->gsamps = 0; 01558 for (x=0;x<4;x++) 01559 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01560 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01561 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01562 dsp->ringtimeout= 0; 01563 }
| void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
| int | cadences | |||
| ) |
Set number of required cadences for busy.
Definition at line 1505 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01506 { 01507 if (cadences < 4) 01508 cadences = 4; 01509 if (cadences > DSP_HISTORY) 01510 cadences = DSP_HISTORY; 01511 dsp->busycount = cadences; 01512 }
| void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
| int | tonelength, | |||
| int | quietlength | |||
| ) |
Set expected lengths of the busy tone.
Definition at line 1514 of file dsp.c.
References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.
Referenced by dahdi_new().
01515 { 01516 dsp->busy_tonelength = tonelength; 01517 dsp->busy_quietlength = quietlength; 01518 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01519 }
| int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
| char * | zone | |||
| ) |
Set zone for doing progress detection.
Definition at line 1589 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
| int ast_dsp_set_digitmode | ( | struct ast_dsp * | dsp, | |
| int | digitmode | |||
| ) |
Set digit mode.
Definition at line 1565 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(), mkintf(), sip_new(), ss_thread(), and store_config().
01566 { 01567 int new; 01568 int old; 01569 01570 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01571 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01572 if (old != new) { 01573 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01574 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01575 } 01576 dsp->digitmode = digitmode; 01577 return 0; 01578 }
| int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
| int | faxmode | |||
| ) |
Set fax mode.
Definition at line 1580 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01581 { 01582 if (dsp->faxmode != faxmode) { 01583 ast_fax_detect_init(dsp); 01584 } 01585 dsp->faxmode = faxmode; 01586 return 0; 01587 }
| void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
| int | features | |||
| ) |
Select feature set.
Definition at line 1480 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(), pri_dchannel(), read_config(), sip_dtmfmode(), sip_new(), ss7_linkset(), and store_config().
01481 { 01482 dsp->features = features; 01483 }
| void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
| int | threshold | |||
| ) |
Set threshold value for silence.
Definition at line 1500 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1232 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, s, and ast_frame::subclass.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
01233 { 01234 short *s; 01235 int len; 01236 01237 if (f->frametype != AST_FRAME_VOICE) { 01238 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01239 return 0; 01240 } 01241 if (f->subclass != AST_FORMAT_SLINEAR) { 01242 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01243 return 0; 01244 } 01245 s = f->data.ptr; 01246 len = f->datalen/2; 01247 return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); 01248 }
| 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 1603 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
01604 { 01605 return (dsp->mute_fragments > 0); 01606 }
| static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 477 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().
00478 { 00479 int i; 00480 00481 s->lasthit = 0; 00482 s->current_hit = 0; 00483 for (i = 0; i < 4; i++) { 00484 goertzel_init (&s->row_out[i], dtmf_row[i], DTMF_GSIZE); 00485 goertzel_init (&s->col_out[i], dtmf_col[i], DTMF_GSIZE); 00486 s->energy = 0.0; 00487 } 00488 s->current_sample = 0; 00489 s->hits = 0; 00490 s->misses = 0; 00491 00492 s->hits_to_begin = DTMF_HITS_TO_BEGIN; 00493 s->misses_to_end = DTMF_MISSES_TO_END; 00494 }
| static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 471 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().
00472 { 00473 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00474 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00475 }
| static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 496 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().
00497 { 00498 int i; 00499 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00500 for (i = 0; i < 6; i++) { 00501 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00502 } 00503 s->current_sample = 0; 00504 s->current_hit = 0; 00505 }
| static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
| int | freq, | |||
| int | duration, | |||
| int | amp | |||
| ) | [static] |
Definition at line 411 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().
00412 { 00413 int duration_samples; 00414 float x; 00415 int periods_in_block; 00416 00417 s->freq = freq; 00418 00419 /* Desired tone duration in samples */ 00420 duration_samples = duration * SAMPLE_RATE / 1000; 00421 /* We want to allow 10% deviation of tone duration */ 00422 duration_samples = duration_samples * 9 / 10; 00423 00424 /* If we want to remove tone, it is important to have block size not 00425 to exceed frame size. Otherwise by the moment tone is detected it is too late 00426 to squelch it from previous frames */ 00427 s->block_size = SAMPLES_IN_FRAME; 00428 00429 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00430 00431 /* Make sure we will have at least 5 periods at target frequency for analisys. 00432 This may make block larger than expected packet and will make squelching impossible 00433 but at least we will be detecting the tone */ 00434 if (periods_in_block < 5) 00435 periods_in_block = 5; 00436 00437 /* Now calculate final block size. It will contain integer number of periods */ 00438 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00439 00440 /* tone_detect is currently only used to detect fax tones and we 00441 do not need suqlching the fax tones */ 00442 s->squelch = 0; 00443 00444 /* Account for the first and the last block to be incomplete 00445 and thus no tone will be detected in them */ 00446 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00447 00448 goertzel_init(&s->tone, freq, s->block_size); 00449 00450 s->samples_pending = s->block_size; 00451 s->hit_count = 0; 00452 s->last_hit = 0; 00453 s->energy = 0.0; 00454 00455 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00456 According to Parseval's theorem the energy computed in time domain equals to energy 00457 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00458 from the energy in the time domain we will get energy of the remaining signal (without the tone 00459 we are detecting). We will be checking that 00460 10*log(Ew / (Et - Ew)) > amp 00461 Calculate threshold so that we will be actually checking 00462 Ew > Et * threshold 00463 */ 00464 00465 x = pow(10.0, amp / 10.0); 00466 s->threshold = x / (x + 1); 00467 00468 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00469 }
| 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 634 of file dsp.c.
References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, 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, fragment_t::end, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), 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, mute_fragment(), dtmf_detect_state_t::mute_samples, dtmf_detect_state_t::row_out, fragment_t::start, store_digit(), and digit_detect_state_t::td.
Referenced by ast_dsp_process().
00635 { 00636 float row_energy[4]; 00637 float col_energy[4]; 00638 float famp; 00639 int i; 00640 int j; 00641 int sample; 00642 int best_row; 00643 int best_col; 00644 int hit; 00645 int limit; 00646 fragment_t mute = {0, 0}; 00647 00648 if (squelch && s->td.dtmf.mute_samples > 0) { 00649 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples; 00650 s->td.dtmf.mute_samples -= mute.end; 00651 } 00652 00653 hit = 0; 00654 for (sample = 0; sample < samples; sample = limit) { 00655 /* DTMF_GSIZE is optimised to meet the DTMF specs. */ 00656 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) 00657 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample); 00658 else 00659 limit = samples; 00660 /* The following unrolled loop takes only 35% (rough estimate) of the 00661 time of a rolled loop on the machine on which it was developed */ 00662 for (j = sample; j < limit; j++) { 00663 famp = amp[j]; 00664 s->td.dtmf.energy += famp*famp; 00665 /* With GCC 2.95, the following unrolled code seems to take about 35% 00666 (rough estimate) as long as a neat little 0-3 loop */ 00667 goertzel_sample(s->td.dtmf.row_out, amp[j]); 00668 goertzel_sample(s->td.dtmf.col_out, amp[j]); 00669 goertzel_sample(s->td.dtmf.row_out + 1, amp[j]); 00670 goertzel_sample(s->td.dtmf.col_out + 1, amp[j]); 00671 goertzel_sample(s->td.dtmf.row_out + 2, amp[j]); 00672 goertzel_sample(s->td.dtmf.col_out + 2, amp[j]); 00673 goertzel_sample(s->td.dtmf.row_out + 3, amp[j]); 00674 goertzel_sample(s->td.dtmf.col_out + 3, amp[j]); 00675 } 00676 s->td.dtmf.current_sample += (limit - sample); 00677 if (s->td.dtmf.current_sample < DTMF_GSIZE) { 00678 continue; 00679 } 00680 /* We are at the end of a DTMF detection block */ 00681 /* Find the peak row and the peak column */ 00682 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00683 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00684 00685 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00686 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00687 if (row_energy[i] > row_energy[best_row]) 00688 best_row = i; 00689 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00690 if (col_energy[i] > col_energy[best_col]) 00691 best_col = i; 00692 } 00693 hit = 0; 00694 /* Basic signal level test and the twist test */ 00695 if (row_energy[best_row] >= DTMF_THRESHOLD && 00696 col_energy[best_col] >= DTMF_THRESHOLD && 00697 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00698 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00699 /* Relative peak test */ 00700 for (i = 0; i < 4; i++) { 00701 if ((i != best_col && 00702 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00703 (i != best_row 00704 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00705 break; 00706 } 00707 } 00708 /* ... and fraction of total energy test */ 00709 if (i >= 4 && 00710 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy) { 00711 /* Got a hit */ 00712 hit = dtmf_positions[(best_row << 2) + best_col]; 00713 } 00714 } 00715 00716 if (s->td.dtmf.current_hit) { 00717 /* We are in the middle of a digit already */ 00718 if (hit != s->td.dtmf.current_hit) { 00719 s->td.dtmf.misses++; 00720 if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) { 00721 /* There were enough misses to consider digit ended */ 00722 s->td.dtmf.current_hit = 0; 00723 } 00724 } else { 00725 s->td.dtmf.misses = 0; 00726 } 00727 } 00728 00729 /* Look for a start of a new digit no matter if we are already in the middle of some 00730 digit or not. This is because hits_to_begin may be smaller than misses_to_end 00731 and we may find begin of new digit before we consider last one ended. */ 00732 if (hit) { 00733 if (hit == s->td.dtmf.lasthit) { 00734 s->td.dtmf.hits++; 00735 } else { 00736 s->td.dtmf.hits = 1; 00737 } 00738 00739 if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin && hit != s->td.dtmf.current_hit) { 00740 store_digit(s, hit); 00741 s->td.dtmf.current_hit = hit; 00742 s->td.dtmf.misses = 0; 00743 } 00744 } else { 00745 s->td.dtmf.hits = 0; 00746 } 00747 00748 s->td.dtmf.lasthit = hit; 00749 00750 /* If we had a hit in this block, include it into mute fragment */ 00751 if (squelch && hit) { 00752 if (mute.end < sample - DTMF_GSIZE) { 00753 /* There is a gap between fragments */ 00754 mute_fragment(dsp, &mute); 00755 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0; 00756 } 00757 mute.end = limit + DTMF_GSIZE; 00758 } 00759 00760 /* Reinitialise the detector for the next block */ 00761 for (i = 0; i < 4; i++) { 00762 goertzel_reset(&s->td.dtmf.row_out[i]); 00763 goertzel_reset(&s->td.dtmf.col_out[i]); 00764 } 00765 s->td.dtmf.energy = 0.0; 00766 s->td.dtmf.current_sample = 0; 00767 } 00768 00769 if (squelch && mute.end) { 00770 if (mute.end > samples) { 00771 s->td.dtmf.mute_samples = mute.end - samples; 00772 mute.end = samples; 00773 } 00774 mute_fragment(dsp, &mute); 00775 } 00776 00777 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00778 }
| static void goertzel_init | ( | goertzel_state_t * | s, | |
| float | freq, | |||
| int | samples | |||
| ) | [inline, static] |
Definition at line 339 of file dsp.c.
References goertzel_state_t::chunky, cos, goertzel_state_t::fac, SAMPLE_RATE, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().
| static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 346 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_digitreset(), dtmf_detect(), mf_detect(), and tone_detect().
| static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 330 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_result_t::power, goertzel_state_t::v2, goertzel_state_t::v3, and goertzel_result_t::value.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), mf_detect(), and tone_detect().
| static void goertzel_sample | ( | goertzel_state_t * | s, | |
| short | sample | |||
| ) | [inline, static] |
Definition at line 304 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), goertzel_update(), mf_detect(), and tone_detect().
| static void goertzel_update | ( | goertzel_state_t * | s, | |
| short * | samps, | |||
| int | count | |||
| ) | [inline, static] |
Definition at line 321 of file dsp.c.
References goertzel_sample().
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 780 of file dsp.c.
References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, DTMF_GSIZE, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute_fragment(), mf_detect_state_t::mute_samples, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.
Referenced by ast_dsp_process().
00782 { 00783 float energy[6]; 00784 int best; 00785 int second_best; 00786 float famp; 00787 int i; 00788 int j; 00789 int sample; 00790 int hit; 00791 int limit; 00792 fragment_t mute = {0, 0}; 00793 00794 if (squelch && s->td.mf.mute_samples > 0) { 00795 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples; 00796 s->td.mf.mute_samples -= mute.end; 00797 } 00798 00799 hit = 0; 00800 for (sample = 0; sample < samples; sample = limit) { 00801 /* 80 is optimised to meet the MF specs. */ 00802 /* XXX So then why is MF_GSIZE defined as 120? */ 00803 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) 00804 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00805 else 00806 limit = samples; 00807 /* The following unrolled loop takes only 35% (rough estimate) of the 00808 time of a rolled loop on the machine on which it was developed */ 00809 for (j = sample; j < limit; j++) { 00810 famp = amp[j]; 00811 /* With GCC 2.95, the following unrolled code seems to take about 35% 00812 (rough estimate) as long as a neat little 0-3 loop */ 00813 goertzel_sample(s->td.mf.tone_out, amp[j]); 00814 goertzel_sample(s->td.mf.tone_out + 1, amp[j]); 00815 goertzel_sample(s->td.mf.tone_out + 2, amp[j]); 00816 goertzel_sample(s->td.mf.tone_out + 3, amp[j]); 00817 goertzel_sample(s->td.mf.tone_out + 4, amp[j]); 00818 goertzel_sample(s->td.mf.tone_out + 5, amp[j]); 00819 } 00820 s->td.mf.current_sample += (limit - sample); 00821 if (s->td.mf.current_sample < MF_GSIZE) { 00822 continue; 00823 } 00824 /* We're at the end of an MF detection block. */ 00825 /* Find the two highest energies. The spec says to look for 00826 two tones and two tones only. Taking this literally -ie 00827 only two tones pass the minimum threshold - doesn't work 00828 well. The sinc function mess, due to rectangular windowing 00829 ensure that! Find the two highest energies and ensure they 00830 are considerably stronger than any of the others. */ 00831 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00832 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00833 if (energy[0] > energy[1]) { 00834 best = 0; 00835 second_best = 1; 00836 } else { 00837 best = 1; 00838 second_best = 0; 00839 } 00840 /*endif*/ 00841 for (i=2;i<6;i++) { 00842 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00843 if (energy[i] >= energy[best]) { 00844 second_best = best; 00845 best = i; 00846 } else if (energy[i] >= energy[second_best]) { 00847 second_best = i; 00848 } 00849 } 00850 /* Basic signal level and twist tests */ 00851 hit = 0; 00852 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00853 && energy[best] < energy[second_best]*BELL_MF_TWIST 00854 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00855 /* Relative peak test */ 00856 hit = -1; 00857 for (i=0;i<6;i++) { 00858 if (i != best && i != second_best) { 00859 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00860 /* The best two are not clearly the best */ 00861 hit = 0; 00862 break; 00863 } 00864 } 00865 } 00866 } 00867 if (hit) { 00868 /* Get the values into ascending order */ 00869 if (second_best < best) { 00870 i = best; 00871 best = second_best; 00872 second_best = i; 00873 } 00874 best = best*5 + second_best - 1; 00875 hit = bell_mf_positions[best]; 00876 /* Look for two successive similar results */ 00877 /* The logic in the next test is: 00878 For KP we need 4 successive identical clean detects, with 00879 two blocks of something different preceeding it. For anything 00880 else we need two successive identical clean detects, with 00881 two blocks of something different preceeding it. */ 00882 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00883 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00884 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00885 hit != s->td.mf.hits[0]))) { 00886 store_digit(s, hit); 00887 } 00888 } 00889 00890 00891 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00892 /* Two successive block without a hit terminate current digit */ 00893 s->td.mf.current_hit = 0; 00894 } 00895 00896 s->td.mf.hits[0] = s->td.mf.hits[1]; 00897 s->td.mf.hits[1] = s->td.mf.hits[2]; 00898 s->td.mf.hits[2] = s->td.mf.hits[3]; 00899 s->td.mf.hits[3] = s->td.mf.hits[4]; 00900 s->td.mf.hits[4] = hit; 00901 00902 /* If we had a hit in this block, include it into mute fragment */ 00903 if (squelch && hit) { 00904 if (mute.end < sample - MF_GSIZE) { 00905 /* There is a gap between fragments */ 00906 mute_fragment(dsp, &mute); 00907 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0; 00908 } 00909 mute.end = limit + DTMF_GSIZE; 00910 } 00911 00912 /* Reinitialise the detector for the next block */ 00913 for (i = 0; i < 6; i++) 00914 goertzel_reset(&s->td.mf.tone_out[i]); 00915 s->td.mf.current_sample = 0; 00916 } 00917 00918 if (squelch && mute.end) { 00919 if (mute.end > samples) { 00920 s->td.mf.mute_samples = mute.end - samples; 00921 mute.end = samples; 00922 } 00923 mute_fragment(dsp, &mute); 00924 } 00925 00926 return (s->td.mf.current_hit); /* return the debounced hit */ 00927 }
| static void mute_fragment | ( | struct ast_dsp * | dsp, | |
| fragment_t * | fragment | |||
| ) | [static] |
Definition at line 401 of file dsp.c.
References ARRAY_LEN, ast_log(), LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.
Referenced by dtmf_detect(), mf_detect(), and tone_detect().
00402 { 00403 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) { 00404 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n"); 00405 return; 00406 } 00407 00408 dsp->mute_data[dsp->mute_fragments++] = *fragment; 00409 }
| static int pair_there | ( | float | p1, | |
| float | p2, | |||
| float | i1, | |||
| float | i2, | |||
| float | e | |||
| ) | [inline, static] |
Definition at line 929 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00930 { 00931 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00932 /* Make sure absolute levels are high enough */ 00933 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 00934 return 0; 00935 /* Amplify ignored stuff */ 00936 i2 *= TONE_THRESH; 00937 i1 *= TONE_THRESH; 00938 e *= TONE_THRESH; 00939 /* Check first tone */ 00940 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 00941 return 0; 00942 /* And second */ 00943 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 00944 return 0; 00945 /* Guess it's there... */ 00946 return 1; 00947 }
| static void store_digit | ( | digit_detect_state_t * | s, | |
| char | digit | |||
| ) | [static] |
Definition at line 622 of file dsp.c.
References ast_log(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, LOG_WARNING, digit_detect_state_t::lost_digits, and MAX_DTMF_DIGITS.
Referenced by dtmf_detect(), and mf_detect().
00623 { 00624 s->detected_digits++; 00625 if (s->current_digits < MAX_DTMF_DIGITS) { 00626 s->digits[s->current_digits++] = digit; 00627 s->digits[s->current_digits] = '\0'; 00628 } else { 00629 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00630 s->lost_digits++; 00631 } 00632 }
| static int tone_detect | ( | struct ast_dsp * | dsp, | |
| tone_detect_state_t * | s, | |||
| int16_t * | amp, | |||
| int | samples | |||
| ) | [static] |
Definition at line 520 of file dsp.c.
References ast_debug, tone_detect_state_t::block_size, fragment_t::end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute_fragment(), tone_detect_state_t::mute_samples, ast_frame::ptr, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, and tone_detect_state_t::tone.
Referenced by ast_dsp_process().
00521 { 00522 float tone_energy; 00523 int i; 00524 int hit = 0; 00525 int limit; 00526 int res = 0; 00527 int16_t *ptr; 00528 int start, end; 00529 fragment_t mute = {0, 0}; 00530 00531 if (s->squelch && s->mute_samples > 0) { 00532 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples; 00533 s->mute_samples -= mute.end; 00534 } 00535 00536 for (start = 0; start < samples; start = end) { 00537 /* Process in blocks. */ 00538 limit = samples - start; 00539 if (limit > s->samples_pending) 00540 limit = s->samples_pending; 00541 end = start + limit; 00542 00543 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00544 /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ 00545 s->energy += (int32_t) *ptr * (int32_t) *ptr; 00546 00547 goertzel_sample(&s->tone, *ptr); 00548 } 00549 00550 s->samples_pending -= limit; 00551 00552 if (s->samples_pending) { 00553 /* Finished incomplete (last) block */ 00554 break; 00555 } 00556 00557 tone_energy = goertzel_result(&s->tone); 00558 00559 /* Scale to make comparable */ 00560 tone_energy *= 2.0; 00561 s->energy *= s->block_size; 00562 00563 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)); 00564 hit = 0; 00565 if (tone_energy > s->energy * s->threshold) { 00566 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00567 hit = 1; 00568 } 00569 00570 if (s->hit_count) 00571 s->hit_count++; 00572 00573 if (hit == s->last_hit) { 00574 if (!hit) { 00575 /* Two successive misses. Tone ended */ 00576 s->hit_count = 0; 00577 } else if (!s->hit_count) { 00578 s->hit_count++; 00579 } 00580 00581 } 00582 00583 if (s->hit_count == s->hits_required) { 00584 ast_debug(1, "%d Hz done detected\n", s->freq); 00585 res = 1; 00586 } 00587 00588 s->last_hit = hit; 00589 00590 /* If we had a hit in this block, include it into mute fragment */ 00591 if (s->squelch && hit) { 00592 if (mute.end < start - s->block_size) { 00593 /* There is a gap between fragments */ 00594 mute_fragment(dsp, &mute); 00595 mute.start = (start > s->block_size) ? (start - s->block_size) : 0; 00596 } 00597 mute.end = end + s->block_size; 00598 } 00599 00600 /* Reinitialise the detector for the next block */ 00601 /* Reset for the next block */ 00602 goertzel_reset(&s->tone); 00603 00604 /* Advance to the next block */ 00605 s->energy = 0.0; 00606 s->samples_pending = s->block_size; 00607 00608 amp += limit; 00609 } 00610 00611 if (s->squelch && mute.end) { 00612 if (mute.end > samples) { 00613 s->mute_samples = mute.end - samples; 00614 mute.end = samples; 00615 } 00616 mute_fragment(dsp, &mute); 00617 } 00618 00619 return res; 00620 }
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] |
1.6.1