#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 = 8, BUSY_THRESHOLD = 100, BUSY_MIN = 150, BUSY_MAX = 600 } |
enum | freq_index { HZ_350 = 0, HZ_440, HZ_480, HZ_620, HZ_950, HZ_1400, HZ_1800, HZ_425 = 0, HZ_400 = 0 } |
enum | gsamp_size { GSAMP_SIZE_NA = 183, GSAMP_SIZE_CR = 188, GSAMP_SIZE_UK = 160 } |
enum | gsamp_thresh { THRESH_RING = 8, THRESH_TALK = 2, THRESH_BUSY = 4, THRESH_CONGESTION = 4, THRESH_HANGUP = 60, THRESH_RING2ANSWER = 300 } |
enum | prog_mode { PROG_MODE_NA = 0, PROG_MODE_CR, PROG_MODE_UK } |
Functions | |
static int | __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len) |
static int | __ast_dsp_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_frame_freed (struct ast_frame *fr) |
Hint that a frame from a dsp was freed. | |
void | ast_dsp_free (struct ast_dsp *dsp) |
int | ast_dsp_get_tcount (struct ast_dsp *dsp) |
Get tcount (Threshold counter). | |
int | ast_dsp_get_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. | |
ast_dsp * | ast_dsp_new (void) |
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_compare (struct ast_dsp *dsp, int compare) |
Set if silence and noice lengths must be compared for busy. | |
void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences) |
Set number of required cadences for busy. | |
void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy) |
Set expected lengths of the busy tones. | |
int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
Set zone for doing progress detection. | |
int | ast_dsp_set_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 [] |
Steve Underwood <steveu@coppice.org>
Definition in file dsp.c.
#define BELL_MF_RELATIVE_PEAK 12.6 |
#define BELL_MF_THRESHOLD 1.6e9 |
#define BELL_MF_TWIST 4.0 |
#define 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 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 pair_there().
enum busy_detect |
Definition at line 109 of file dsp.c.
00109 { 00110 BUSY_PERCENT = 10, /*!< The percentage difference between the two last tone periods */ 00111 BUSY_PAT_PERCENT = 8, /*!< 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 = 150, /*!< Busy must be at least 150 ms in half-cadence */ 00114 BUSY_MAX = 600 /*!< Busy can't be longer than 600 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 889 of file dsp.c.
References DSP_TONE_STATE_BUSY, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_350, HZ_440, HZ_480, HZ_620, pair_there(), pass, PROG_MODE_NA, and ast_dsp::progmode.
Referenced by ast_dsp_call_progress(), and ast_dsp_process().
00890 { 00891 int x; 00892 int y; 00893 int pass; 00894 int newstate = DSP_TONE_STATE_SILENCE; 00895 int res = 0; 00896 while (len) { 00897 /* Take the lesser of the number of samples we need and what we have */ 00898 pass = len; 00899 if (pass > dsp->gsamp_size - dsp->gsamps) 00900 pass = dsp->gsamp_size - dsp->gsamps; 00901 for (x=0;x<pass;x++) { 00902 for (y=0;y<dsp->freqcount;y++) 00903 goertzel_sample(&dsp->freqs[y], s[x]); 00904 dsp->genergy += s[x] * s[x]; 00905 } 00906 s += pass; 00907 dsp->gsamps += pass; 00908 len -= pass; 00909 if (dsp->gsamps == dsp->gsamp_size) { 00910 float hz[7]; 00911 for (y=0;y<7;y++) 00912 hz[y] = goertzel_result(&dsp->freqs[y]); 00913 switch (dsp->progmode) { 00914 case PROG_MODE_NA: 00915 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 00916 newstate = DSP_TONE_STATE_BUSY; 00917 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 00918 newstate = DSP_TONE_STATE_RINGING; 00919 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 00920 newstate = DSP_TONE_STATE_DIALTONE; 00921 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 00922 newstate = DSP_TONE_STATE_SPECIAL1; 00923 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 00924 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 00925 newstate = DSP_TONE_STATE_SPECIAL2; 00926 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 00927 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 00928 newstate = DSP_TONE_STATE_SPECIAL3; 00929 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00930 newstate = DSP_TONE_STATE_TALKING; 00931 } else 00932 newstate = DSP_TONE_STATE_SILENCE; 00933 break; 00934 case PROG_MODE_CR: 00935 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 00936 newstate = DSP_TONE_STATE_RINGING; 00937 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 00938 newstate = DSP_TONE_STATE_TALKING; 00939 } else 00940 newstate = DSP_TONE_STATE_SILENCE; 00941 break; 00942 case PROG_MODE_UK: 00943 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 00944 newstate = DSP_TONE_STATE_HUNGUP; 00945 } 00946 break; 00947 default: 00948 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 00949 } 00950 if (newstate == dsp->tstate) { 00951 dsp->tcount++; 00952 if (dsp->ringtimeout) 00953 dsp->ringtimeout++; 00954 switch (dsp->tstate) { 00955 case DSP_TONE_STATE_RINGING: 00956 if ((dsp->features & DSP_PROGRESS_RINGING) && 00957 (dsp->tcount==THRESH_RING)) { 00958 res = AST_CONTROL_RINGING; 00959 dsp->ringtimeout= 1; 00960 } 00961 break; 00962 case DSP_TONE_STATE_BUSY: 00963 if ((dsp->features & DSP_PROGRESS_BUSY) && 00964 (dsp->tcount==THRESH_BUSY)) { 00965 res = AST_CONTROL_BUSY; 00966 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00967 } 00968 break; 00969 case DSP_TONE_STATE_TALKING: 00970 if ((dsp->features & DSP_PROGRESS_TALK) && 00971 (dsp->tcount==THRESH_TALK)) { 00972 res = AST_CONTROL_ANSWER; 00973 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00974 } 00975 break; 00976 case DSP_TONE_STATE_SPECIAL3: 00977 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 00978 (dsp->tcount==THRESH_CONGESTION)) { 00979 res = AST_CONTROL_CONGESTION; 00980 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00981 } 00982 break; 00983 case DSP_TONE_STATE_HUNGUP: 00984 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 00985 (dsp->tcount==THRESH_HANGUP)) { 00986 res = AST_CONTROL_HANGUP; 00987 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00988 } 00989 break; 00990 } 00991 if (dsp->ringtimeout==THRESH_RING2ANSWER) { 00992 ast_debug(1, "Consider call as answered because of timeout after last ring\n"); 00993 res = AST_CONTROL_ANSWER; 00994 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 00995 } 00996 } else { 00997 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 00998 ast_debug(5, "Start state %d\n", newstate); 00999 dsp->tstate = newstate; 01000 dsp->tcount = 1; 01001 } 01002 01003 /* Reset goertzel */ 01004 for (x=0;x<7;x++) 01005 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01006 dsp->gsamps = 0; 01007 dsp->genergy = 0.0; 01008 } 01009 } 01010 01011 return res; 01012 }
static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | writeback | |||
) | [static] |
Definition at line 811 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().
00812 { 00813 int res = 0; 00814 00815 if ((dsp->features & DSP_FEATURE_DTMF_DETECT) && (dsp->digitmode & DSP_DIGITMODE_MF)) 00816 res = mf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00817 else if (dsp->features & DSP_FEATURE_DTMF_DETECT) 00818 res = dtmf_detect(&dsp->digit_state, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00819 00820 if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CNG)) { 00821 if (tone_detect(&dsp->cng_tone_state, s, len, NULL)) { 00822 store_digit(&dsp->digit_state, 'f'); 00823 res = 'f'; 00824 } 00825 } 00826 00827 if ((dsp->features & DSP_FEATURE_FAX_DETECT) && (dsp->faxmode & DSP_FAXMODE_DETECT_CED)) { 00828 if (tone_detect(&dsp->ced_tone_state, s, len, NULL)) { 00829 store_digit(&dsp->digit_state, 'e'); 00830 res = 'e'; 00831 } 00832 } 00833 00834 return res; 00835 }
static int __ast_dsp_silence | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence | |||
) | [static] |
Definition at line 1027 of file dsp.c.
References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::totalnoise, and ast_dsp::totalsilence.
Referenced by ast_dsp_process(), and ast_dsp_silence().
01028 { 01029 int accum; 01030 int x; 01031 int res = 0; 01032 01033 if (!len) 01034 return 0; 01035 accum = 0; 01036 for (x=0;x<len; x++) 01037 accum += abs(s[x]); 01038 accum /= len; 01039 if (accum < dsp->threshold) { 01040 /* Silent */ 01041 dsp->totalsilence += len/8; 01042 #ifdef DEBUG_DSP_BUSYDETECT 01043 fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum); 01044 #endif 01045 if (dsp->totalnoise) { 01046 /* Move and save history */ 01047 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicnoise[0])); 01048 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01049 /* check if previous tone differs BUSY_PERCENT from the one before it */ 01050 int tone1 = dsp->historicnoise[DSP_HISTORY - 1]; 01051 int tone2 = dsp->historicnoise[DSP_HISTORY - 2]; 01052 if (tone1 < tone2) { 01053 if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2) 01054 dsp->busymaybe = 1; 01055 else 01056 dsp->busymaybe = 0; 01057 } else { 01058 if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2) 01059 dsp->busymaybe = 1; 01060 else 01061 dsp->busymaybe = 0; 01062 } 01063 } 01064 dsp->totalnoise = 0; 01065 res = 1; 01066 } else { 01067 /* Not silent */ 01068 dsp->totalnoise += len/8; 01069 #ifdef DEBUG_DSP_BUSYDETECT 01070 fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum); 01071 #endif 01072 if (dsp->totalsilence) { 01073 /* Move and save history */ 01074 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicsilence[0])); 01075 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01076 } 01077 dsp->totalsilence = 0; 01078 } 01079 if (totalsilence) 01080 *totalsilence = dsp->totalsilence; 01081 return res; 01082 }
static void ast_digit_detect_init | ( | digit_detect_state_t * | s, | |
int | mf | |||
) | [static] |
Definition at line 445 of file dsp.c.
References ast_dtmf_detect_init(), ast_mf_detect_init(), and s.
Referenced by ast_dsp_digitmode(), and ast_dsp_new().
00446 { 00447 s->current_digits = 0; 00448 s->detected_digits = 0; 00449 s->lost_digits = 0; 00450 s->digits[0] = '\0'; 00451 00452 if (mf) 00453 ast_mf_detect_init(&s->td.mf); 00454 else 00455 ast_dtmf_detect_init(&s->td.dtmf); 00456 }
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 1084 of file dsp.c.
References ast_log(), buf, BUSY_MAX, BUSY_MIN, ast_dsp::busy_pattern_fuzzy, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busymaybe, ast_dsp::busytoneonly, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and option_debug.
Referenced by ast_dsp_process().
01085 { 01086 int res = 0, x; 01087 int avgsilence = 0, hitsilence = 0; 01088 int avgtone = 0, hittone = 0; 01089 #ifdef DEBUG_DSP_BUSYDETECT 01090 char buf[16]; 01091 char silence_list[64]="", tone_list[64]=""; 01092 #endif 01093 01094 if (!dsp->busymaybe) 01095 return res; 01096 dsp->busymaybe = 0; 01097 01098 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01099 avgsilence += dsp->historicsilence[x]; 01100 avgtone += dsp->historicnoise[x]; 01101 } 01102 avgsilence /= dsp->busycount; 01103 avgtone /= dsp->busycount; 01104 #ifdef DEBUG_DSP_BUSYDETECT 01105 sprintf(silence_list,"Silences: "); 01106 sprintf(tone_list,"Tones: "); 01107 #endif 01108 for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) { 01109 #ifdef DEBUG_DSP_BUSYDETECT 01110 snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]); 01111 strcat(silence_list, buf); 01112 snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]); 01113 strcat(tone_list, buf); 01114 #endif 01115 if (!dsp->busytoneonly) { 01116 if (avgsilence > dsp->historicsilence[x]) { 01117 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01118 hitsilence++; 01119 } else { 01120 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01121 hitsilence++; 01122 } 01123 } 01124 if (avgtone > dsp->historicnoise[x]) { 01125 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01126 hittone++; 01127 } else { 01128 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01129 hittone++; 01130 } 01131 } 01132 #ifdef DEBUG_DSP_BUSYDETECT 01133 fprintf(stderr, "BUSY DETECTOR\n"); 01134 fprintf(stderr, "%s\n", tone_list); 01135 fprintf(stderr, "%s\n", silence_list) 01136 #endif 01137 if ((dsp->busytoneonly || 01138 (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) && 01139 (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01140 if (dsp->busycompare) { 01141 if (dsp->busytoneonly) { 01142 res = 1; 01143 ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare"); 01144 } else { 01145 if (avgtone > avgsilence) { 01146 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01147 res = 1; 01148 } else { 01149 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01150 res = 1; 01151 } 01152 } 01153 } else { 01154 res = 1; 01155 } 01156 } 01157 /* If we know the expected busy tone length, check we are in the range */ 01158 if (res && (dsp->busy_tonelength > 0)) { 01159 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) { 01160 #ifdef BUSYDETECT_DEBUG 01161 if(option_debug) { 01162 ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength); 01163 } 01164 #endif 01165 res = 0; 01166 } 01167 } 01168 /* If we know the expected busy tone silent-period length, check we are in the range */ 01169 if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) { 01170 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) { 01171 #ifdef BUSYDETECT_DEBUG 01172 if(option_debug) { 01173 ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength); 01174 } 01175 #endif 01176 res = 0; 01177 } 01178 } 01179 if (res) { 01180 if (option_debug) 01181 ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01182 } else { 01183 if (option_debug) 01184 ast_log(LOG_NOTICE, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01185 } 01186 return res; 01187 }
Scans for progress indication in audio.
Definition at line 1014 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.
01015 { 01016 if (inf->frametype != AST_FRAME_VOICE) { 01017 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01018 return 0; 01019 } 01020 if (inf->subclass != AST_FORMAT_SLINEAR) { 01021 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01022 return 0; 01023 } 01024 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01025 }
Return non-zero if DTMF hit was found.
Definition at line 837 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.
00838 { 00839 short *s; 00840 int len; 00841 int ign=0; 00842 00843 if (inf->frametype != AST_FRAME_VOICE) { 00844 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00845 return 0; 00846 } 00847 if (inf->subclass != AST_FORMAT_SLINEAR) { 00848 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00849 return 0; 00850 } 00851 s = inf->data; 00852 len = inf->datalen / 2; 00853 return __ast_dsp_digitdetect(dsp, s, len, &ign); 00854 }
int ast_dsp_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1541 of file dsp.c.
References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_setoption(), mgcp_new(), sip_new(), ss_thread(), and store_config().
01542 { 01543 int new; 01544 int old; 01545 01546 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01547 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01548 if (old != new) { 01549 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01550 ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); 01551 } 01552 dsp->digitmode = digitmode; 01553 return 0; 01554 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1499 of file dsp.c.
References digit_detect_state_t::current_digits, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, goertzel_reset(), digit_detect_state_t::mf, s, digit_detect_state_t::td, and ast_dsp::thinkdigit.
Referenced by ss_thread().
01500 { 01501 int i; 01502 01503 dsp->thinkdigit = 0; 01504 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01505 mf_detect_state_t *s = &dsp->digit_state.td.mf; 01506 /* Reinitialise the detector for the next block */ 01507 for (i = 0; i < 6; i++) { 01508 goertzel_reset(&s->tone_out[i]); 01509 } 01510 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; 01511 s->current_sample = 0; 01512 } else { 01513 dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; 01514 /* Reinitialise the detector for the next block */ 01515 for (i = 0; i < 4; i++) { 01516 goertzel_reset(&s->row_out[i]); 01517 goertzel_reset(&s->col_out[i]); 01518 } 01519 s->lasthit = s->current_hit = 0; 01520 s->energy = 0.0; 01521 s->current_sample = 0; 01522 } 01523 01524 dsp->digit_state.digits[0] = '\0'; 01525 dsp->digit_state.current_digits = 0; 01526 }
void ast_dsp_frame_freed | ( | struct ast_frame * | fr | ) |
Hint that a frame from a dsp was freed.
This is called from ast_frame_free if AST_FRFLAG_FROM_DSP is set. This occurs because it is possible for the dsp to be freed while someone still holds a reference to the frame that is in that dsp. This has been known to happen when the dsp on a DAHDI channel detects a busy signal. The channel is hung up, and the application that read the frame to begin with still has a reference to the frame.
Definition at line 1589 of file dsp.c.
References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, f, and ast_dsp::freqcount.
Referenced by __frame_free().
01590 { 01591 struct ast_dsp *dsp; 01592 01593 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP); 01594 01595 dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f)); 01596 01597 if (dsp->freqcount != -1) 01598 return; 01599 01600 ast_dsp_free(dsp); 01601 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1446 of file dsp.c.
References ast_free, AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::f, and ast_dsp::freqcount.
Referenced by __ast_play_and_record(), __oh323_destroy(), ast_dsp_frame_freed(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), dahdi_hangup(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), ss_thread(), transmit_audio(), and unload_module().
01447 { 01448 if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) { 01449 /* If this flag is still set, that means that the dsp's destruction 01450 * been torn down, while we still have a frame out there being used. 01451 * When ast_frfree() gets called on that frame, this ast_trans_pvt 01452 * will get destroyed, too. */ 01453 01454 /* Set the magic flag to destroy the dsp when the frame is freed */ 01455 dsp->freqcount = -1; 01456 01457 return; 01458 } 01459 ast_free(dsp); 01460 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1584 of file dsp.c.
References ast_dsp::tcount.
01585 { 01586 return dsp->tcount; 01587 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1579 of file dsp.c.
References ast_dsp::tstate.
01580 { 01581 return dsp->tstate; 01582 }
int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, | |
char * | buf, | |||
int | max | |||
) |
Get pending DTMF/MF digits.
Definition at line 876 of file dsp.c.
References digit_detect_state_t::current_digits, ast_dsp::digit_state, and digit_detect_state_t::digits.
00877 { 00878 if (max > dsp->digit_state.current_digits) 00879 max = dsp->digit_state.current_digits; 00880 if (max > 0) { 00881 memcpy(buf, dsp->digit_state.digits, max); 00882 memmove(dsp->digit_state.digits, dsp->digit_state.digits + max, dsp->digit_state.current_digits - max); 00883 dsp->digit_state.current_digits -= max; 00884 } 00885 buf[max] = '\0'; 00886 return max; 00887 }
struct ast_dsp* ast_dsp_new | ( | void | ) |
Definition at line 1407 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and ast_dsp::threshold.
Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), dahdi_new(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), store_config(), and transmit_audio().
01408 { 01409 struct ast_dsp *dsp; 01410 01411 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01412 dsp->threshold = DEFAULT_THRESHOLD; 01413 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01414 dsp->busycount = DSP_HISTORY; 01415 dsp->digitmode = DSP_DIGITMODE_DTMF; 01416 dsp->faxmode = DSP_FAXMODE_DETECT_CNG; 01417 dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT; 01418 #ifdef BUSYDETECT_TONEONLY 01419 dsp->busytoneonly = 1; 01420 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01421 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE"); 01422 #endif 01423 #else 01424 dsp->busytoneonly = 0; 01425 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01426 dsp->busycompare = 1; 01427 #else 01428 dsp->busycompare = 0; 01429 #endif 01430 #endif 01431 /* Initialize digit detector */ 01432 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); 01433 /* Initialize initial DSP progress detect parameters */ 01434 ast_dsp_prog_reset(dsp); 01435 /* Initialize fax detector */ 01436 ast_fax_detect_init(dsp); 01437 } 01438 return dsp; 01439 }
struct ast_frame* ast_dsp_process | ( | struct ast_channel * | chan, | |
struct ast_dsp * | dsp, | |||
struct ast_frame * | af | |||
) |
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
Definition at line 1207 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_FRFLAG_FROM_DSP, ast_frfree, ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, chan, 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(), transmit_audio(), and usbradio_read().
01208 { 01209 int silence; 01210 int res; 01211 int digit; 01212 int x; 01213 short *shortdata; 01214 unsigned char *odata; 01215 int len; 01216 int writeback = 0; 01217 01218 #define FIX_INF(inf) do { \ 01219 if (writeback) { \ 01220 switch (inf->subclass) { \ 01221 case AST_FORMAT_SLINEAR: \ 01222 break; \ 01223 case AST_FORMAT_ULAW: \ 01224 for (x=0;x<len;x++) \ 01225 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01226 break; \ 01227 case AST_FORMAT_ALAW: \ 01228 for (x=0;x<len;x++) \ 01229 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01230 break; \ 01231 } \ 01232 } \ 01233 } while(0) 01234 01235 if (!af) 01236 return NULL; 01237 if (af->frametype != AST_FRAME_VOICE) 01238 return af; 01239 odata = af->data; 01240 len = af->datalen; 01241 /* Make sure we have short data */ 01242 switch (af->subclass) { 01243 case AST_FORMAT_SLINEAR: 01244 shortdata = af->data; 01245 len = af->datalen / 2; 01246 break; 01247 case AST_FORMAT_ULAW: 01248 shortdata = alloca(af->datalen * 2); 01249 for (x = 0;x < len; x++) 01250 shortdata[x] = AST_MULAW(odata[x]); 01251 break; 01252 case AST_FORMAT_ALAW: 01253 shortdata = alloca(af->datalen * 2); 01254 for (x = 0; x < len; x++) 01255 shortdata[x] = AST_ALAW(odata[x]); 01256 break; 01257 default: 01258 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01259 return af; 01260 } 01261 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01262 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01263 memset(&dsp->f, 0, sizeof(dsp->f)); 01264 dsp->f.frametype = AST_FRAME_NULL; 01265 ast_frfree(af); 01266 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01267 return &dsp->f; 01268 } 01269 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01270 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01271 memset(&dsp->f, 0, sizeof(dsp->f)); 01272 dsp->f.frametype = AST_FRAME_CONTROL; 01273 dsp->f.subclass = AST_CONTROL_BUSY; 01274 ast_frfree(af); 01275 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01276 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01277 return &dsp->f; 01278 } 01279 if (((dsp->features & DSP_FEATURE_DTMF_DETECT) || (dsp->features & DSP_FEATURE_FAX_DETECT))) { 01280 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01281 #if 0 01282 if (digit) 01283 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01284 #endif 01285 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01286 if (!dsp->thinkdigit) { 01287 if (digit) { 01288 /* Looks like we might have something. 01289 * Request a conference mute for the moment */ 01290 memset(&dsp->f, 0, sizeof(dsp->f)); 01291 dsp->f.frametype = AST_FRAME_DTMF; 01292 dsp->f.subclass = 'm'; 01293 dsp->thinkdigit = 'x'; 01294 FIX_INF(af); 01295 if (chan) 01296 ast_queue_frame(chan, af); 01297 ast_frfree(af); 01298 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01299 return &dsp->f; 01300 } 01301 } else { 01302 if (digit) { 01303 /* Thought we saw one last time. Pretty sure we really have now */ 01304 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01305 /* If we found a digit, and we're changing digits, go 01306 ahead and send this one, but DON'T stop confmute because 01307 we're detecting something else, too... */ 01308 memset(&dsp->f, 0, sizeof(dsp->f)); 01309 dsp->f.frametype = AST_FRAME_DTMF_END; 01310 dsp->f.subclass = dsp->thinkdigit; 01311 FIX_INF(af); 01312 if (chan) 01313 ast_queue_frame(chan, af); 01314 ast_frfree(af); 01315 } else { 01316 dsp->thinkdigit = digit; 01317 memset(&dsp->f, 0, sizeof(dsp->f)); 01318 dsp->f.frametype = AST_FRAME_DTMF_BEGIN; 01319 dsp->f.subclass = dsp->thinkdigit; 01320 FIX_INF(af); 01321 if (chan) 01322 ast_queue_frame(chan, af); 01323 ast_frfree(af); 01324 } 01325 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01326 return &dsp->f; 01327 } else { 01328 memset(&dsp->f, 0, sizeof(dsp->f)); 01329 if (dsp->thinkdigit != 'x') { 01330 /* If we found a digit, send it now */ 01331 dsp->f.frametype = AST_FRAME_DTMF_END; 01332 dsp->f.subclass = dsp->thinkdigit; 01333 dsp->thinkdigit = 0; 01334 } else { 01335 dsp->f.frametype = AST_FRAME_DTMF; 01336 dsp->f.subclass = 'u'; 01337 dsp->thinkdigit = 0; 01338 } 01339 FIX_INF(af); 01340 if (chan) 01341 ast_queue_frame(chan, af); 01342 ast_frfree(af); 01343 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01344 return &dsp->f; 01345 } 01346 } 01347 } else if (dsp->digit_state.current_digits > 1 || 01348 (dsp->digit_state.current_digits == 1 && digit != dsp->digit_state.digits[0])) { 01349 /* Since we basically generate DTMF_END frames we do it only when a digit 01350 has finished. */ 01351 01352 memset(&dsp->f, 0, sizeof(dsp->f)); 01353 dsp->f.frametype = AST_FRAME_DTMF; 01354 dsp->f.subclass = dsp->digit_state.digits[0]; 01355 memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits); 01356 dsp->digit_state.current_digits--; 01357 FIX_INF(af); 01358 if (chan) 01359 ast_queue_frame(chan, af); 01360 ast_frfree(af); 01361 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01362 return &dsp->f; 01363 } 01364 } 01365 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01366 res = __ast_dsp_call_progress(dsp, shortdata, len); 01367 if (res) { 01368 switch (res) { 01369 case AST_CONTROL_ANSWER: 01370 case AST_CONTROL_BUSY: 01371 case AST_CONTROL_RINGING: 01372 case AST_CONTROL_CONGESTION: 01373 case AST_CONTROL_HANGUP: 01374 memset(&dsp->f, 0, sizeof(dsp->f)); 01375 dsp->f.frametype = AST_FRAME_CONTROL; 01376 dsp->f.subclass = res; 01377 dsp->f.src = "dsp_progress"; 01378 if (chan) 01379 ast_queue_frame(chan, &dsp->f); 01380 break; 01381 default: 01382 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01383 } 01384 } 01385 } 01386 FIX_INF(af); 01387 return af; 01388 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1390 of file dsp.c.
References ARRAY_LEN, ast_dsp::freqcount, ast_dsp::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, ast_dsp::ringtimeout, and progress::size.
Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().
01391 { 01392 int max = 0; 01393 int x; 01394 01395 dsp->gsamp_size = modes[dsp->progmode].size; 01396 dsp->gsamps = 0; 01397 for (x = 0; x < ARRAY_LEN(modes[dsp->progmode].freqs); x++) { 01398 if (modes[dsp->progmode].freqs[x]) { 01399 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01400 max = x + 1; 01401 } 01402 } 01403 dsp->freqcount = max; 01404 dsp->ringtimeout= 0; 01405 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1528 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.
01529 { 01530 int x; 01531 01532 dsp->totalsilence = 0; 01533 dsp->gsamps = 0; 01534 for (x=0;x<4;x++) 01535 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01536 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01537 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01538 dsp->ringtimeout= 0; 01539 }
void ast_dsp_set_busy_compare | ( | struct ast_dsp * | dsp, | |
int | compare | |||
) |
Set if silence and noice lengths must be compared for busy.
Definition at line 1479 of file dsp.c.
References ast_dsp::busycompare.
Referenced by dahdi_new().
01480 { 01481 if (compare > 0) 01482 dsp->busycompare = 1; 01483 else 01484 dsp->busycompare = 0; 01485 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1470 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01471 { 01472 if (cadences < 4) 01473 cadences = 4; 01474 if (cadences > DSP_HISTORY) 01475 cadences = DSP_HISTORY; 01476 dsp->busycount = cadences; 01477 }
void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
int | tonelength, | |||
int | quietlength, | |||
int | fuzzy | |||
) |
Set expected lengths of the busy tones.
Definition at line 1487 of file dsp.c.
References ast_debug, ast_dsp::busy_pattern_fuzzy, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and ast_dsp::busytoneonly.
Referenced by dahdi_new().
01488 { 01489 dsp->busy_tonelength = tonelength; 01490 if (quietlength > 0) 01491 dsp->busy_quietlength = quietlength; 01492 else 01493 dsp->busytoneonly = 1; 01494 ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01495 if( fuzzy > 0 && fuzzy < 50 ) 01496 dsp->busy_pattern_fuzzy = fuzzy; 01497 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1565 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
01566 { 01567 int x; 01568 01569 for (x = 0; x < ARRAY_LEN(aliases); x++) { 01570 if (!strcasecmp(aliases[x].name, zone)) { 01571 dsp->progmode = aliases[x].mode; 01572 ast_dsp_prog_reset(dsp); 01573 return 0; 01574 } 01575 } 01576 return -1; 01577 }
int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, | |
int | faxmode | |||
) |
Set fax mode.
Definition at line 1556 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
Referenced by transmit_audio().
01557 { 01558 if (dsp->faxmode != faxmode) { 01559 ast_fax_detect_init(dsp); 01560 } 01561 dsp->faxmode = faxmode; 01562 return 0; 01563 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1441 of file dsp.c.
References ast_dsp::features.
Referenced by __oh323_new(), dahdi_new(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), store_config(), and transmit_audio().
void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
int | threshold | |||
) |
Set threshold value for silence.
Definition at line 1462 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), dahdi_new(), do_waiting(), handle_recordfile(), and isAnsweringMachine().
01463 { 01464 if (threshold < 256) 01465 dsp->threshold = 256; 01466 else 01467 dsp->threshold = threshold; 01468 }
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1189 of file dsp.c.
References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len(), LOG_WARNING, and s.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), and isAnsweringMachine().
01190 { 01191 short *s; 01192 int len; 01193 01194 if (f->frametype != AST_FRAME_VOICE) { 01195 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01196 return 0; 01197 } 01198 if (f->subclass != AST_FORMAT_SLINEAR) { 01199 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01200 return 0; 01201 } 01202 s = f->data; 01203 len = f->datalen/2; 01204 return __ast_dsp_silence(dsp, s, len, totalsilence); 01205 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 420 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_digit_detect_init().
00421 { 00422 int i; 00423 00424 s->lasthit = 0; 00425 s->current_hit = 0; 00426 for (i = 0; i < 4; i++) { 00427 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00428 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00429 s->energy = 0.0; 00430 } 00431 s->current_sample = 0; 00432 }
static void ast_fax_detect_init | ( | struct ast_dsp * | s | ) | [static] |
Definition at line 414 of file dsp.c.
References ast_tone_detect_init(), FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_FREQ, and s.
Referenced by ast_dsp_new(), and ast_dsp_set_faxmode().
00415 { 00416 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB); 00417 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB); 00418 }
static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 434 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_digit_detect_init().
00435 { 00436 int i; 00437 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00438 for (i = 0; i < 6; i++) { 00439 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00440 } 00441 s->current_sample = 0; 00442 s->current_hit = 0; 00443 }
static void ast_tone_detect_init | ( | tone_detect_state_t * | s, | |
int | freq, | |||
int | duration, | |||
int | amp | |||
) | [static] |
Definition at line 354 of file dsp.c.
References ast_debug, goertzel_init(), s, SAMPLE_RATE, and SAMPLES_IN_FRAME.
Referenced by ast_fax_detect_init().
00355 { 00356 int duration_samples; 00357 float x; 00358 int periods_in_block; 00359 00360 s->freq = freq; 00361 00362 /* Desired tone duration in samples */ 00363 duration_samples = duration * SAMPLE_RATE / 1000; 00364 /* We want to allow 10% deviation of tone duration */ 00365 duration_samples = duration_samples * 9 / 10; 00366 00367 /* If we want to remove tone, it is important to have block size not 00368 to exceed frame size. Otherwise by the moment tone is detected it is too late 00369 to squelch it from previous frames */ 00370 s->block_size = SAMPLES_IN_FRAME; 00371 00372 periods_in_block = s->block_size * freq / SAMPLE_RATE; 00373 00374 /* Make sure we will have at least 5 periods at target frequency for analisys. 00375 This may make block larger than expected packet and will make squelching impossible 00376 but at least we will be detecting the tone */ 00377 if (periods_in_block < 5) 00378 periods_in_block = 5; 00379 00380 /* Now calculate final block size. It will contain integer number of periods */ 00381 s->block_size = periods_in_block * SAMPLE_RATE / freq; 00382 00383 /* tone_detect is currently only used to detect fax tones and we 00384 do not need suqlching the fax tones */ 00385 s->squelch = 0; 00386 00387 /* Account for the first and the last block to be incomplete 00388 and thus no tone will be detected in them */ 00389 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size; 00390 00391 goertzel_init(&s->tone, freq, s->block_size); 00392 00393 s->samples_pending = s->block_size; 00394 s->hit_count = 0; 00395 s->last_hit = 0; 00396 s->energy = 0.0; 00397 00398 /* We want tone energy to be amp decibels above the rest of the signal (the noise). 00399 According to Parseval's theorem the energy computed in time domain equals to energy 00400 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result) 00401 from the energy in the time domain we will get energy of the remaining signal (without the tone 00402 we are detecting). We will be checking that 00403 10*log(Ew / (Et - Ew)) > amp 00404 Calculate threshold so that we will be actually checking 00405 Ew > Et * threshold 00406 */ 00407 00408 x = pow(10.0, amp / 10.0); 00409 s->threshold = x / (x + 1); 00410 00411 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required); 00412 }
static int dtmf_detect | ( | digit_detect_state_t * | s, | |
int16_t | amp[], | |||
int | samples, | |||
int | digitmode, | |||
int * | writeback | |||
) | [static] |
Definition at line 561 of file dsp.c.
References DSP_DIGITMODE_NOQUELCH, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, goertzel_result(), goertzel_sample(), s, and store_digit().
Referenced by __ast_dsp_digitdetect().
00563 { 00564 float row_energy[4]; 00565 float col_energy[4]; 00566 float famp; 00567 int i; 00568 int j; 00569 int sample; 00570 int best_row; 00571 int best_col; 00572 int hit; 00573 int limit; 00574 00575 hit = 0; 00576 for (sample = 0; sample < samples; sample = limit) { 00577 /* 102 is optimised to meet the DTMF specs. */ 00578 if ((samples - sample) >= (102 - s->td.dtmf.current_sample)) 00579 limit = sample + (102 - s->td.dtmf.current_sample); 00580 else 00581 limit = samples; 00582 /* The following unrolled loop takes only 35% (rough estimate) of the 00583 time of a rolled loop on the machine on which it was developed */ 00584 for (j = sample; j < limit; j++) { 00585 famp = amp[j]; 00586 s->td.dtmf.energy += famp*famp; 00587 /* With GCC 2.95, the following unrolled code seems to take about 35% 00588 (rough estimate) as long as a neat little 0-3 loop */ 00589 goertzel_sample(s->td.dtmf.row_out, amp[j]); 00590 goertzel_sample(s->td.dtmf.col_out, amp[j]); 00591 goertzel_sample(s->td.dtmf.row_out + 1, amp[j]); 00592 goertzel_sample(s->td.dtmf.col_out + 1, amp[j]); 00593 goertzel_sample(s->td.dtmf.row_out + 2, amp[j]); 00594 goertzel_sample(s->td.dtmf.col_out + 2, amp[j]); 00595 goertzel_sample(s->td.dtmf.row_out + 3, amp[j]); 00596 goertzel_sample(s->td.dtmf.col_out + 3, amp[j]); 00597 } 00598 s->td.dtmf.current_sample += (limit - sample); 00599 if (s->td.dtmf.current_sample < 102) { 00600 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00601 /* If we had a hit last time, go ahead and clear this out since likely it 00602 will be another hit */ 00603 for (i=sample;i<limit;i++) 00604 amp[i] = 0; 00605 *writeback = 1; 00606 } 00607 continue; 00608 } 00609 /* We are at the end of a DTMF detection block */ 00610 /* Find the peak row and the peak column */ 00611 row_energy[0] = goertzel_result (&s->td.dtmf.row_out[0]); 00612 col_energy[0] = goertzel_result (&s->td.dtmf.col_out[0]); 00613 00614 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00615 row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); 00616 if (row_energy[i] > row_energy[best_row]) 00617 best_row = i; 00618 col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); 00619 if (col_energy[i] > col_energy[best_col]) 00620 best_col = i; 00621 } 00622 hit = 0; 00623 /* Basic signal level test and the twist test */ 00624 if (row_energy[best_row] >= DTMF_THRESHOLD && 00625 col_energy[best_col] >= DTMF_THRESHOLD && 00626 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00627 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00628 /* Relative peak test */ 00629 for (i = 0; i < 4; i++) { 00630 if ((i != best_col && 00631 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00632 (i != best_row 00633 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00634 break; 00635 } 00636 } 00637 /* ... and fraction of total energy test */ 00638 if (i >= 4 && 00639 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy) { 00640 /* Got a hit */ 00641 hit = dtmf_positions[(best_row << 2) + best_col]; 00642 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00643 /* Zero out frame data if this is part DTMF */ 00644 for (i=sample;i<limit;i++) 00645 amp[i] = 0; 00646 *writeback = 1; 00647 } 00648 } 00649 } 00650 00651 /* The logic in the next test is: 00652 For digits we need two successive identical clean detects, with 00653 something different preceeding it. This can work with 00654 back to back differing digits. More importantly, it 00655 can work with nasty phones that give a very wobbly start 00656 to a digit */ 00657 if (hit != s->td.dtmf.current_hit) { 00658 if (hit && s->td.dtmf.lasthit == hit) { 00659 s->td.dtmf.current_hit = hit; 00660 store_digit(s, hit); 00661 } else if (s->td.dtmf.lasthit != s->td.dtmf.current_hit) { 00662 s->td.dtmf.current_hit = 0; 00663 } 00664 } 00665 s->td.dtmf.lasthit = hit; 00666 00667 /* Reinitialise the detector for the next block */ 00668 for (i = 0; i < 4; i++) { 00669 goertzel_reset(&s->td.dtmf.row_out[i]); 00670 goertzel_reset(&s->td.dtmf.col_out[i]); 00671 } 00672 s->td.dtmf.energy = 0.0; 00673 s->td.dtmf.current_sample = 0; 00674 } 00675 return (s->td.dtmf.current_hit); /* return the debounced hit */ 00676 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 310 of file dsp.c.
References cos, s, and SAMPLE_RATE.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().
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] |
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 301 of file dsp.c.
References goertzel_result_t::power, s, and goertzel_result_t::value.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), and mf_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 s.
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(), and s.
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 681 of file dsp.c.
References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, DSP_DIGITMODE_NOQUELCH, goertzel_result(), goertzel_sample(), MF_GSIZE, s, and store_digit().
Referenced by __ast_dsp_digitdetect().
00683 { 00684 float energy[6]; 00685 int best; 00686 int second_best; 00687 float famp; 00688 int i; 00689 int j; 00690 int sample; 00691 int hit; 00692 int limit; 00693 00694 hit = 0; 00695 for (sample = 0; sample < samples; sample = limit) { 00696 /* 80 is optimised to meet the MF specs. */ 00697 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) 00698 limit = sample + (MF_GSIZE - s->td.mf.current_sample); 00699 else 00700 limit = samples; 00701 /* The following unrolled loop takes only 35% (rough estimate) of the 00702 time of a rolled loop on the machine on which it was developed */ 00703 for (j = sample; j < limit; j++) { 00704 famp = amp[j]; 00705 /* With GCC 2.95, the following unrolled code seems to take about 35% 00706 (rough estimate) as long as a neat little 0-3 loop */ 00707 goertzel_sample(s->td.mf.tone_out, amp[j]); 00708 goertzel_sample(s->td.mf.tone_out + 1, amp[j]); 00709 goertzel_sample(s->td.mf.tone_out + 2, amp[j]); 00710 goertzel_sample(s->td.mf.tone_out + 3, amp[j]); 00711 goertzel_sample(s->td.mf.tone_out + 4, amp[j]); 00712 goertzel_sample(s->td.mf.tone_out + 5, amp[j]); 00713 } 00714 s->td.mf.current_sample += (limit - sample); 00715 if (s->td.mf.current_sample < MF_GSIZE) { 00716 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00717 /* If we had a hit last time, go ahead and clear this out since likely it 00718 will be another hit */ 00719 for (i=sample;i<limit;i++) 00720 amp[i] = 0; 00721 *writeback = 1; 00722 } 00723 continue; 00724 } 00725 /* We're at the end of an MF detection block. */ 00726 /* Find the two highest energies. The spec says to look for 00727 two tones and two tones only. Taking this literally -ie 00728 only two tones pass the minimum threshold - doesn't work 00729 well. The sinc function mess, due to rectangular windowing 00730 ensure that! Find the two highest energies and ensure they 00731 are considerably stronger than any of the others. */ 00732 energy[0] = goertzel_result(&s->td.mf.tone_out[0]); 00733 energy[1] = goertzel_result(&s->td.mf.tone_out[1]); 00734 if (energy[0] > energy[1]) { 00735 best = 0; 00736 second_best = 1; 00737 } else { 00738 best = 1; 00739 second_best = 0; 00740 } 00741 /*endif*/ 00742 for (i=2;i<6;i++) { 00743 energy[i] = goertzel_result(&s->td.mf.tone_out[i]); 00744 if (energy[i] >= energy[best]) { 00745 second_best = best; 00746 best = i; 00747 } else if (energy[i] >= energy[second_best]) { 00748 second_best = i; 00749 } 00750 } 00751 /* Basic signal level and twist tests */ 00752 hit = 0; 00753 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00754 && energy[best] < energy[second_best]*BELL_MF_TWIST 00755 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00756 /* Relative peak test */ 00757 hit = -1; 00758 for (i=0;i<6;i++) { 00759 if (i != best && i != second_best) { 00760 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00761 /* The best two are not clearly the best */ 00762 hit = 0; 00763 break; 00764 } 00765 } 00766 } 00767 } 00768 if (hit) { 00769 /* Get the values into ascending order */ 00770 if (second_best < best) { 00771 i = best; 00772 best = second_best; 00773 second_best = i; 00774 } 00775 best = best*5 + second_best - 1; 00776 hit = bell_mf_positions[best]; 00777 /* Look for two successive similar results */ 00778 /* The logic in the next test is: 00779 For KP we need 4 successive identical clean detects, with 00780 two blocks of something different preceeding it. For anything 00781 else we need two successive identical clean detects, with 00782 two blocks of something different preceeding it. */ 00783 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && 00784 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])|| 00785 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] && 00786 hit != s->td.mf.hits[0]))) { 00787 store_digit(s, hit); 00788 } 00789 } 00790 00791 00792 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) { 00793 /* Two successive block without a hit terminate current digit */ 00794 s->td.mf.current_hit = 0; 00795 } 00796 00797 s->td.mf.hits[0] = s->td.mf.hits[1]; 00798 s->td.mf.hits[1] = s->td.mf.hits[2]; 00799 s->td.mf.hits[2] = s->td.mf.hits[3]; 00800 s->td.mf.hits[3] = s->td.mf.hits[4]; 00801 s->td.mf.hits[4] = hit; 00802 /* Reinitialise the detector for the next block */ 00803 for (i = 0; i < 6; i++) 00804 goertzel_reset(&s->td.mf.tone_out[i]); 00805 s->td.mf.current_sample = 0; 00806 } 00807 00808 return (s->td.mf.current_hit); /* return the debounced hit */ 00809 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 856 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00857 { 00858 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00859 /* Make sure absolute levels are high enough */ 00860 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 00861 return 0; 00862 /* Amplify ignored stuff */ 00863 i2 *= TONE_THRESH; 00864 i1 *= TONE_THRESH; 00865 e *= TONE_THRESH; 00866 /* Check first tone */ 00867 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 00868 return 0; 00869 /* And second */ 00870 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 00871 return 0; 00872 /* Guess it's there... */ 00873 return 1; 00874 }
static void store_digit | ( | digit_detect_state_t * | s, | |
char | digit | |||
) | [static] |
Definition at line 549 of file dsp.c.
References ast_log(), LOG_WARNING, MAX_DTMF_DIGITS, and s.
Referenced by __ast_dsp_digitdetect(), dtmf_detect(), and mf_detect().
00550 { 00551 s->detected_digits++; 00552 if (s->current_digits < MAX_DTMF_DIGITS) { 00553 s->digits[s->current_digits++] = digit; 00554 s->digits[s->current_digits] = '\0'; 00555 } else { 00556 ast_log(LOG_WARNING, "Digit lost due to full buffer\n"); 00557 s->lost_digits++; 00558 } 00559 }
static int tone_detect | ( | tone_detect_state_t * | s, | |
int16_t * | amp, | |||
int | samples, | |||
int * | writeback | |||
) | [static] |
Definition at line 458 of file dsp.c.
References goertzel_sample(), and s.
Referenced by __ast_dsp_digitdetect().
00460 { 00461 float tone_energy; 00462 int i; 00463 int hit = 0; 00464 int limit; 00465 int res = 0; 00466 int16_t *ptr; 00467 00468 while (1) { 00469 /* Process in blocks. */ 00470 limit = (samples < s->samples_pending) ? samples : s->samples_pending; 00471 00472 for (i = limit, ptr = amp ; i > 0; i--, ptr++) { 00473 /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */ 00474 s->energy += (int32_t) *ptr * (int32_t) *ptr; 00475 00476 goertzel_sample(&s->tone, *ptr); 00477 } 00478 00479 s->samples_pending -= limit; 00480 00481 if (s->samples_pending) { 00482 /* Finished incomplete (last) block */ 00483 if (s->last_hit && s->squelch) { 00484 /* If we had a hit last time, go ahead and clear this out since likely it 00485 will be another hit */ 00486 memset(amp, 0, sizeof(*amp) * limit); 00487 if (writeback) 00488 *writeback = 1; 00489 } 00490 break; 00491 } 00492 00493 00494 tone_energy = goertzel_result(&s->tone); 00495 00496 /* Scale to make comparable */ 00497 tone_energy *= 2.0; 00498 s->energy *= s->block_size; 00499 00500 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)); 00501 hit = 0; 00502 if (tone_energy > s->energy * s->threshold) { 00503 00504 ast_debug(10, "Hit! count=%d\n", s->hit_count); 00505 hit = 1; 00506 00507 if (s->squelch) { 00508 /* Zero out frame data */ 00509 memset(amp, 0, sizeof(*amp) * limit); 00510 if (writeback) 00511 *writeback = 1; 00512 } 00513 } 00514 00515 if (s->hit_count) 00516 s->hit_count++; 00517 00518 if (hit == s->last_hit) { 00519 if (!hit) { 00520 /* Two successive misses. Tone ended */ 00521 s->hit_count = 0; 00522 } else if (!s->hit_count) { 00523 s->hit_count++; 00524 } 00525 00526 } 00527 00528 if (s->hit_count == s->hits_required) { 00529 ast_debug(1, "%d Hz done detected\n", s->freq); 00530 res = 1; 00531 } 00532 00533 s->last_hit = hit; 00534 00535 /* Reset for the next block */ 00536 goertzel_reset(&s->tone); 00537 00538 /* Advance to the next block */ 00539 s->energy = 0.0; 00540 s->samples_pending = s->block_size; 00541 00542 amp += limit; 00543 samples -= limit; 00544 } 00545 00546 return res; 00547 }
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().