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