#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_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 const char | bell_mf_positions [] = "1247C-358A--69*---0B----#" |
| static const int | DEFAULT_SILENCE_THRESHOLD = 256 |
| The default silence threshold we will use if an alternate configured value is not present or is invalid. | |
| static const float | dtmf_col [] |
| static const char | dtmf_positions [] = "123A" "456B" "789C" "*0#D" |
| static const float | dtmf_row [] |
| static const float | mf_tones [] |
| static struct progress | modes [] |
| static int | thresholds [THRESHOLD_MAX] |
Definition in file dsp.c.
| #define BELL_MF_RELATIVE_PEAK 12.6 |
| #define BELL_MF_THRESHOLD 1.6e9 |
| #define BELL_MF_TWIST 4.0 |
| #define DEFAULT_THRESHOLD 512 |
This value is the minimum threshold, calculated by averaging all of the samples within a frame, for which a frame is determined to either be silence (below the threshold) or noise (above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will accept any value between 0 and 32767.
Definition at line 117 of file dsp.c.
Referenced by ast_dsp_new().
| #define DSP_HISTORY 15 |
Remember last 15 units
Definition at line 128 of file dsp.c.
Referenced by __ast_dsp_silence_noise(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().
| #define DTMF_GSIZE 102 |
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 |
| #define DTMF_MISSES_TO_END 3 |
| #define DTMF_NORMAL_TWIST 6.3 |
| #define DTMF_RELATIVE_PEAK_COL 6.3 |
| #define DTMF_RELATIVE_PEAK_ROW 6.3 |
| #define DTMF_REVERSE_TWIST (relax ? 4.0 : 2.5) |
| #define DTMF_THRESHOLD 8.0e7 |
| #define DTMF_TO_TOTAL_ENERGY 42.0 |
| #define FAX_TONE_CED_DB 16 |
| #define FAX_TONE_CED_DURATION 2600 |
| #define FAX_TONE_CED_FREQ 2100 |
| #define FAX_TONE_CNG_DB 16 |
| #define FAX_TONE_CNG_DURATION 500 |
| #define FAX_TONE_CNG_FREQ 1100 |
| #define MAX_DTMF_DIGITS 128 |
| #define MF_GSIZE 120 |
| #define SAMPLES_IN_FRAME 160 |
| #define TONE_MIN_THRESH 1e8 |
How much tone there should be at least to attempt
Definition at line 131 of file dsp.c.
Referenced by __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 |
| 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 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 |
| HZ_350 | For US modes { |
| HZ_440 | |
| HZ_480 | |
| HZ_620 | |
| HZ_950 | |
| HZ_1400 | |
| HZ_1800 | } |
| HZ_425 | For CR/BR modes |
| HZ_350UK | For UK mode |
| HZ_400UK | |
| HZ_440UK |
Definition at line 71 of file dsp.c.
00071 { 00072 /*! For US modes { */ 00073 HZ_350 = 0, 00074 HZ_440, 00075 HZ_480, 00076 HZ_620, 00077 HZ_950, 00078 HZ_1400, 00079 HZ_1800, /*!< } */ 00080 00081 /*! For CR/BR modes */ 00082 HZ_425 = 0, 00083 00084 /*! For UK mode */ 00085 HZ_350UK = 0, 00086 HZ_400UK, 00087 HZ_440UK 00088 };
| enum gsamp_size |
Number of goertzels for progress detect
| GSAMP_SIZE_NA | North America - 350, 440, 480, 620, 950, 1400, 1800 Hz |
| GSAMP_SIZE_CR | Costa Rica, Brazil - Only care about 425 Hz |
| GSAMP_SIZE_UK | UK disconnect goertzel feed - should trigger 400hz |
Definition at line 59 of file dsp.c.
00059 { 00060 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ 00061 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */ 00062 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */ 00063 };
| enum gsamp_thresh |
All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)
Definition at line 134 of file dsp.c.
00134 { 00135 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */ 00136 THRESH_TALK = 2, /*!< Talk detection does not work continuously */ 00137 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */ 00138 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */ 00139 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */ 00140 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */ 00141 };
| enum prog_mode |
Definition at line 65 of file dsp.c.
00065 { 00066 PROG_MODE_NA = 0, 00067 PROG_MODE_CR, 00068 PROG_MODE_UK 00069 };
| static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len | |||
| ) | [static] |
Definition at line 965 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().
00966 { 00967 int x; 00968 int y; 00969 int pass; 00970 int newstate = DSP_TONE_STATE_SILENCE; 00971 int res = 0; 00972 while (len) { 00973 /* Take the lesser of the number of samples we need and what we have */ 00974 pass = len; 00975 if (pass > dsp->gsamp_size - dsp->gsamps) { 00976 pass = dsp->gsamp_size - dsp->gsamps; 00977 } 00978 for (x = 0; x < pass; x++) { 00979 for (y = 0; y < dsp->freqcount; y++) { 00980 goertzel_sample(&dsp->freqs[y], s[x]); 00981 } 00982 dsp->genergy += s[x] * s[x]; 00983 } 00984 s += pass; 00985 dsp->gsamps += pass; 00986 len -= pass; 00987 if (dsp->gsamps == dsp->gsamp_size) { 00988 float hz[7]; 00989 for (y = 0; y < 7; y++) { 00990 hz[y] = goertzel_result(&dsp->freqs[y]); 00991 } 00992 switch (dsp->progmode) { 00993 case PROG_MODE_NA: 00994 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 00995 newstate = DSP_TONE_STATE_BUSY; 00996 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 00997 newstate = DSP_TONE_STATE_RINGING; 00998 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 00999 newstate = DSP_TONE_STATE_DIALTONE; 01000 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01001 newstate = DSP_TONE_STATE_SPECIAL1; 01002 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01003 /* End of SPECIAL1 or middle of SPECIAL2 */ 01004 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) { 01005 newstate = DSP_TONE_STATE_SPECIAL2; 01006 } 01007 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01008 /* End of SPECIAL2 or middle of SPECIAL3 */ 01009 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01010 newstate = DSP_TONE_STATE_SPECIAL3; 01011 } 01012 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01013 newstate = DSP_TONE_STATE_TALKING; 01014 } else { 01015 newstate = DSP_TONE_STATE_SILENCE; 01016 } 01017 break; 01018 case PROG_MODE_CR: 01019 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01020 newstate = DSP_TONE_STATE_RINGING; 01021 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01022 newstate = DSP_TONE_STATE_TALKING; 01023 } else { 01024 newstate = DSP_TONE_STATE_SILENCE; 01025 } 01026 break; 01027 case PROG_MODE_UK: 01028 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { 01029 newstate = DSP_TONE_STATE_HUNGUP; 01030 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { 01031 newstate = DSP_TONE_STATE_DIALTONE; 01032 } 01033 break; 01034 default: 01035 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01036 } 01037 if (newstate == dsp->tstate) { 01038 dsp->tcount++; 01039 if (dsp->ringtimeout) { 01040 dsp->ringtimeout++; 01041 } 01042 switch (dsp->tstate) { 01043 case DSP_TONE_STATE_RINGING: 01044 if ((dsp->features & DSP_PROGRESS_RINGING) && 01045 (dsp->tcount == THRESH_RING)) { 01046 res = AST_CONTROL_RINGING; 01047 dsp->ringtimeout = 1; 01048 } 01049 break; 01050 case DSP_TONE_STATE_BUSY: 01051 if ((dsp->features & DSP_PROGRESS_BUSY) && 01052 (dsp->tcount == THRESH_BUSY)) { 01053 res = AST_CONTROL_BUSY; 01054 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01055 } 01056 break; 01057 case DSP_TONE_STATE_TALKING: 01058 if ((dsp->features & DSP_PROGRESS_TALK) && 01059 (dsp->tcount == THRESH_TALK)) { 01060 res = AST_CONTROL_ANSWER; 01061 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01062 } 01063 break; 01064 case DSP_TONE_STATE_SPECIAL3: 01065 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01066 (dsp->tcount == THRESH_CONGESTION)) { 01067 res = AST_CONTROL_CONGESTION; 01068 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01069 } 01070 break; 01071 case DSP_TONE_STATE_HUNGUP: 01072 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01073 (dsp->tcount == THRESH_HANGUP)) { 01074 res = AST_CONTROL_HANGUP; 01075 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01076 } 01077 break; 01078 } 01079 if (dsp->ringtimeout == THRESH_RING2ANSWER) { 01080 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 01081 res = AST_CONTROL_ANSWER; 01082 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01083 } 01084 } else { 01085 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01086 ast_debug(5, "Start state %d\n", newstate); 01087 dsp->tstate = newstate; 01088 dsp->tcount = 1; 01089 } 01090 01091 /* Reset goertzel */ 01092 for (x = 0; x < 7; x++) { 01093 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01094 } 01095 dsp->gsamps = 0; 01096 dsp->genergy = 0.0; 01097 } 01098 } 01099 01100 return res; 01101 }
| static int __ast_dsp_silence_noise | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len, | |||
| int * | totalsilence, | |||
| int * | totalnoise | |||
| ) | [static] |
Definition at line 1116 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().
01117 { 01118 int accum; 01119 int x; 01120 int res = 0; 01121 01122 if (!len) { 01123 return 0; 01124 } 01125 accum = 0; 01126 for (x = 0; x < len; x++) { 01127 accum += abs(s[x]); 01128 } 01129 accum /= len; 01130 if (accum < dsp->threshold) { 01131 /* Silent */ 01132 dsp->totalsilence += len / 8; 01133 if (dsp->totalnoise) { 01134 /* Move and save history */ 01135 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0])); 01136 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01137 /* we don't want to check for busydetect that frequently */ 01138 #if 0 01139 dsp->busymaybe = 1; 01140 #endif 01141 } 01142 dsp->totalnoise = 0; 01143 res = 1; 01144 } else { 01145 /* Not silent */ 01146 dsp->totalnoise += len / 8; 01147 if (dsp->totalsilence) { 01148 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01149 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01150 /* Move and save history */ 01151 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0])); 01152 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01153 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01154 if (silence1 < silence2) { 01155 if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) { 01156 dsp->busymaybe = 1; 01157 } else { 01158 dsp->busymaybe = 0; 01159 } 01160 } else { 01161 if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) { 01162 dsp->busymaybe = 1; 01163 } else { 01164 dsp->busymaybe = 0; 01165 } 01166 } 01167 } 01168 dsp->totalsilence = 0; 01169 } 01170 if (totalsilence) { 01171 *totalsilence = dsp->totalsilence; 01172 } 01173 if (totalnoise) { 01174 *totalnoise = dsp->totalnoise; 01175 } 01176 return res; 01177 }
| static int _dsp_init | ( | int | reload | ) | [static] |
Definition at line 1677 of file dsp.c.
References ast_config_destroy(), ast_config_load2(), ast_variable_retrieve(), ast_verb, CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, THRESHOLD_SILENCE, and value.
Referenced by ast_dsp_init(), and ast_dsp_reload().
01678 { 01679 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01680 struct ast_config *cfg; 01681 01682 cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags); 01683 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 01684 ast_verb(5, "Can't find dsp config file %s. Assuming default silencethreshold of %d.\n", CONFIG_FILE_NAME, DEFAULT_SILENCE_THRESHOLD); 01685 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01686 return 0; 01687 } 01688 01689 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 01690 return 0; 01691 } 01692 01693 if (cfg) { 01694 const char *value; 01695 01696 value = ast_variable_retrieve(cfg, "default", "silencethreshold"); 01697 if (value && sscanf(value, "%30d", &thresholds[THRESHOLD_SILENCE]) != 1) { 01698 ast_verb(5, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value); 01699 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01700 } else if (!value) { 01701 thresholds[THRESHOLD_SILENCE] = DEFAULT_SILENCE_THRESHOLD; 01702 } 01703 01704 ast_config_destroy(cfg); 01705 } 01706 return 0; 01707 }
| static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
| int | mf | |||
| ) | [static] |
Definition at line 510 of file dsp.c.
References ast_dtmf_detect_init(), ast_mf_detect_init(), 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().
00511 { 00512 s->current_digits = 0; 00513 s->detected_digits = 0; 00514 s->lost_digits = 0; 00515 s->digits[0] = '\0'; 00516 00517 if (mf) { 00518 ast_mf_detect_init(&s->td.mf); 00519 } else { 00520 ast_dtmf_detect_init(&s->td.dtmf); 00521 } 00522 }
| 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 1179 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().
01180 { 01181 int res = 0, x; 01182 #ifndef BUSYDETECT_TONEONLY 01183 int avgsilence = 0, hitsilence = 0; 01184 #endif 01185 int avgtone = 0, hittone = 0; 01186 if (!dsp->busymaybe) { 01187 return res; 01188 } 01189 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01190 #ifndef BUSYDETECT_TONEONLY 01191 avgsilence += dsp->historicsilence[x]; 01192 #endif 01193 avgtone += dsp->historicnoise[x]; 01194 } 01195 #ifndef BUSYDETECT_TONEONLY 01196 avgsilence /= dsp->busycount; 01197 #endif 01198 avgtone /= dsp->busycount; 01199 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { 01200 #ifndef BUSYDETECT_TONEONLY 01201 if (avgsilence > dsp->historicsilence[x]) { 01202 if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) { 01203 hitsilence++; 01204 } 01205 } else { 01206 if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) { 01207 hitsilence++; 01208 } 01209 } 01210 #endif 01211 if (avgtone > dsp->historicnoise[x]) { 01212 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) { 01213 hittone++; 01214 } 01215 } else { 01216 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) { 01217 hittone++; 01218 } 01219 } 01220 } 01221 #ifndef BUSYDETECT_TONEONLY 01222 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01223 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01224 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01225 #else 01226 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01227 #endif 01228 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01229 if (avgtone > avgsilence) { 01230 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) { 01231 res = 1; 01232 } 01233 } else { 01234 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) { 01235 res = 1; 01236 } 01237 } 01238 #else 01239 res = 1; 01240 #endif 01241 } 01242 /* If we know the expected busy tone length, check we are in the range */ 01243 if (res && (dsp->busy_tonelength > 0)) { 01244 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01245 #ifdef BUSYDETECT_DEBUG 01246 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01247 avgtone, dsp->busy_tonelength); 01248 #endif 01249 res = 0; 01250 } 01251 } 01252 #ifndef BUSYDETECT_TONEONLY 01253 /* If we know the expected busy tone silent-period length, check we are in the range */ 01254 if (res && (dsp->busy_quietlength > 0)) { 01255 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01256 #ifdef BUSYDETECT_DEBUG 01257 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01258 avgsilence, dsp->busy_quietlength); 01259 #endif 01260 res = 0; 01261 } 01262 } 01263 #endif 01264 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG) 01265 if (res) { 01266 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01267 } else { 01268 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01269 } 01270 #endif 01271 return res; 01272 }
Scans for progress indication in audio.
Definition at line 1103 of file dsp.c.
References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
01104 { 01105 if (inf->frametype != AST_FRAME_VOICE) { 01106 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01107 return 0; 01108 } 01109 if (inf->subclass.codec != AST_FORMAT_SLINEAR) { 01110 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01111 return 0; 01112 } 01113 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); 01114 }
| void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1579 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, digit_detect_state_t::td, and mf_detect_state_t::tone_out.
Referenced by analog_ss_thread(), and my_dsp_reset_and_flush_digits().
01580 { 01581 int i; 01582 01583 dsp->dtmf_began = 0; 01584 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01585 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01586 /* Reinitialise the detector for the next block */ 01587 for (i = 0; i < 6; i++) { 01588 goertzel_reset(&s->tone_out[i]); 01589 } 01590 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01591 s->current_sample = 0; 01592 } else { 01593 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01594 /* Reinitialise the detector for the next block */ 01595 for (i = 0; i < 4; i++) { 01596 goertzel_reset(&s->row_out[i]); 01597 goertzel_reset(&s->col_out[i]); 01598 } 01599 s->lasthit = s->current_hit = 0; 01600 s->energy = 0.0; 01601 s->current_sample = 0; 01602 s->hits = 0; 01603 s->misses = 0; 01604 } 01605 01606 dsp->digit_state.digits[0] = '\0'; 01607 dsp->digit_state.current_digits = 0; 01608 }
| void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1551 of file dsp.c.
References ast_free.
Referenced by __ast_play_and_record(), __oh323_destroy(), analog_ss_thread(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_endpoint(), destroy_session(), disable_dsp_detect(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), my_all_subchannels_hungup(), my_dsp_set_digitmode(), record_exec(), sip_rtp_read(), and unload_module().
01552 { 01553 ast_free(dsp); 01554 }
| int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1672 of file dsp.c.
References ast_dsp::tcount.
Referenced by dahdi_read().
01673 { 01674 return dsp->tcount; 01675 }
| int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1709 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().
01710 { 01711 return thresholds[which]; 01712 }
| int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1667 of file dsp.c.
References ast_dsp::tstate.
Referenced by dahdi_read().
01668 { 01669 return dsp->tstate; 01670 }
| int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1714 of file dsp.c.
References _dsp_init().
Referenced by main().
01715 { 01716 return _dsp_init(0); 01717 }
| struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1525 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(), enable_dsp_detect(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), my_dsp_set_digitmode(), read_config(), record_exec(), and store_config().
01526 { 01527 struct ast_dsp *dsp; 01528 01529 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01530 dsp->threshold = DEFAULT_THRESHOLD; 01531 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01532 dsp->busycount = DSP_HISTORY; 01533 dsp->digitmode = DSP_DIGITMODE_DTMF; 01534 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01535 /* Initialize digit detector */ 01536 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01537 dsp->display_inband_dtmf_warning = 1; 01538 /* Initialize initial DSP progress detect parameters */ 01539 ast_dsp_prog_reset(dsp); 01540 /* Initialize fax detector */ 01541 ast_fax_detect_init(dsp); 01542 } 01543 return dsp; 01544 }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1292 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
Referenced by do_waiting().
01293 { 01294 short *s; 01295 int len; 01296 01297 if (f->frametype != AST_FRAME_VOICE) { 01298 ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); 01299 return 0; 01300 } 01301 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01302 ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); 01303 return 0; 01304 } 01305 s = f->data.ptr; 01306 len = f->datalen/2; 01307 return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); 01308 }
| 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 1311 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_TESTLAW, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_frisolate(), ast_getformatname(), AST_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_frame_subclass::codec, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, digit_detect_state_t::digitlen, 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, ast_frame_subclass::integer, ast_frame::len, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_channel::name, ast_frame::ptr, SAMPLE_RATE, 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().
01312 { 01313 int silence; 01314 int res; 01315 int digit = 0, fax_digit = 0; 01316 int x; 01317 short *shortdata; 01318 unsigned char *odata; 01319 int len; 01320 struct ast_frame *outf = NULL; 01321 01322 if (!af) { 01323 return NULL; 01324 } 01325 if (af->frametype != AST_FRAME_VOICE) { 01326 return af; 01327 } 01328 01329 odata = af->data.ptr; 01330 len = af->datalen; 01331 /* Make sure we have short data */ 01332 switch (af->subclass.codec) { 01333 case AST_FORMAT_SLINEAR: 01334 shortdata = af->data.ptr; 01335 len = af->datalen / 2; 01336 break; 01337 case AST_FORMAT_ULAW: 01338 case AST_FORMAT_TESTLAW: 01339 shortdata = alloca(af->datalen * 2); 01340 for (x = 0;x < len; x++) { 01341 shortdata[x] = AST_MULAW(odata[x]); 01342 } 01343 break; 01344 case AST_FORMAT_ALAW: 01345 shortdata = alloca(af->datalen * 2); 01346 for (x = 0; x < len; x++) { 01347 shortdata[x] = AST_ALAW(odata[x]); 01348 } 01349 break; 01350 default: 01351 /*Display warning only once. Otherwise you would get hundreds of warnings every second */ 01352 if (dsp->display_inband_dtmf_warning) 01353 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass.codec)); 01354 dsp->display_inband_dtmf_warning = 0; 01355 return af; 01356 } 01357 01358 /* Initially we do not want to mute anything */ 01359 dsp->mute_fragments = 0; 01360 01361 /* Need to run the silence detection stuff for silence suppression and busy detection */ 01362 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { 01363 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); 01364 } 01365 01366 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01367 memset(&dsp->f, 0, sizeof(dsp->f)); 01368 dsp->f.frametype = AST_FRAME_NULL; 01369 ast_frfree(af); 01370 return ast_frisolate(&dsp->f); 01371 } 01372 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01373 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01374 memset(&dsp->f, 0, sizeof(dsp->f)); 01375 dsp->f.frametype = AST_FRAME_CONTROL; 01376 dsp->f.subclass.integer = AST_CONTROL_BUSY; 01377 ast_frfree(af); 01378 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01379 return ast_frisolate(&dsp->f); 01380 } 01381 01382 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { 01383 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { 01384 fax_digit = 'f'; 01385 } 01386 01387 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { 01388 fax_digit = 'e'; 01389 } 01390 } 01391 01392 if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { 01393 if (dsp->digitmode & DSP_DIGITMODE_MF) 01394 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01395 else 01396 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); 01397 01398 if (dsp->digit_state.current_digits) { 01399 int event = 0, event_len = 0; 01400 char event_digit = 0; 01401 01402 if (!dsp->dtmf_began) { 01403 /* We have not reported DTMF_BEGIN for anything yet */ 01404 01405 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01406 event = AST_FRAME_DTMF_BEGIN; 01407 event_digit = dsp->digit_state.digits[0]; 01408 } 01409 dsp->dtmf_began = 1; 01410 01411 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { 01412 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ 01413 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { 01414 event = AST_FRAME_DTMF_END; 01415 event_digit = dsp->digit_state.digits[0]; 01416 event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; 01417 } 01418 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); 01419 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0])); 01420 dsp->digit_state.current_digits--; 01421 dsp->dtmf_began = 0; 01422 01423 if (dsp->features & DSP_FEATURE_BUSY_DETECT) { 01424 /* Reset Busy Detector as we have some confirmed activity */ 01425 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01426 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01427 ast_debug(1, "DTMF Detected - Reset busydetector\n"); 01428 } 01429 } 01430 01431 if (event) { 01432 memset(&dsp->f, 0, sizeof(dsp->f)); 01433 dsp->f.frametype = event; 01434 dsp->f.subclass.integer = event_digit; 01435 dsp->f.len = event_len; 01436 outf = &dsp->f; 01437 goto done; 01438 } 01439 } 01440 } 01441 01442 if (fax_digit) { 01443 /* Fax was detected - digit is either 'f' or 'e' */ 01444 01445 memset(&dsp->f, 0, sizeof(dsp->f)); 01446 dsp->f.frametype = AST_FRAME_DTMF; 01447 dsp->f.subclass.integer = fax_digit; 01448 outf = &dsp->f; 01449 goto done; 01450 } 01451 01452 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01453 res = __ast_dsp_call_progress(dsp, shortdata, len); 01454 if (res) { 01455 switch (res) { 01456 case AST_CONTROL_ANSWER: 01457 case AST_CONTROL_BUSY: 01458 case AST_CONTROL_RINGING: 01459 case AST_CONTROL_CONGESTION: 01460 case AST_CONTROL_HANGUP: 01461 memset(&dsp->f, 0, sizeof(dsp->f)); 01462 dsp->f.frametype = AST_FRAME_CONTROL; 01463 dsp->f.subclass.integer = res; 01464 dsp->f.src = "dsp_progress"; 01465 if (chan) 01466 ast_queue_frame(chan, &dsp->f); 01467 break; 01468 default: 01469 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01470 } 01471 } 01472 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { 01473 res = __ast_dsp_call_progress(dsp, shortdata, len); 01474 } 01475 01476 done: 01477 /* Mute fragment of the frame */ 01478 for (x = 0; x < dsp->mute_fragments; x++) { 01479 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); 01480 } 01481 01482 switch (af->subclass.codec) { 01483 case AST_FORMAT_SLINEAR: 01484 break; 01485 case AST_FORMAT_ULAW: 01486 for (x = 0; x < len; x++) { 01487 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); 01488 } 01489 break; 01490 case AST_FORMAT_ALAW: 01491 for (x = 0; x < len; x++) { 01492 odata[x] = AST_LIN2A((unsigned short) shortdata[x]); 01493 } 01494 break; 01495 } 01496 01497 if (outf) { 01498 if (chan) { 01499 ast_queue_frame(chan, af); 01500 } 01501 ast_frfree(af); 01502 return ast_frisolate(outf); 01503 } else { 01504 return af; 01505 } 01506 }
| static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1508 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().
01509 { 01510 int max = 0; 01511 int x; 01512 01513 dsp->gsamp_size = modes[dsp->progmode].size; 01514 dsp->gsamps = 0; 01515 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01516 if (modes[dsp->progmode].freqs[x]) { 01517 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01518 max = x + 1; 01519 } 01520 } 01521 dsp->freqcount = max; 01522 dsp->ringtimeout= 0; 01523 }
| int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1719 of file dsp.c.
References _dsp_init().
01720 { 01721 return _dsp_init(1); 01722 }
| void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1610 of file dsp.c.
References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::ringtimeout, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by debug_check_frame_for_silence().
01611 { 01612 int x; 01613 01614 dsp->totalsilence = 0; 01615 dsp->gsamps = 0; 01616 for (x = 0; x < 4; x++) { 01617 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01618 } 01619 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01620 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01621 dsp->ringtimeout= 0; 01622 }
| void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
| int | cadences | |||
| ) |
Set number of required cadences for busy.
Definition at line 1561 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01562 { 01563 if (cadences < 4) { 01564 cadences = 4; 01565 } 01566 if (cadences > DSP_HISTORY) { 01567 cadences = DSP_HISTORY; 01568 } 01569 dsp->busycount = cadences; 01570 }
| void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
| int | tonelength, | |||
| int | quietlength | |||
| ) |
Set expected lengths of the busy tone.
Definition at line 1572 of file dsp.c.
References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.
Referenced by dahdi_new().
01573 { 01574 dsp->busy_tonelength = tonelength; 01575 dsp->busy_quietlength = quietlength; 01576 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01577 }
| int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
| char * | zone | |||
| ) |
Set zone for doing progress detection.
Definition at line 1648 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
01649 { 01650 int x; 01651 01652 for (x = 0; x < ARRAY_LEN(aliases); x++) { 01653 if (!strcasecmp(aliases[x].name, zone)) { 01654 dsp->progmode = aliases[x].mode; 01655 ast_dsp_prog_reset(dsp); 01656 return 0; 01657 } 01658 } 01659 return -1; 01660 }
| int ast_dsp_set_digitmode | ( | struct ast_dsp * | dsp, | |
| int | digitmode | |||
| ) |
Set digit mode.
Definition at line 1624 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 analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), enable_dsp_detect(), mgcp_new(), mkintf(), my_dsp_set_digitmode(), and store_config().
01625 { 01626 int new; 01627 int old; 01628 01629 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01630 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01631 if (old != new) { 01632 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01633 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01634 } 01635 dsp->digitmode = digitmode; 01636 return 0; 01637 }
| int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
| int | faxmode | |||
| ) |
Set fax mode.
Definition at line 1639 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01640 { 01641 if (dsp->faxmode != faxmode) { 01642 ast_fax_detect_init(dsp); 01643 } 01644 dsp->faxmode = faxmode; 01645 return 0; 01646 }
| void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
| int | features | |||
| ) |
Select feature set.
Definition at line 1546 of file dsp.c.
References ast_dsp::features.
Referenced by __oh323_new(), dahdi_handle_dtmfup(), dahdi_new(), dahdi_read(), dahdi_setoption(), disable_dtmf_detect(), enable_dsp_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_rtp_read(), and store_config().
01547 { 01548 dsp->features = features; 01549 }
| void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
| int | threshold | |||
| ) |
Set threshold value for silence.
Definition at line 1556 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), do_waiting(), fax_session_new(), 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 1274 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), debug_check_frame_for_silence(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
01275 { 01276 short *s; 01277 int len; 01278 01279 if (f->frametype != AST_FRAME_VOICE) { 01280 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01281 return 0; 01282 } 01283 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 01284 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01285 return 0; 01286 } 01287 s = f->data.ptr; 01288 len = f->datalen/2; 01289 return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); 01290 }
| 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 1662 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
01663 { 01664 return (dsp->mute_fragments > 0); 01665 }
| static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 480 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().
00481 { 00482 int i; 00483 00484 s->lasthit = 0; 00485 s->current_hit = 0; 00486 for (i = 0; i < 4; i++) { 00487 goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE); 00488 goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE); 00489 s->energy = 0.0; 00490 } 00491 s->current_sample = 0; 00492 s->hits = 0; 00493 s->misses = 0; 00494 00495 s->hits_to_begin = DTMF_HITS_TO_BEGIN; 00496 s->misses_to_end = DTMF_MISSES_TO_END; 00497 }
| static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 474 of file dsp.c.
References ast_tone_detect_init(), 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().
00475 { 00476 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00477 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00478 }
| static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 499 of file dsp.c.
References 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().
00500 { 00501 int i; 00502 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00503 for (i = 0; i < 6; i++) { 00504 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00505 } 00506 s->current_sample = 0; 00507 s->current_hit = 0; 00508 }
| static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
| int | freq, | |||
| int | duration, | |||
| int | amp | |||
| ) | [static] |
Definition at line 414 of file dsp.c.
References ast_debug, 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().
00415 { 00416 int duration_samples; 00417 float x; 00418 int periods_in_block; 00419 00420 s->freq = freq; 00421 00422 /* Desired tone duration in samples */ 00423 duration_samples = duration * SAMPLE_RATE / 1000; 00424 /* We want to allow 10% deviation of tone duration */ 00425 duration_samples = duration_samples * 9 / 10; 00426 00427 /* If we want to remove tone, it is important to have block size not 00428 to exceed frame size. Otherwise by the moment tone is detected it is too late 00429 to squelch it from previous frames */ 00430 s->block_size = SAMPLES_IN_FRAME; 00431 00432 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00433 00434 /* Make sure we will have at least 5 periods at target frequency for analisys. 00435 This may make block larger than expected packet and will make squelching impossible 00436 but at least we will be detecting the tone */ 00437 if (periods_in_block < 5) 00438 periods_in_block = 5; 00439 00440 /* Now calculate final block size. It will contain integer number of periods */ 00441 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00442 00443 /* tone_detect is currently only used to detect fax tones and we 00444 do not need suqlching the fax tones */ 00445 s->squelch = 0; 00446 00447 /* Account for the first and the last block to be incomplete 00448 and thus no tone will be detected in them */ 00449 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00450 00451 goertzel_init(&s->tone, freq, s->block_size); 00452 00453 s->samples_pending = s->block_size; 00454 s->hit_count = 0; 00455 s->last_hit = 0; 00456 s->energy = 0.0; 00457 00458 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00459 According to Parseval's theorem the energy computed in time domain equals to energy 00460 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00461 from the energy in the time domain we will get energy of the remaining signal (without the tone 00462 we are detecting). We will be checking that 00463 10*log(Ew / (Et - Ew)) > amp 00464 Calculate threshold so that we will be actually checking 00465 Ew > Et * threshold 00466 */ 00467 00468 x = pow(10.0, amp / 10.0); 00469 s->threshold = x / (x + 1); 00470 00471 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00472 }
| static int dtmf_detect | ( | struct ast_dsp * | dsp, | |
| digit_detect_state_t * | s, | |||
| int16_t | amp[], | |||
| int | samples, | |||
| int | squelch, | |||
| int | relax | |||
| ) | [static] |
Definition at line 641 of file dsp.c.
References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, digit_detect_state_t::digitlen, 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, 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 /* Current hit was same as last, so increment digit duration (of last digit) */ 00737 s->digitlen[s->current_digits - 1] += DTMF_GSIZE; 00738 } 00739 } 00740 00741 /* Look for a start of a new digit no matter if we are already in the middle of some 00742 digit or not. This is because hits_to_begin may be smaller than misses_to_end 00743 and we may find begin of new digit before we consider last one ended. */ 00744 if (hit) { 00745 if (hit == s->td.dtmf.lasthit) { 00746 s->td.dtmf.hits++; 00747 } else { 00748 s->td.dtmf.hits = 1; 00749 } 00750 00751 if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin && hit != s->td.dtmf.current_hit) { 00752 store_digit(s, hit); 00753 s->td.dtmf.current_hit = hit; 00754 s->td.dtmf.misses = 0; 00755 } 00756 } else { 00757 s->td.dtmf.hits = 0; 00758 } 00759 00760 s->td.dtmf.lasthit = hit; 00761 00762 /* If we had a hit in this block, include it into mute fragment */ 00763 if (squelch && hit) { 00764 if (mute.end < sample - DTMF_GSIZE) { 00765 /* There is a gap between fragments */ 00766 mute_fragment(dsp, &mute); 00767 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0; 00768 } 00769 mute.end = limit + DTMF_GSIZE; 00770 } 00771 00772 /* Reinitialise the detector for the next block */ 00773 for (i = 0; i < 4; i++) { 00774 goertzel_reset(&s->td.dtmf.row_out[i]); 00775 goertzel_reset(&s->td.dtmf.col_out[i]); 00776 } 00777 s->td.dtmf.energy = 0.0; 00778 s->td.dtmf.current_sample = 0; 00779 } 00780 00781 if (squelch && mute.end) { 00782 if (mute.end > samples) { 00783 s->td.dtmf.mute_samples = mute.end - samples; 00784 mute.end = samples; 00785 } 00786 mute_fragment(dsp, &mute); 00787 } 00788 00789 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00790 }
| static void goertzel_init | ( | goertzel_state_t * | s, | |
| float | freq, | |||
| int | samples | |||
| ) | [inline, static] |
Definition at line 342 of file dsp.c.
References goertzel_state_t::chunky, cos, goertzel_state_t::fac, M_PI, SAMPLE_RATE, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().
00343 { 00344 s->v2 = s->v3 = s->chunky = 0.0; 00345 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE)); 00346 s->samples = samples; 00347 }
| static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 349 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_digitreset(), 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().
00334 { 00335 goertzel_result_t r; 00336 r.value = (s->v3 * s->v3) + (s->v2 * s->v2); 00337 r.value -= ((s->v2 * s->v3) >> 15) * s->fac; 00338 r.power = s->chunky * 2; 00339 return (float)r.value * (float)(1 << r.power); 00340 }
| static void goertzel_sample | ( | goertzel_state_t * | s, | |
| short | sample | |||
| ) | [inline, static] |
Definition at line 306 of file dsp.c.
References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), goertzel_update(), mf_detect(), and tone_detect().
00307 { 00308 int v1; 00309 00310 v1 = s->v2; 00311 s->v2 = s->v3; 00312 00313 s->v3 = (s->fac * s->v2) >> 15; 00314 s->v3 = s->v3 - v1 + (sample >> s->chunky); 00315 if (abs(s->v3) > 32768) { 00316 s->chunky++; 00317 s->v3 = s->v3 >> 1; 00318 s->v2 = s->v2 >> 1; 00319 v1 = v1 >> 1; 00320 } 00321 }
| static void goertzel_update | ( | goertzel_state_t * | s, | |
| short * | samps, | |||
| int | count | |||
| ) | [inline, static] |
Definition at line 323 of file dsp.c.
References goertzel_sample().
00324 { 00325 int i; 00326 00327 for (i = 0; i < count; i++) { 00328 goertzel_sample(s, samps[i]); 00329 } 00330 }
| static int mf_detect | ( | struct ast_dsp * | dsp, | |
| digit_detect_state_t * | s, | |||
| int16_t | amp[], | |||
| int | samples, | |||
| int | squelch, | |||
| int | relax | |||
| ) | [static] |
Definition at line 792 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, 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().
00794 { 00795 float energy[6]; 00796 int best; 00797 int second_best; 00798 float famp; 00799 int i; 00800 int j; 00801 int sample; 00802 int hit; 00803 int limit; 00804 fragment_t mute = {0, 0}; 00805 00806 if (squelch && s->td.mf.mute_samples > 0) { 00807 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples; 00808 s->td.mf.mute_samples -= mute.end; 00809 } 00810 00811 hit = 0; 00812 for (sample = 0; sample < samples; sample = limit) { 00813 /* 80 is optimised to meet the MF specs. */ 00814 /* XXX So then why is MF_GSIZE defined as 120? */ 00815 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) { 00816 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00817 } else { 00818 limit = samples; 00819 } 00820 /* The following unrolled loop takes only 35% (rough estimate) of the 00821 time of a rolled loop on the machine on which it was developed */ 00822 for (j = sample; j < limit; j++) { 00823 famp = amp[j]; 00824 /* With GCC 2.95, the following unrolled code seems to take about 35% 00825 (rough estimate) as long as a neat little 0-3 loop */ 00826 goertzel_sample(s->td.mf.tone_out, amp[j]); 00827 goertzel_sample(s->td.mf.tone_out + 1, amp[j]); 00828 goertzel_sample(s->td.mf.tone_out + 2, amp[j]); 00829 goertzel_sample(s->td.mf.tone_out + 3, amp[j]); 00830 goertzel_sample(s->td.mf.tone_out + 4, amp[j]); 00831 goertzel_sample(s->td.mf.tone_out + 5, amp[j]); 00832 } 00833 s->td.mf.current_sample += (limit - sample); 00834 if (s->td.mf.current_sample < MF_GSIZE) { 00835 continue; 00836 } 00837 /* We're at the end of an MF detection block. */ 00838 /* Find the two highest energies. The spec says to look for 00839 two tones and two tones only. Taking this literally -ie 00840 only two tones pass the minimum threshold - doesn't work 00841 well. The sinc function mess, due to rectangular windowing 00842 ensure that! Find the two highest energies and ensure they 00843 are considerably stronger than any of the others. */ 00844 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00845 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00846 if (energy[0] > energy[1]) { 00847 best = 0; 00848 second_best = 1; 00849 } else { 00850 best = 1; 00851 second_best = 0; 00852 } 00853 /*endif*/ 00854 for (i = 2; i < 6; i++) { 00855 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00856 if (energy[i] >= energy[best]) { 00857 second_best = best; 00858 best = i; 00859 } else if (energy[i] >= energy[second_best]) { 00860 second_best = i; 00861 } 00862 } 00863 /* Basic signal level and twist tests */ 00864 hit = 0; 00865 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00866 && energy[best] < energy[second_best]*BELL_MF_TWIST 00867 && energy[best] * BELL_MF_TWIST > energy[second_best]) { 00868 /* Relative peak test */ 00869 hit = -1; 00870 for (i = 0; i < 6; i++) { 00871 if (i != best && i != second_best) { 00872 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00873 /* The best two are not clearly the best */ 00874 hit = 0; 00875 break; 00876 } 00877 } 00878 } 00879 } 00880 if (hit) { 00881 /* Get the values into ascending order */ 00882 if (second_best < best) { 00883 i = best; 00884 best = second_best; 00885 second_best = i; 00886 } 00887 best = best * 5 + second_best - 1; 00888 hit = bell_mf_positions[best]; 00889 /* Look for two successive similar results */ 00890 /* The logic in the next test is: 00891 For KP we need 4 successive identical clean detects, with 00892 two blocks of something different preceeding it. For anything 00893 else we need two successive identical clean detects, with 00894 two blocks of something different preceeding it. */ 00895 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00896 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00897 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00898 hit != s->td.mf.hits[0]))) { 00899 store_digit(s, hit); 00900 } 00901 } 00902 00903 00904 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00905 /* Two successive block without a hit terminate current digit */ 00906 s->td.mf.current_hit = 0; 00907 } 00908 00909 s->td.mf.hits[0] = s->td.mf.hits[1]; 00910 s->td.mf.hits[1] = s->td.mf.hits[2]; 00911 s->td.mf.hits[2] = s->td.mf.hits[3]; 00912 s->td.mf.hits[3] = s->td.mf.hits[4]; 00913 s->td.mf.hits[4] = hit; 00914 00915 /* If we had a hit in this block, include it into mute fragment */ 00916 if (squelch && hit) { 00917 if (mute.end < sample - MF_GSIZE) { 00918 /* There is a gap between fragments */ 00919 mute_fragment(dsp, &mute); 00920 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0; 00921 } 00922 mute.end = limit + DTMF_GSIZE; 00923 } 00924 00925 /* Reinitialise the detector for the next block */ 00926 for (i = 0; i < 6; i++) 00927 goertzel_reset(&s->td.mf.tone_out[i]); 00928 s->td.mf.current_sample = 0; 00929 } 00930 00931 if (squelch && mute.end) { 00932 if (mute.end > samples) { 00933 s->td.mf.mute_samples = mute.end - samples; 00934 mute.end = samples; 00935 } 00936 mute_fragment(dsp, &mute); 00937 } 00938 00939 return (s->td.mf.current_hit); /* return the debounced hit */ 00940 }
| static void mute_fragment | ( | struct ast_dsp * | dsp, | |
| fragment_t * | fragment | |||
| ) | [static] |
Definition at line 404 of file dsp.c.
References ARRAY_LEN, ast_log(), LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.
Referenced by dtmf_detect(), mf_detect(), and tone_detect().
00405 { 00406 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) { 00407 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n"); 00408 return; 00409 } 00410 00411 dsp->mute_data[dsp->mute_fragments++] = *fragment; 00412 }
| static int pair_there | ( | float | p1, | |
| float | p2, | |||
| float | i1, | |||
| float | i2, | |||
| float | e | |||
| ) | [inline, static] |
Definition at line 942 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00943 { 00944 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00945 /* Make sure absolute levels are high enough */ 00946 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) { 00947 return 0; 00948 } 00949 /* Amplify ignored stuff */ 00950 i2 *= TONE_THRESH; 00951 i1 *= TONE_THRESH; 00952 e *= TONE_THRESH; 00953 /* Check first tone */ 00954 if ((p1 < i1) || (p1 < i2) || (p1 < e)) { 00955 return 0; 00956 } 00957 /* And second */ 00958 if ((p2 < i1) || (p2 < i2) || (p2 < e)) { 00959 return 0; 00960 } 00961 /* Guess it's there... */ 00962 return 1; 00963 }
| static void store_digit | ( | digit_detect_state_t * | s, | |
| char | digit | |||
| ) | [static] |
Definition at line 628 of file dsp.c.
References ast_log(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digitlen, digit_detect_state_t::digits, LOG_WARNING, digit_detect_state_t::lost_digits, and MAX_DTMF_DIGITS.
Referenced by dtmf_detect(), and mf_detect().
00629 { 00630 s->detected_digits++; 00631 if (s->current_digits < MAX_DTMF_DIGITS) { 00632 s->digitlen[s->current_digits] = 0; 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 524 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, 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().
00525 { 00526 float tone_energy; 00527 int i; 00528 int hit = 0; 00529 int limit; 00530 int res = 0; 00531 int16_t *ptr; 00532 int start, end; 00533 fragment_t mute = {0, 0}; 00534 00535 if (s->squelch && s->mute_samples > 0) { 00536 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples; 00537 s->mute_samples -= mute.end; 00538 } 00539 00540 for (start = 0; start < samples; start = end) { 00541 /* Process in blocks. */ 00542 limit = samples - start; 00543 if (limit > s->samples_pending) { 00544 limit = s->samples_pending; 00545 } 00546 end = start + limit; 00547 00548 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00549 /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ 00550 s->energy += (int32_t) *ptr * (int32_t) *ptr; 00551 00552 goertzel_sample(&s->tone, *ptr); 00553 } 00554 00555 s->samples_pending -= limit; 00556 00557 if (s->samples_pending) { 00558 /* Finished incomplete (last) block */ 00559 break; 00560 } 00561 00562 tone_energy = goertzel_result(&s->tone); 00563 00564 /* Scale to make comparable */ 00565 tone_energy *= 2.0; 00566 s->energy *= s->block_size; 00567 00568 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)); 00569 hit = 0; 00570 if (tone_energy > s->energy * s->threshold) { 00571 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00572 hit = 1; 00573 } 00574 00575 if (s->hit_count) { 00576 s->hit_count++; 00577 } 00578 00579 if (hit == s->last_hit) { 00580 if (!hit) { 00581 /* Two successive misses. Tone ended */ 00582 s->hit_count = 0; 00583 } else if (!s->hit_count) { 00584 s->hit_count++; 00585 } 00586 00587 } 00588 00589 if (s->hit_count == s->hits_required) { 00590 ast_debug(1, "%d Hz done detected\n", s->freq); 00591 res = 1; 00592 } 00593 00594 s->last_hit = hit; 00595 00596 /* If we had a hit in this block, include it into mute fragment */ 00597 if (s->squelch && hit) { 00598 if (mute.end < start - s->block_size) { 00599 /* There is a gap between fragments */ 00600 mute_fragment(dsp, &mute); 00601 mute.start = (start > s->block_size) ? (start - s->block_size) : 0; 00602 } 00603 mute.end = end + s->block_size; 00604 } 00605 00606 /* Reinitialise the detector for the next block */ 00607 /* Reset for the next block */ 00608 goertzel_reset(&s->tone); 00609 00610 /* Advance to the next block */ 00611 s->energy = 0.0; 00612 s->samples_pending = s->block_size; 00613 00614 amp += limit; 00615 } 00616 00617 if (s->squelch && mute.end) { 00618 if (mute.end > samples) { 00619 s->mute_samples = mute.end - samples; 00620 mute.end = samples; 00621 } 00622 mute_fragment(dsp, &mute); 00623 } 00624 00625 return res; 00626 }
Referenced by ast_dsp_set_call_progress_zone(), and find_alias().
const char bell_mf_positions[] = "1247C-358A--69*---0B----#" [static] |
const int DEFAULT_SILENCE_THRESHOLD = 256 [static] |
const float dtmf_col[] [static] |
const char dtmf_positions[] = "123A" "456B" "789C" "*0#D" [static] |
const float dtmf_row[] [static] |
const float mf_tones[] [static] |
Referenced by ast_dsp_prog_reset(), and setrem().
int thresholds[THRESHOLD_MAX] [static] |
1.5.6