#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"

Go to the source code of this file.
Data Structures | |
| struct | ast_dsp |
| struct | digit_detect_state_t |
| struct | dtmf_detect_state_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 | DEFAULT_THRESHOLD 512 |
| #define | DSP_HISTORY 15 |
| #define | DTMF_2ND_HARMONIC_COL 63.1 |
| #define | DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) |
| #define | DTMF_NORMAL_TWIST 6.3 |
| #define | DTMF_RELATIVE_PEAK_COL 6.3 |
| #define | DTMF_RELATIVE_PEAK_ROW 6.3 |
| #define | DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 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 | FIX_INF(inf) |
| #define | MAX_DTMF_DIGITS 128 |
| #define | MF_GSIZE 120 |
| #define | SAMPLE_RATE 8000 |
| #define | SAMPLES_IN_FRAME 160 |
| #define | TONE_MIN_THRESH 1e8 |
| #define | TONE_THRESH 10.0 |
Enumerations | |
| enum | busy_detect { BUSY_PERCENT = 10, BUSY_PAT_PERCENT = 7, BUSY_THRESHOLD = 100, BUSY_MIN = 75, BUSY_MAX = 3100 } |
| enum | freq_index { HZ_350 = 0, HZ_440, HZ_480, HZ_620, HZ_950, HZ_1400, HZ_1800, HZ_425 = 0, HZ_400 = 0 } |
| enum | gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 } |
| enum | gsamp_thresh { THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4, THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300 } |
| enum | prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK } |
Functions | |
| static int | __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len) |
| static int | __ast_dsp_digitdetect (struct ast_dsp *dsp, short *s, int len, int *writeback) |
| static int | __ast_dsp_silence (struct ast_dsp *dsp, short *s, int len, int *totalsilence) |
| 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. | |
| int | ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *inf) |
| Return non-zero if DTMF hit was found. | |
| int | ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode) |
| Set digit mode. | |
| 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_tstate (struct ast_dsp *dsp) |
| Get tstate (Tone State). | |
| int | ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max) |
| Get pending DTMF/MF digits. | |
| struct ast_dsp * | ast_dsp_new (void) |
| 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) |
| 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_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. | |
| 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 (digit_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback) |
| 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 (digit_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback) |
| 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 (tone_detect_state_t *s, int16_t *amp, int samples, int *writeback) |
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 [] |
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 |
| #define DSP_HISTORY 15 |
Remember last 15 units
Definition at line 118 of file dsp.c.
Referenced by __ast_dsp_silence(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().
| #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) |
| #define DTMF_NORMAL_TWIST 6.3 |
| #define DTMF_RELATIVE_PEAK_COL 6.3 |
| #define DTMF_RELATIVE_PEAK_ROW 6.3 |
| #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 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 FIX_INF | ( | inf | ) |
Referenced by ast_dsp_process().
| #define MAX_DTMF_DIGITS 128 |
| #define MF_GSIZE 120 |
| #define SAMPLE_RATE 8000 |
Definition at line 185 of file dsp.c.
Referenced by ast_tone_detect_init(), goertzel_init(), and open_stream().
| #define SAMPLES_IN_FRAME 160 |
| #define TONE_MIN_THRESH 1e8 |
How much tone there should be at least to attempt
Definition at line 121 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 120 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 109 of file dsp.c.
00109 { 00110 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */ 00111 BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */ 00112 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */ 00113 BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */ 00114 BUSY_MAX =3100 /*!< Busy can't be longer than 3100 ms in half-cadence */ 00115 };
| enum freq_index |
| HZ_350 | For US modes { |
| HZ_440 | |
| HZ_480 | |
| HZ_620 | |
| HZ_950 | |
| HZ_1400 | |
| HZ_1800 | } |
| HZ_425 | For CR/BR modes |
| HZ_400 | For UK mode |
Definition at line 70 of file dsp.c.
00070 { 00071 /*! For US modes { */ 00072 HZ_350 = 0, 00073 HZ_440, 00074 HZ_480, 00075 HZ_620, 00076 HZ_950, 00077 HZ_1400, 00078 HZ_1800, /*!< } */ 00079 00080 /*! For CR/BR modes */ 00081 HZ_425 = 0, 00082 00083 /*! For UK mode */ 00084 HZ_400 = 0 00085 };
| 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 58 of file dsp.c.
00058 { 00059 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ 00060 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */ 00061 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */ 00062 };
| enum gsamp_thresh |
All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)
Definition at line 124 of file dsp.c.
00124 { 00125 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */ 00126 THRESH_TALK = 2, /*!< Talk detection does not work continuously */ 00127 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */ 00128 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */ 00129 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */ 00130 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */ 00131 };
| enum prog_mode |
Definition at line 64 of file dsp.c.
00064 { 00065 PROG_MODE_NA = 0, 00066 PROG_MODE_CR, 00067 PROG_MODE_UK 00068 };
| static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len | |||
| ) | [static] |
Definition at line 886 of file dsp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_call_progress(), and ast_dsp_process().
00887 { 00888 int x; 00889 int y; 00890 int pass; 00891 int newstate = DSP_TONE_STATE_SILENCE; 00892 int res = 0; 00893 while (len) { 00894 /* Take the lesser of the number of samples we need and what we have */ 00895 pass = len; 00896 if (pass > dsp->gsamp_size - dsp->gsamps) 00897 pass = dsp->gsamp_size - dsp->gsamps; 00898 for (x=0;x<pass;x++) { 00899 for (y=0;y<dsp->freqcount;y++) 00900 goertzel_sample(&dsp->freqs[y], s[x]); 00901 dsp->genergy += s[x] * s[x]; 00902 } 00903 s += pass; 00904 dsp->gsamps += pass; 00905 len -= pass; 00906 if (dsp->gsamps == dsp->gsamp_size) { 00907 float hz[7]; 00908 for (y=0;y<7;y++) 00909 hz[y] = goertzel_result(&dsp->freqs[y]); 00910 switch (dsp->progmode) { 00911 case PROG_MODE_NA: 00912 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 00913 newstate = DSP_TONE_STATE_BUSY; 00914 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 00915 newstate = DSP_TONE_STATE_RINGING; 00916 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 00917 newstate = DSP_TONE_STATE_DIALTONE; 00918 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 00919 newstate = DSP_TONE_STATE_SPECIAL1; 00920 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 00921 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 00922 newstate = DSP_TONE_STATE_SPECIAL2; 00923 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 00924 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 00925 newstate = DSP_TONE_STATE_SPECIAL3; 00926 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00927 newstate = DSP_TONE_STATE_TALKING; 00928 } else 00929 newstate = DSP_TONE_STATE_SILENCE; 00930 break; 00931 case PROG_MODE_CR: 00932 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 00933 newstate = DSP_TONE_STATE_RINGING; 00934 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00935 newstate = DSP_TONE_STATE_TALKING; 00936 } else 00937 newstate = DSP_TONE_STATE_SILENCE; 00938 break; 00939 case PROG_MODE_UK: 00940 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 00941 newstate = DSP_TONE_STATE_HUNGUP; 00942 } 00943 break; 00944 default: 00945 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 00946 } 00947 if (newstate == dsp->tstate) { 00948 dsp->tcount++; 00949 if (dsp->ringtimeout) 00950 dsp->ringtimeout++; 00951 switch (dsp->tstate) { 00952 case DSP_TONE_STATE_RINGING: 00953 if ((dsp->features & DSP_PROGRESS_RINGING) && 00954 (dsp->tcount==THRESH_RING)) { 00955 res = AST_CONTROL_RINGING; 00956 dsp->ringtimeout= 1; 00957 } 00958 break; 00959 case DSP_TONE_STATE_BUSY: 00960 if ((dsp->features & DSP_PROGRESS_BUSY) && 00961 (dsp->tcount==THRESH_BUSY)) { 00962 res = AST_CONTROL_BUSY; 00963 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00964 } 00965 break; 00966 case DSP_TONE_STATE_TALKING: 00967 if ((dsp->features & DSP_PROGRESS_TALK) && 00968 (dsp->tcount==THRESH_TALK)) { 00969 res = AST_CONTROL_ANSWER; 00970 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00971 } 00972 break; 00973 case DSP_TONE_STATE_SPECIAL3: 00974 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 00975 (dsp->tcount==THRESH_CONGESTION)) { 00976 res = AST_CONTROL_CONGESTION; 00977 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00978 } 00979 break; 00980 case DSP_TONE_STATE_HUNGUP: 00981 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 00982 (dsp->tcount==THRESH_HANGUP)) { 00983 res = AST_CONTROL_HANGUP; 00984 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00985 } 00986 break; 00987 } 00988 if (dsp->ringtimeout==THRESH_RING2ANSWER) { 00989 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 00990 res = AST_CONTROL_ANSWER; 00991 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00992 } 00993 } else { 00994 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 00995 ast_debug(5, "Start state %d\n", newstate); 00996 dsp->tstate = newstate; 00997 dsp->tcount = 1; 00998 } 00999 01000 /* Reset goertzel */ 01001 for (x=0;x<7;x++) 01002 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01003 dsp->gsamps = 0; 01004 dsp->genergy = 0.0; 01005 } 01006 } 01007 01008 return res; 01009 }
| static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len, | |||
| int * | writeback | |||
| ) | [static] |
Definition at line 808 of file dsp.c.
References ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dtmf_detect(), ast_dsp::faxmode, ast_dsp::features, mf_detect(), store_digit(), and tone_detect().
Referenced by ast_dsp_digitdetect(), and ast_dsp_process().
00809 { 00810 int res = 0; 00811 00812 if ((dsp->features & DSP_FEATURE_DTMF_DETECT) && (dsp->digitmode & DSP_DIGITMODE_MF)) 00813 res = mf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00814 else if (dsp->features & DSP_FEATURE_DTMF_DETECT) 00815 res = dtmf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00816 00817 if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CNG)) { 00818 if (tone_detect(&dsp->cng_tone_state, s, len, NULL)) { 00819 store_digit(&dsp->digit_state, 'f'); 00820 res = 'f'; 00821 } 00822 } 00823 00824 if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CED)) { 00825 if (tone_detect(&dsp->ced_tone_state, s, len, NULL)) { 00826 store_digit(&dsp->digit_state, 'e'); 00827 res = 'e'; 00828 } 00829 } 00830 00831 return res; 00832 }
| static int __ast_dsp_silence | ( | struct ast_dsp * | dsp, | |
| short * | s, | |||
| int | len, | |||
| int * | totalsilence | |||
| ) | [static] |
Definition at line 1024 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_process(), and ast_dsp_silence().
01025 { 01026 int accum; 01027 int x; 01028 int res = 0; 01029 01030 if (!len) 01031 return 0; 01032 accum = 0; 01033 for (x=0;x<len; x++) 01034 accum += abs(s[x]); 01035 accum /= len; 01036 if (accum < dsp->threshold) { 01037 /* Silent */ 01038 dsp->totalsilence += len/8; 01039 if (dsp->totalnoise) { 01040 /* Move and save history */ 01041 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); 01042 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01043 /* we don't want to check for busydetect that frequently */ 01044 #if 0 01045 dsp->busymaybe = 1; 01046 #endif 01047 } 01048 dsp->totalnoise = 0; 01049 res = 1; 01050 } else { 01051 /* Not silent */ 01052 dsp->totalnoise += len/8; 01053 if (dsp->totalsilence) { 01054 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01055 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01056 /* Move and save history */ 01057 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0])); 01058 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01059 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01060 if (silence1 < silence2) { 01061 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) 01062 dsp->busymaybe = 1; 01063 else 01064 dsp->busymaybe = 0; 01065 } else { 01066 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) 01067 dsp->busymaybe = 1; 01068 else 01069 dsp->busymaybe = 0; 01070 } 01071 } 01072 dsp->totalsilence = 0; 01073 } 01074 if (totalsilence) 01075 *totalsilence = dsp->totalsilence; 01076 return res; 01077 }
| static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
| int | mf | |||
| ) | [static] |
Definition at line 442 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_digitmode(), and ast_dsp_new().
00443 { 00444 s->current_digits = 0; 00445 s->detected_digits = 0; 00446 s->lost_digits = 0; 00447 s->digits[0] = '\0'; 00448 00449 if (mf) 00450 ast_mf_detect_init(&s->td.mf); 00451 else 00452 ast_dtmf_detect_init(&s->td.dtmf); 00453 }
| 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 1079 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().
01080 { 01081 int res = 0, x; 01082 #ifndef BUSYDETECT_TONEONLY 01083 int avgsilence = 0, hitsilence = 0; 01084 #endif 01085 int avgtone = 0, hittone = 0; 01086 if (!dsp->busymaybe) 01087 return res; 01088 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01089 #ifndef BUSYDETECT_TONEONLY 01090 avgsilence += dsp->historicsilence[x]; 01091 #endif 01092 avgtone += dsp->historicnoise[x]; 01093 } 01094 #ifndef BUSYDETECT_TONEONLY 01095 avgsilence /= dsp->busycount; 01096 #endif 01097 avgtone /= dsp->busycount; 01098 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01099 #ifndef BUSYDETECT_TONEONLY 01100 if (avgsilence > dsp->historicsilence[x]) { 01101 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01102 hitsilence++; 01103 } else { 01104 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01105 hitsilence++; 01106 } 01107 #endif 01108 if (avgtone > dsp->historicnoise[x]) { 01109 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01110 hittone++; 01111 } else { 01112 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01113 hittone++; 01114 } 01115 } 01116 #ifndef BUSYDETECT_TONEONLY 01117 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01118 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01119 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01120 #else 01121 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01122 #endif 01123 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01124 if (avgtone > avgsilence) { 01125 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01126 res = 1; 01127 } else { 01128 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01129 res = 1; 01130 } 01131 #else 01132 res = 1; 01133 #endif 01134 } 01135 /* If we know the expected busy tone length, check we are in the range */ 01136 if (res && (dsp->busy_tonelength > 0)) { 01137 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01138 #ifdef BUSYDETECT_DEBUG 01139 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", 01140 avgtone, dsp->busy_tonelength); 01141 #endif 01142 res = 0; 01143 } 01144 } 01145 #ifndef BUSYDETECT_TONEONLY 01146 /* If we know the expected busy tone silent-period length, check we are in the range */ 01147 if (res && (dsp->busy_quietlength > 0)) { 01148 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01149 #ifdef BUSYDETECT_DEBUG 01150 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", 01151 avgsilence, dsp->busy_quietlength); 01152 #endif 01153 res = 0; 01154 } 01155 } 01156 #endif 01157 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG) 01158 if (res) { 01159 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01160 } else { 01161 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01162 } 01163 #endif 01164 return res; 01165 }
Scans for progress indication in audio.
Definition at line 1011 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, and ast_frame::subclass.
01012 { 01013 if (inf->frametype != AST_FRAME_VOICE) { 01014 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01015 return 0; 01016 } 01017 if (inf->subclass != AST_FORMAT_SLINEAR) { 01018 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01019 return 0; 01020 } 01021 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01022 }
Return non-zero if DTMF hit was found.
Definition at line 834 of file dsp.c.
References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, s, and ast_frame::subclass.
00835 { 00836 short *s; 00837 int len; 00838 int ign=0; 00839 00840 if (inf->frametype != AST_FRAME_VOICE) { 00841 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00842 return 0; 00843 } 00844 if (inf->subclass != AST_FORMAT_SLINEAR) { 00845 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00846 return 0; 00847 } 00848 s = inf->data; 00849 len = inf->datalen / 2; 00850 return __ast_dsp_digitdetect(dsp, s, len, &ign); 00851 }
| int ast_dsp_digitmode | ( | struct ast_dsp * | dsp, | |
| int | digitmode | |||
| ) |
Set digit mode.
Definition at line 1472 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().
01473 { 01474 int new; 01475 int old; 01476 01477 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01478 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01479 if (old != new) { 01480 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01481 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01482 } 01483 dsp->digitmode = digitmode; 01484 return 0; 01485 }
| void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1430 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, dtmf_detect_state_t::energy, goertzel_reset(), mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::row_out, s, digit_detect_state_t::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out.
Referenced by ss_thread().
01431 { 01432 int i; 01433 01434 dsp->thinkdigit = 0; 01435 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01436 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01437 /* Reinitialise the detector for the next block */ 01438 for (i = 0; i < 6; i++) { 01439 goertzel_reset(&s->tone_out[i]); 01440 } 01441 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01442 s->current_sample = 0; 01443 } else { 01444 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01445 /* Reinitialise the detector for the next block */ 01446 for (i = 0; i < 4; i++) { 01447 goertzel_reset(&s->row_out[i]); 01448 goertzel_reset(&s->col_out[i]); 01449 } 01450 s->lasthit = s->current_hit = 0; 01451 s->energy = 0.0; 01452 s->current_sample = 0; 01453 } 01454 01455 dsp->digit_state.digits[0] = '\0'; 01456 dsp->digit_state.current_digits = 0; 01457 }
| void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1404 of file dsp.c.
References ast_free.
Referenced by __ast_play_and_record(), __oh323_destroy(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_endpoint(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), and unload_module().
01405 { 01406 ast_free(dsp); 01407 }
| int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1515 of file dsp.c.
References ast_dsp::tcount.
01516 { 01517 return dsp->tcount; 01518 }
| int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1510 of file dsp.c.
References ast_dsp::tstate.
01511 { 01512 return dsp->tstate; 01513 }
| int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, | |
| char * | buf, | |||
| int | max | |||
| ) |
Get pending DTMF/MF digits.
Definition at line 873 of file dsp.c.
References digit_detect_state_t::current_digits, ast_dsp::digit_state, and digit_detect_state_t::digits.
00874 { 00875 if (max > dsp->digit_state.current_digits) 00876 max = dsp->digit_state.current_digits; 00877 if (max > 0) { 00878 memcpy(buf, dsp->digit_state.digits, max); 00879 memmove(dsp->digit_state.digits, dsp->digit_state.digits + max, dsp->digit_state.current_digits - max); 00880 dsp->digit_state.current_digits -= max; 00881 } 00882 buf[max] = '\0'; 00883 return max; 00884 }
| struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1379 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::faxmode, ast_dsp::features, and ast_dsp::threshold.
Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), record_exec(), sip_dtmfmode(), sip_new(), and store_config().
01380 { 01381 struct ast_dsp *dsp; 01382 01383 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01384 dsp->threshold = DEFAULT_THRESHOLD; 01385 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01386 dsp->busycount = DSP_HISTORY; 01387 dsp->digitmode = DSP_DIGITMODE_DTMF; 01388 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01389 /* Initialize digit detector */ 01390 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01391 /* Initialize initial DSP progress detect parameters */ 01392 ast_dsp_prog_reset(dsp); 01393 /* Initialize fax detector */ 01394 ast_fax_detect_init(dsp); 01395 } 01396 return dsp; 01397 }
| 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 1185 of file dsp.c.
References __ast_dsp_call_progress(), __ast_dsp_digitdetect(), __ast_dsp_silence(), 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_frfree, ast_frisolate(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len(), LOG_WARNING, ast_channel::name, ast_frame::src, ast_frame::subclass, and ast_dsp::thinkdigit.
Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), and usbradio_read().
01186 { 01187 int silence; 01188 int res; 01189 int digit; 01190 int x; 01191 short *shortdata; 01192 unsigned char *odata; 01193 int len; 01194 int writeback = 0; 01195 01196 #define FIX_INF(inf) do { \ 01197 if (writeback) { \ 01198 switch (inf->subclass) { \ 01199 case AST_FORMAT_SLINEAR: \ 01200 break; \ 01201 case AST_FORMAT_ULAW: \ 01202 for (x=0;x<len;x++) \ 01203 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01204 break; \ 01205 case AST_FORMAT_ALAW: \ 01206 for (x=0;x<len;x++) \ 01207 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01208 break; \ 01209 } \ 01210 } \ 01211 } while(0) 01212 01213 if (!af) 01214 return NULL; 01215 if (af->frametype != AST_FRAME_VOICE) 01216 return af; 01217 odata = af->data; 01218 len = af->datalen; 01219 /* Make sure we have short data */ 01220 switch (af->subclass) { 01221 case AST_FORMAT_SLINEAR: 01222 shortdata = af->data; 01223 len = af->datalen / 2; 01224 break; 01225 case AST_FORMAT_ULAW: 01226 shortdata = alloca(af->datalen * 2); 01227 for (x = 0;x < len; x++) 01228 shortdata[x] = AST_MULAW(odata[x]); 01229 break; 01230 case AST_FORMAT_ALAW: 01231 shortdata = alloca(af->datalen * 2); 01232 for (x = 0; x < len; x++) 01233 shortdata[x] = AST_ALAW(odata[x]); 01234 break; 01235 default: 01236 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01237 return af; 01238 } 01239 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01240 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01241 memset(&dsp->f, 0, sizeof(dsp->f)); 01242 dsp->f.frametype = AST_FRAME_NULL; 01243 ast_frfree(af); 01244 return ast_frisolate(&dsp->f); 01245 } 01246 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01247 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01248 memset(&dsp->f, 0, sizeof(dsp->f)); 01249 dsp->f.frametype = AST_FRAME_CONTROL; 01250 dsp->f.subclass = AST_CONTROL_BUSY; 01251 ast_frfree(af); 01252 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01253 return ast_frisolate(&dsp->f); 01254 } 01255 if (((dsp->features & DSP_FEATURE_DTMF_DETECT) || (dsp->features & DSP_FEATURE_FAX_DETECT))) { 01256 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01257 #if 0 01258 if (digit) 01259 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01260 #endif 01261 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01262 if (!dsp->thinkdigit) { 01263 if (digit) { 01264 /* Looks like we might have something. 01265 * Request a conference mute for the moment */ 01266 memset(&dsp->f, 0, sizeof(dsp->f)); 01267 dsp->f.frametype = AST_FRAME_DTMF; 01268 dsp->f.subclass = 'm'; 01269 dsp->thinkdigit = 'x'; 01270 FIX_INF(af); 01271 if (chan) 01272 ast_queue_frame(chan, af); 01273 ast_frfree(af); 01274 return ast_frisolate(&dsp->f); 01275 } 01276 } else { 01277 if (digit) { 01278 /* Thought we saw one last time. Pretty sure we really have now */ 01279 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01280 /* If we found a digit, and we're changing digits, go 01281 ahead and send this one, but DON'T stop confmute because 01282 we're detecting something else, too... */ 01283 memset(&dsp->f, 0, sizeof(dsp->f)); 01284 dsp->f.frametype = AST_FRAME_DTMF_END; 01285 dsp->f.subclass = dsp->thinkdigit; 01286 FIX_INF(af); 01287 if (chan) 01288 ast_queue_frame(chan, af); 01289 ast_frfree(af); 01290 } else { 01291 dsp->thinkdigit = digit; 01292 memset(&dsp->f, 0, sizeof(dsp->f)); 01293 dsp->f.frametype = AST_FRAME_DTMF_BEGIN; 01294 dsp->f.subclass = dsp->thinkdigit; 01295 FIX_INF(af); 01296 if (chan) 01297 ast_queue_frame(chan, af); 01298 ast_frfree(af); 01299 } 01300 return ast_frisolate(&dsp->f); 01301 } else { 01302 memset(&dsp->f, 0, sizeof(dsp->f)); 01303 if (dsp->thinkdigit != 'x') { 01304 /* If we found a digit, send it now */ 01305 dsp->f.frametype = AST_FRAME_DTMF_END; 01306 dsp->f.subclass = dsp->thinkdigit; 01307 dsp->thinkdigit = 0; 01308 } else { 01309 dsp->f.frametype = AST_FRAME_DTMF; 01310 dsp->f.subclass = 'u'; 01311 dsp->thinkdigit = 0; 01312 } 01313 FIX_INF(af); 01314 if (chan) 01315 ast_queue_frame(chan, af); 01316 ast_frfree(af); 01317 return ast_frisolate(&dsp->f); 01318 } 01319 } 01320 } else if (dsp->digit_state.current_digits > 1 || 01321 (dsp->digit_state.current_digits == 1 && digit != dsp->digit_state.digits[0])) { 01322 /* Since we basically generate DTMF_END frames we do it only when a digit 01323 has finished. */ 01324 01325 memset(&dsp->f, 0, sizeof(dsp->f)); 01326 dsp->f.frametype = AST_FRAME_DTMF; 01327 dsp->f.subclass = dsp->digit_state.digits[0]; 01328 memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits); 01329 dsp->digit_state.current_digits--; 01330 FIX_INF(af); 01331 if (chan) 01332 ast_queue_frame(chan, af); 01333 ast_frfree(af); 01334 return ast_frisolate(&dsp->f); 01335 } 01336 } 01337 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01338 res = __ast_dsp_call_progress(dsp, shortdata, len); 01339 if (res) { 01340 switch (res) { 01341 case AST_CONTROL_ANSWER: 01342 case AST_CONTROL_BUSY: 01343 case AST_CONTROL_RINGING: 01344 case AST_CONTROL_CONGESTION: 01345 case AST_CONTROL_HANGUP: 01346 memset(&dsp->f, 0, sizeof(dsp->f)); 01347 dsp->f.frametype = AST_FRAME_CONTROL; 01348 dsp->f.subclass = res; 01349 dsp->f.src = "dsp_progress"; 01350 if (chan) 01351 ast_queue_frame(chan, &dsp->f); 01352 break; 01353 default: 01354 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01355 } 01356 } 01357 } 01358 FIX_INF(af); 01359 return af; 01360 }
| static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1362 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().
01363 { 01364 int max = 0; 01365 int x; 01366 01367 dsp->gsamp_size = modes[dsp->progmode].size; 01368 dsp->gsamps = 0; 01369 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01370 if (modes[dsp->progmode].freqs[x]) { 01371 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01372 max = x + 1; 01373 } 01374 } 01375 dsp->freqcount = max; 01376 dsp->ringtimeout= 0; 01377 }
| void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1459 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.
01460 { 01461 int x; 01462 01463 dsp->totalsilence = 0; 01464 dsp->gsamps = 0; 01465 for (x=0;x<4;x++) 01466 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01467 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01468 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01469 dsp->ringtimeout= 0; 01470 }
| void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
| int | cadences | |||
| ) |
Set number of required cadences for busy.
Definition at line 1414 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01415 { 01416 if (cadences < 4) 01417 cadences = 4; 01418 if (cadences > DSP_HISTORY) 01419 cadences = DSP_HISTORY; 01420 dsp->busycount = cadences; 01421 }
| void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
| int | tonelength, | |||
| int | quietlength | |||
| ) |
Set expected lengths of the busy tone.
Definition at line 1423 of file dsp.c.
References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.
Referenced by dahdi_new().
01424 { 01425 dsp->busy_tonelength = tonelength; 01426 dsp->busy_quietlength = quietlength; 01427 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01428 }
| int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
| char * | zone | |||
| ) |
Set zone for doing progress detection.
Definition at line 1496 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
01497 { 01498 int x; 01499 01500 for (x = 0; x < ARRAY_LEN(aliases); x++) { 01501 if (!strcasecmp(aliases[x].name, zone)) { 01502 dsp->progmode = aliases[x].mode; 01503 ast_dsp_prog_reset(dsp); 01504 return 0; 01505 } 01506 } 01507 return -1; 01508 }
| int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
| int | faxmode | |||
| ) |
Set fax mode.
Definition at line 1487 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
01488 { 01489 if (dsp->faxmode != faxmode) { 01490 ast_fax_detect_init(dsp); 01491 } 01492 dsp->faxmode = faxmode; 01493 return 0; 01494 }
| void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
| int | features | |||
| ) |
Select feature set.
Definition at line 1399 of file dsp.c.
References ast_dsp::features.
Referenced by __oh323_new(), dahdi_new(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), and store_config().
| void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
| int | threshold | |||
| ) |
Set threshold value for silence.
Definition at line 1409 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 1167 of file dsp.c.
References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, s, and ast_frame::subclass.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
01168 { 01169 short *s; 01170 int len; 01171 01172 if (f->frametype != AST_FRAME_VOICE) { 01173 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01174 return 0; 01175 } 01176 if (f->subclass != AST_FORMAT_SLINEAR) { 01177 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01178 return 0; 01179 } 01180 s = f->data; 01181 len = f->datalen/2; 01182 return __ast_dsp_silence(dsp, s, len, totalsilence); 01183 }
| static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 417 of file dsp.c.
References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::energy, goertzel_init(), dtmf_detect_state_t::lasthit, and dtmf_detect_state_t::row_out.
Referenced by ast_digit_detect_init().
00418 { 00419 int i; 00420 00421 s->lasthit = 0; 00422 s->current_hit = 0; 00423 for (i = 0; i < 4; i++) { 00424 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00425 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00426 s->energy = 0.0; 00427 } 00428 s->current_sample = 0; 00429 }
| static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 411 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().
00412 { 00413 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00414 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00415 }
| static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 431 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().
00432 { 00433 int i; 00434 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00435 for (i = 0; i < 6; i++) { 00436 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00437 } 00438 s->current_sample = 0; 00439 s->current_hit = 0; 00440 }
| static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
| int | freq, | |||
| int | duration, | |||
| int | amp | |||
| ) | [static] |
Definition at line 351 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().
00352 { 00353 int duration_samples; 00354 float x; 00355 int periods_in_block; 00356 00357 s->freq = freq; 00358 00359 /* Desired tone duration in samples */ 00360 duration_samples = duration * SAMPLE_RATE / 1000; 00361 /* We want to allow 10% deviation of tone duration */ 00362 duration_samples = duration_samples * 9 / 10; 00363 00364 /* If we want to remove tone, it is important to have block size not 00365 to exceed frame size. Otherwise by the moment tone is detected it is too late 00366 to squelch it from previous frames */ 00367 s->block_size = SAMPLES_IN_FRAME; 00368 00369 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00370 00371 /* Make sure we will have at least 5 periods at target frequency for analisys. 00372 This may make block larger than expected packet and will make squelching impossible 00373 but at least we will be detecting the tone */ 00374 if (periods_in_block < 5) 00375 periods_in_block = 5; 00376 00377 /* Now calculate final block size. It will contain integer number of periods */ 00378 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00379 00380 /* tone_detect is currently only used to detect fax tones and we 00381 do not need suqlching the fax tones */ 00382 s->squelch = 0; 00383 00384 /* Account for the first and the last block to be incomplete 00385 and thus no tone will be detected in them */ 00386 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00387 00388 goertzel_init(&s->tone, freq, s->block_size); 00389 00390 s->samples_pending = s->block_size; 00391 s->hit_count = 0; 00392 s->last_hit = 0; 00393 s->energy = 0.0; 00394 00395 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00396 According to Parseval's theorem the energy computed in time domain equals to energy 00397 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00398 from the energy in the time domain we will get energy of the remaining signal (without the tone 00399 we are detecting). We will be checking that 00400 10*log(Ew / (Et - Ew)) > amp 00401 Calculate threshold so that we will be actually checking 00402 Ew > Et * threshold 00403 */ 00404 00405 x = pow(10.0, amp / 10.0); 00406 s->threshold = x / (x + 1); 00407 00408 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00409 }
| static int dtmf_detect | ( | digit_detect_state_t * | s, | |
| int16_t | amp[], | |||
| int | samples, | |||
| int | digitmode, | |||
| int * | writeback | |||
| ) | [static] |
Definition at line 558 of file dsp.c.
References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, DSP_DIGITMODE_NOQUELCH, digit_detect_state_t::dtmf, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::lasthit, dtmf_detect_state_t::row_out, store_digit(), and digit_detect_state_t::td.
Referenced by __ast_dsp_digitdetect().
00560 { 00561 float row_energy[4]; 00562 float col_energy[4]; 00563 float famp; 00564 int i; 00565 int j; 00566 int sample; 00567 int best_row; 00568 int best_col; 00569 int hit; 00570 int limit; 00571 00572 hit = 0; 00573 for (sample = 0; sample < samples; sample = limit) { 00574 /* 102 is optimised to meet the DTMF specs. */ 00575 if ((samples - sample) >= (102 - s->td.dtmf.current_sample)) 00576 limit = sample + (102 - s->td.dtmf.current_sample); 00577 else 00578 limit = samples; 00579 /* The following unrolled loop takes only 35% (rough estimate) of the 00580 time of a rolled loop on the machine on which it was developed */ 00581 for (j = sample; j < limit; j++) { 00582 famp = amp[j]; 00583 s->td.dtmf.energy += famp*famp; 00584 /* With GCC 2.95, the following unrolled code seems to take about 35% 00585 (rough estimate) as long as a neat little 0-3 loop */ 00586 goertzel_sample(s->td.dtmf.row_out, amp[j]); 00587 goertzel_sample(s->td.dtmf.col_out, amp[j]); 00588 goertzel_sample(s->td.dtmf.row_out + 1, amp[j]); 00589 goertzel_sample(s->td.dtmf.col_out + 1, amp[j]); 00590 goertzel_sample(s->td.dtmf.row_out + 2, amp[j]); 00591 goertzel_sample(s->td.dtmf.col_out + 2, amp[j]); 00592 goertzel_sample(s->td.dtmf.row_out + 3, amp[j]); 00593 goertzel_sample(s->td.dtmf.col_out + 3, amp[j]); 00594 } 00595 s->td.dtmf.current_sample += (limit - sample); 00596 if (s->td.dtmf.current_sample < 102) { 00597 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00598 /* If we had a hit last time, go ahead and clear this out since likely it 00599 will be another hit */ 00600 for (i=sample;i<limit;i++) 00601 amp[i] = 0; 00602 *writeback = 1; 00603 } 00604 continue; 00605 } 00606 /* We are at the end of a DTMF detection block */ 00607 /* Find the peak row and the peak column */ 00608 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00609 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00610 00611 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00612 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00613 if (row_energy[i] > row_energy[best_row]) 00614 best_row = i; 00615 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00616 if (col_energy[i] > col_energy[best_col]) 00617 best_col = i; 00618 } 00619 hit = 0; 00620 /* Basic signal level test and the twist test */ 00621 if (row_energy[best_row] >= DTMF_THRESHOLD && 00622 col_energy[best_col] >= DTMF_THRESHOLD && 00623 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00624 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00625 /* Relative peak test */ 00626 for (i = 0; i < 4; i++) { 00627 if ((i != best_col && 00628 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00629 (i != best_row 00630 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00631 break; 00632 } 00633 } 00634 /* ... and fraction of total energy test */ 00635 if (i >= 4 && 00636 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy) { 00637 /* Got a hit */ 00638 hit = dtmf_positions[(best_row << 2) + best_col]; 00639 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00640 /* Zero out frame data if this is part DTMF */ 00641 for (i=sample;i<limit;i++) 00642 amp[i] = 0; 00643 *writeback = 1; 00644 } 00645 } 00646 } 00647 00648 /* The logic in the next test is: 00649 For digits we need two successive identical clean detects, with 00650 something different preceeding it. This can work with 00651 back to back differing digits. More importantly, it 00652 can work with nasty phones that give a very wobbly start 00653 to a digit */ 00654 if (hit != s->td.dtmf.current_hit) { 00655 if (hit && s->td.dtmf.lasthit == hit) { 00656 s->td.dtmf.current_hit = hit; 00657 store_digit(s, hit); 00658 } else if (s->td.dtmf.lasthit != s->td.dtmf.current_hit) { 00659 s->td.dtmf.current_hit = 0; 00660 } 00661 } 00662 s->td.dtmf.lasthit = hit; 00663 00664 /* Reinitialise the detector for the next block */ 00665 for (i = 0; i < 4; i++) { 00666 goertzel_reset(&s->td.dtmf.row_out[i]); 00667 goertzel_reset(&s->td.dtmf.col_out[i]); 00668 } 00669 s->td.dtmf.energy = 0.0; 00670 s->td.dtmf.current_sample = 0; 00671 } 00672 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00673 }
| static void goertzel_init | ( | goertzel_state_t * | s, | |
| float | freq, | |||
| int | samples | |||
| ) | [inline, static] |
Definition at line 310 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().
00311 { 00312 s->v2 = s->v3 = s->chunky = 0.0; 00313 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / SAMPLE_RATE)); 00314 s->samples = samples; 00315 }
| static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 317 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 301 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().
00302 { 00303 goertzel_result_t r; 00304 r.value = (s->v3 * s->v3) + (s->v2 * s->v2); 00305 r.value -= ((s->v2 * s->v3) >> 15) * s->fac; 00306 r.power = s->chunky * 2; 00307 return (float)r.value * (float)(1 << r.power); 00308 }
| static void goertzel_sample | ( | goertzel_state_t * | s, | |
| short | sample | |||
| ) | [inline, static] |
Definition at line 275 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().
00276 { 00277 int v1; 00278 00279 v1 = s->v2; 00280 s->v2 = s->v3; 00281 00282 s->v3 = (s->fac * s->v2) >> 15; 00283 s->v3 = s->v3 - v1 + (sample >> s->chunky); 00284 if (abs(s->v3) > 32768) { 00285 s->chunky++; 00286 s->v3 = s->v3 >> 1; 00287 s->v2 = s->v2 >> 1; 00288 v1 = v1 >> 1; 00289 } 00290 }
| static void goertzel_update | ( | goertzel_state_t * | s, | |
| short * | samps, | |||
| int | count | |||
| ) | [inline, static] |
Definition at line 292 of file dsp.c.
References goertzel_sample().
00293 { 00294 int i; 00295 00296 for (i=0;i<count;i++) 00297 goertzel_sample(s, samps[i]); 00298 }
| static int mf_detect | ( | digit_detect_state_t * | s, | |
| int16_t | amp[], | |||
| int | samples, | |||
| int | digitmode, | |||
| int * | writeback | |||
| ) | [static] |
Definition at line 678 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, DSP_DIGITMODE_NOQUELCH, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.
Referenced by __ast_dsp_digitdetect().
00680 { 00681 float energy[6]; 00682 int best; 00683 int second_best; 00684 float famp; 00685 int i; 00686 int j; 00687 int sample; 00688 int hit; 00689 int limit; 00690 00691 hit = 0; 00692 for (sample = 0; sample < samples; sample = limit) { 00693 /* 80 is optimised to meet the MF specs. */ 00694 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) 00695 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00696 else 00697 limit = samples; 00698 /* The following unrolled loop takes only 35% (rough estimate) of the 00699 time of a rolled loop on the machine on which it was developed */ 00700 for (j = sample; j < limit; j++) { 00701 famp = amp[j]; 00702 /* With GCC 2.95, the following unrolled code seems to take about 35% 00703 (rough estimate) as long as a neat little 0-3 loop */ 00704 goertzel_sample(s->td.mf.tone_out, amp[j]); 00705 goertzel_sample(s->td.mf.tone_out + 1, amp[j]); 00706 goertzel_sample(s->td.mf.tone_out + 2, amp[j]); 00707 goertzel_sample(s->td.mf.tone_out + 3, amp[j]); 00708 goertzel_sample(s->td.mf.tone_out + 4, amp[j]); 00709 goertzel_sample(s->td.mf.tone_out + 5, amp[j]); 00710 } 00711 s->td.mf.current_sample += (limit - sample); 00712 if (s->td.mf.current_sample < MF_GSIZE) { 00713 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00714 /* If we had a hit last time, go ahead and clear this out since likely it 00715 will be another hit */ 00716 for (i=sample;i<limit;i++) 00717 amp[i] = 0; 00718 *writeback = 1; 00719 } 00720 continue; 00721 } 00722 /* We're at the end of an MF detection block. */ 00723 /* Find the two highest energies. The spec says to look for 00724 two tones and two tones only. Taking this literally -ie 00725 only two tones pass the minimum threshold - doesn't work 00726 well. The sinc function mess, due to rectangular windowing 00727 ensure that! Find the two highest energies and ensure they 00728 are considerably stronger than any of the others. */ 00729 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00730 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00731 if (energy[0] > energy[1]) { 00732 best = 0; 00733 second_best = 1; 00734 } else { 00735 best = 1; 00736 second_best = 0; 00737 } 00738 /*endif*/ 00739 for (i=2;i<6;i++) { 00740 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00741 if (energy[i] >= energy[best]) { 00742 second_best = best; 00743 best = i; 00744 } else if (energy[i] >= energy[second_best]) { 00745 second_best = i; 00746 } 00747 } 00748 /* Basic signal level and twist tests */ 00749 hit = 0; 00750 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00751 && energy[best] < energy[second_best]*BELL_MF_TWIST 00752 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00753 /* Relative peak test */ 00754 hit = -1; 00755 for (i=0;i<6;i++) { 00756 if (i != best && i != second_best) { 00757 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00758 /* The best two are not clearly the best */ 00759 hit = 0; 00760 break; 00761 } 00762 } 00763 } 00764 } 00765 if (hit) { 00766 /* Get the values into ascending order */ 00767 if (second_best < best) { 00768 i = best; 00769 best = second_best; 00770 second_best = i; 00771 } 00772 best = best*5 + second_best - 1; 00773 hit = bell_mf_positions[best]; 00774 /* Look for two successive similar results */ 00775 /* The logic in the next test is: 00776 For KP we need 4 successive identical clean detects, with 00777 two blocks of something different preceeding it. For anything 00778 else we need two successive identical clean detects, with 00779 two blocks of something different preceeding it. */ 00780 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00781 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00782 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00783 hit != s->td.mf.hits[0]))) { 00784 store_digit(s, hit); 00785 } 00786 } 00787 00788 00789 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00790 /* Two successive block without a hit terminate current digit */ 00791 s->td.mf.current_hit = 0; 00792 } 00793 00794 s->td.mf.hits[0] = s->td.mf.hits[1]; 00795 s->td.mf.hits[1] = s->td.mf.hits[2]; 00796 s->td.mf.hits[2] = s->td.mf.hits[3]; 00797 s->td.mf.hits[3] = s->td.mf.hits[4]; 00798 s->td.mf.hits[4] = hit; 00799 /* Reinitialise the detector for the next block */ 00800 for (i = 0; i < 6; i++) 00801 goertzel_reset(&s->td.mf.tone_out[i]); 00802 s->td.mf.current_sample = 0; 00803 } 00804 00805 return (s->td.mf.current_hit); /* return the debounced hit */ 00806 }
| static int pair_there | ( | float | p1, | |
| float | p2, | |||
| float | i1, | |||
| float | i2, | |||
| float | e | |||
| ) | [inline, static] |
Definition at line 853 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00854 { 00855 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00856 /* Make sure absolute levels are high enough */ 00857 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 00858 return 0; 00859 /* Amplify ignored stuff */ 00860 i2 *= TONE_THRESH; 00861 i1 *= TONE_THRESH; 00862 e *= TONE_THRESH; 00863 /* Check first tone */ 00864 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 00865 return 0; 00866 /* And second */ 00867 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 00868 return 0; 00869 /* Guess it's there... */ 00870 return 1; 00871 }
| static void store_digit | ( | digit_detect_state_t * | s, | |
| char | digit | |||
| ) | [static] |
Definition at line 546 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 __ast_dsp_digitdetect(), dtmf_detect(), and mf_detect().
00547 { 00548 s->detected_digits++; 00549 if (s->current_digits < MAX_DTMF_DIGITS) { 00550 s->digits[s->current_digits++] = digit; 00551 s->digits[s->current_digits] = '\0'; 00552 } else { 00553 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00554 s->lost_digits++; 00555 } 00556 }
| static int tone_detect | ( | tone_detect_state_t * | s, | |
| int16_t * | amp, | |||
| int | samples, | |||
| int * | writeback | |||
| ) | [static] |
Definition at line 455 of file dsp.c.
References ast_debug, tone_detect_state_t::block_size, 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, 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_dsp_digitdetect().
00457 { 00458 float tone_energy; 00459 int i; 00460 int hit = 0; 00461 int limit; 00462 int res = 0; 00463 int16_t *ptr; 00464 00465 while (1) { 00466 /* Process in blocks. */ 00467 limit = (samples < s->samples_pending) ? samples : s->samples_pending; 00468 00469 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00470 /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ 00471 s->energy += (int32_t) *ptr * (int32_t) *ptr; 00472 00473 goertzel_sample(&s->tone, *ptr); 00474 } 00475 00476 s->samples_pending -= limit; 00477 00478 if (s->samples_pending) { 00479 /* Finished incomplete (last) block */ 00480 if (s->last_hit && s->squelch) { 00481 /* If we had a hit last time, go ahead and clear this out since likely it 00482 will be another hit */ 00483 memset(amp, 0, sizeof(*amp) * limit); 00484 if (writeback) 00485 *writeback = 1; 00486 } 00487 break; 00488 } 00489 00490 00491 tone_energy = goertzel_result(&s->tone); 00492 00493 /* Scale to make comparable */ 00494 tone_energy *= 2.0; 00495 s->energy *= s->block_size; 00496 00497 ast_debug(10, "tone %d, Ew=%f, Et=%f, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy)); 00498 hit = 0; 00499 if (tone_energy > s->energy * s->threshold) { 00500 00501 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00502 hit = 1; 00503 00504 if (s->squelch) { 00505 /* Zero out frame data */ 00506 memset(amp, 0, sizeof(*amp) * limit); 00507 if (writeback) 00508 *writeback = 1; 00509 } 00510 } 00511 00512 if (s->hit_count) 00513 s->hit_count++; 00514 00515 if (hit == s->last_hit) { 00516 if (!hit) { 00517 /* Two successive misses. Tone ended */ 00518 s->hit_count = 0; 00519 } else if (!s->hit_count) { 00520 s->hit_count++; 00521 } 00522 00523 } 00524 00525 if (s->hit_count == s->hits_required) { 00526 ast_debug(1, "%d Hz done detected\n", s->freq); 00527 res = 1; 00528 } 00529 00530 s->last_hit = hit; 00531 00532 /* Reset for the next block */ 00533 goertzel_reset(&s->tone); 00534 00535 /* Advance to the next block */ 00536 s->energy = 0.0; 00537 s->samples_pending = s->block_size; 00538 00539 amp += limit; 00540 samples -= limit; 00541 } 00542 00543 return res; 00544 }
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().
1.5.6