#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
Include dependency graph for dsp.c:
Go to the source code of this file.
Data Structures | |
struct | ast_dsp |
struct | dtmf_detect_state_t |
struct | goertzel_state_t |
struct | mf_detect_state_t |
struct | progalias |
struct | progress |
Defines | |
#define | BELL_MF_RELATIVE_PEAK 12.6 |
#define | BELL_MF_THRESHOLD 1.6e9 |
#define | BELL_MF_TWIST 4.0 |
#define | BUSY_MAX 3100 |
#define | BUSY_MIN 75 |
#define | BUSY_PAT_PERCENT 7 |
#define | BUSY_PERCENT 10 |
#define | BUSY_THRESHOLD 100 |
#define | BUSYDETECT_MARTIN |
#define | COUNT_THRESH 3 |
#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_DETECT |
#define | FAX_THRESHOLD 8.0e7 |
#define | FIX_INF(inf) |
#define | GSAMP_SIZE_CR 188 |
#define | GSAMP_SIZE_NA 183 |
#define | GSAMP_SIZE_UK 160 |
#define | HZ_1400 5 |
#define | HZ_1800 6 |
#define | HZ_350 0 |
#define | HZ_400 0 |
#define | HZ_425 0 |
#define | HZ_440 1 |
#define | HZ_480 2 |
#define | HZ_620 3 |
#define | HZ_950 4 |
#define | MAX_DTMF_DIGITS 128 |
#define | MF_GSIZE 120 |
#define | PROG_MODE_CR 1 |
#define | PROG_MODE_NA 0 |
#define | PROG_MODE_UK 2 |
#define | TONE_MIN_THRESH 1e8 |
#define | TONE_THRESH 10.0 |
#define | UK_HANGUP_THRESH 60 |
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) |
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. | |
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_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. | |
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_mf_detect_init (mf_detect_state_t *s) |
static int | dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect) |
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 (mf_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) |
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 | fax_freq = 1100.0 |
static float | mf_tones [] |
static struct progress | modes [] |
Definition in file dsp.c.
|
|
|
|
|
|
|
Definition at line 110 of file dsp.c. Referenced by ast_dsp_busydetect(). |
|
Definition at line 109 of file dsp.c. Referenced by ast_dsp_busydetect(). |
|
Definition at line 107 of file dsp.c. Referenced by ast_dsp_busydetect(). |
|
Definition at line 106 of file dsp.c. Referenced by ast_dsp_busydetect(). |
|
Definition at line 108 of file dsp.c. Referenced by ast_dsp_busydetect(). |
|
|
|
Definition at line 120 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 104 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 113 of file dsp.c. Referenced by __ast_dsp_silence(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Referenced by ast_dsp_process(). |
|
|
|
|
|
|
|
Definition at line 75 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 76 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 70 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 82 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 79 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 71 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 72 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 73 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 74 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
|
|
Definition at line 670 of file dsp.c. Referenced by mf_detect(). |
|
Definition at line 66 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 65 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 67 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 119 of file dsp.c. Referenced by __ast_dsp_call_progress(), and pair_there(). |
|
Definition at line 118 of file dsp.c. Referenced by __ast_dsp_call_progress(), and pair_there(). |
|
Definition at line 121 of file dsp.c. Referenced by __ast_dsp_call_progress(). |
|
Definition at line 1031 of file dsp.c. References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), COUNT_THRESH, dsp, 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::tcount, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, UK_HANGUP_THRESH, goertzel_state_t::v2, and goertzel_state_t::v3. Referenced by ast_dsp_call_progress(), and ast_dsp_process(). 01032 { 01033 int x; 01034 int y; 01035 int pass; 01036 int newstate = DSP_TONE_STATE_SILENCE; 01037 int res = 0; 01038 int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH; 01039 while(len) { 01040 /* Take the lesser of the number of samples we need and what we have */ 01041 pass = len; 01042 if (pass > dsp->gsamp_size - dsp->gsamps) 01043 pass = dsp->gsamp_size - dsp->gsamps; 01044 for (x=0;x<pass;x++) { 01045 for (y=0;y<dsp->freqcount;y++) 01046 goertzel_sample(&dsp->freqs[y], s[x]); 01047 dsp->genergy += s[x] * s[x]; 01048 } 01049 s += pass; 01050 dsp->gsamps += pass; 01051 len -= pass; 01052 if (dsp->gsamps == dsp->gsamp_size) { 01053 float hz[7]; 01054 for (y=0;y<7;y++) 01055 hz[y] = goertzel_result(&dsp->freqs[y]); 01056 #if 0 01057 printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n"); 01058 printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 01059 hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy); 01060 #endif 01061 switch(dsp->progmode) { 01062 case PROG_MODE_NA: 01063 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01064 newstate = DSP_TONE_STATE_BUSY; 01065 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01066 newstate = DSP_TONE_STATE_RINGING; 01067 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01068 newstate = DSP_TONE_STATE_DIALTONE; 01069 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01070 newstate = DSP_TONE_STATE_SPECIAL1; 01071 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01072 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 01073 newstate = DSP_TONE_STATE_SPECIAL2; 01074 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01075 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 01076 newstate = DSP_TONE_STATE_SPECIAL3; 01077 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01078 newstate = DSP_TONE_STATE_TALKING; 01079 } else 01080 newstate = DSP_TONE_STATE_SILENCE; 01081 break; 01082 case PROG_MODE_CR: 01083 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01084 newstate = DSP_TONE_STATE_RINGING; 01085 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01086 newstate = DSP_TONE_STATE_TALKING; 01087 } else 01088 newstate = DSP_TONE_STATE_SILENCE; 01089 break; 01090 case PROG_MODE_UK: 01091 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 01092 newstate = DSP_TONE_STATE_HUNGUP; 01093 } 01094 break; 01095 default: 01096 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01097 } 01098 if (newstate == dsp->tstate) { 01099 dsp->tcount++; 01100 if (dsp->tcount == thresh) { 01101 if ((dsp->features & DSP_PROGRESS_BUSY) && 01102 dsp->tstate == DSP_TONE_STATE_BUSY) { 01103 res = AST_CONTROL_BUSY; 01104 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01105 } else if ((dsp->features & DSP_PROGRESS_TALK) && 01106 dsp->tstate == DSP_TONE_STATE_TALKING) { 01107 res = AST_CONTROL_ANSWER; 01108 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01109 } else if ((dsp->features & DSP_PROGRESS_RINGING) && 01110 dsp->tstate == DSP_TONE_STATE_RINGING) 01111 res = AST_CONTROL_RINGING; 01112 else if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01113 dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01114 res = AST_CONTROL_CONGESTION; 01115 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01116 } else if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01117 dsp->tstate == DSP_TONE_STATE_HUNGUP) { 01118 res = AST_CONTROL_HANGUP; 01119 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01120 } 01121 } 01122 } else { 01123 #if 0 01124 printf("Newstate: %d\n", newstate); 01125 #endif 01126 dsp->tstate = newstate; 01127 dsp->tcount = 1; 01128 } 01129 01130 /* Reset goertzel */ 01131 for (x=0;x<7;x++) 01132 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01133 dsp->gsamps = 0; 01134 dsp->genergy = 0.0; 01135 } 01136 } 01137 #if 0 01138 if (res) 01139 printf("Returning %d\n", res); 01140 #endif 01141 return res; 01142 }
|
|
Definition at line 956 of file dsp.c. References ast_dsp::digitmode, dsp, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, ast_dsp::dtmf, dtmf_detect(), ast_dsp::features, ast_dsp::mf, mf_detect(), and ast_dsp::td. Referenced by ast_dsp_digitdetect(), and ast_dsp_process(). 00957 { 00958 int res; 00959 00960 if (dsp->digitmode & DSP_DIGITMODE_MF) 00961 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00962 else 00963 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT); 00964 return res; 00965 }
|
|
Definition at line 1157 of file dsp.c. References ast_dsp::busycount, ast_dsp::busymaybe, dsp, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::totalnoise, and ast_dsp::totalsilence. Referenced by ast_dsp_process(), and ast_dsp_silence(). 01158 { 01159 int accum; 01160 int x; 01161 int res = 0; 01162 01163 if (!len) 01164 return 0; 01165 accum = 0; 01166 for (x=0;x<len; x++) 01167 accum += abs(s[x]); 01168 accum /= len; 01169 if (accum < dsp->threshold) { 01170 /* Silent */ 01171 dsp->totalsilence += len/8; 01172 if (dsp->totalnoise) { 01173 /* Move and save history */ 01174 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); 01175 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01176 /* we don't want to check for busydetect that frequently */ 01177 #if 0 01178 dsp->busymaybe = 1; 01179 #endif 01180 } 01181 dsp->totalnoise = 0; 01182 res = 1; 01183 } else { 01184 /* Not silent */ 01185 dsp->totalnoise += len/8; 01186 if (dsp->totalsilence) { 01187 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01188 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01189 /* Move and save history */ 01190 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0])); 01191 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01192 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01193 if (silence1 < silence2) { 01194 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) 01195 dsp->busymaybe = 1; 01196 else 01197 dsp->busymaybe = 0; 01198 } else { 01199 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) 01200 dsp->busymaybe = 1; 01201 else 01202 dsp->busymaybe = 0; 01203 } 01204 } 01205 dsp->totalsilence = 0; 01206 } 01207 if (totalsilence) 01208 *totalsilence = dsp->totalsilence; 01209 return res; 01210 }
|
|
Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.
Definition at line 1213 of file dsp.c. References ast_dsp_busydetect(), ast_log(), BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, BUSY_THRESHOLD, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, dsp, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, and LOG_NOTICE. Referenced by ast_dsp_busydetect(), and ast_dsp_process(). 01214 { 01215 int res = 0, x; 01216 #ifndef BUSYDETECT_TONEONLY 01217 int avgsilence = 0, hitsilence = 0; 01218 #endif 01219 int avgtone = 0, hittone = 0; 01220 if (!dsp->busymaybe) 01221 return res; 01222 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01223 #ifndef BUSYDETECT_TONEONLY 01224 avgsilence += dsp->historicsilence[x]; 01225 #endif 01226 avgtone += dsp->historicnoise[x]; 01227 } 01228 #ifndef BUSYDETECT_TONEONLY 01229 avgsilence /= dsp->busycount; 01230 #endif 01231 avgtone /= dsp->busycount; 01232 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01233 #ifndef BUSYDETECT_TONEONLY 01234 if (avgsilence > dsp->historicsilence[x]) { 01235 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01236 hitsilence++; 01237 } else { 01238 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01239 hitsilence++; 01240 } 01241 #endif 01242 if (avgtone > dsp->historicnoise[x]) { 01243 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01244 hittone++; 01245 } else { 01246 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01247 hittone++; 01248 } 01249 } 01250 #ifndef BUSYDETECT_TONEONLY 01251 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01252 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01253 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01254 #else 01255 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01256 #endif 01257 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01258 #ifdef BUSYDETECT_TONEONLY 01259 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE 01260 #endif 01261 if (avgtone > avgsilence) { 01262 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01263 res = 1; 01264 } else { 01265 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01266 res = 1; 01267 } 01268 #else 01269 res = 1; 01270 #endif 01271 } 01272 /* If we know the expected busy tone length, check we are in the range */ 01273 if (res && (dsp->busy_tonelength > 0)) { 01274 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01275 #if 0 01276 ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n", 01277 avgtone, dsp->busy_tonelength); 01278 #endif 01279 res = 0; 01280 } 01281 } 01282 /* If we know the expected busy tone silent-period length, check we are in the range */ 01283 if (res && (dsp->busy_quietlength > 0)) { 01284 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01285 #if 0 01286 ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n", 01287 avgsilence, dsp->busy_quietlength); 01288 #endif 01289 res = 0; 01290 } 01291 } 01292 #if 1 01293 if (res) 01294 ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01295 #endif 01296 return res; 01297 }
|
|
Scans for progress indication in audio.
Definition at line 1144 of file dsp.c. References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass. 01145 { 01146 if (inf->frametype != AST_FRAME_VOICE) { 01147 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01148 return 0; 01149 } 01150 if (inf->subclass != AST_FORMAT_SLINEAR) { 01151 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01152 return 0; 01153 } 01154 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01155 }
|
|
Return non-zero if DTMF hit was found.
Definition at line 967 of file dsp.c. References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass. 00968 { 00969 short *s; 00970 int len; 00971 int ign=0; 00972 00973 if (inf->frametype != AST_FRAME_VOICE) { 00974 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00975 return 0; 00976 } 00977 if (inf->subclass != AST_FORMAT_SLINEAR) { 00978 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00979 return 0; 00980 } 00981 s = inf->data; 00982 len = inf->datalen / 2; 00983 return __ast_dsp_digitdetect(dsp, s, len, &ign); 00984 }
|
|
Set digit mode.
Definition at line 1684 of file dsp.c. References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_dsp::digitmode, dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td. Referenced by i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption(). 01685 { 01686 int new; 01687 int old; 01688 01689 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01690 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01691 if (old != new) { 01692 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01693 if (new & DSP_DIGITMODE_MF) 01694 ast_mf_detect_init(&dsp->td.mf); 01695 else 01696 ast_dtmf_detect_init(&dsp->td.dtmf); 01697 } 01698 dsp->digitmode = digitmode; 01699 return 0; 01700 }
|
|
Reset DTMF detector.
Definition at line 1622 of file dsp.c. References mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, ast_dsp::digitmode, mf_detect_state_t::digits, dsp, DSP_DIGITMODE_MF, goertzel_reset(), mf_detect_state_t::hits, ast_dsp::mf, mf_detect_state_t::mhit, ast_dsp::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out. Referenced by ss_thread(). 01623 { 01624 int i; 01625 01626 dsp->thinkdigit = 0; 01627 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01628 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01629 dsp->td.mf.current_digits = 0; 01630 /* Reinitialise the detector for the next block */ 01631 for (i = 0; i < 6; i++) { 01632 goertzel_reset(&dsp->td.mf.tone_out[i]); 01633 #ifdef OLD_DSP_ROUTINES 01634 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01635 #endif 01636 } 01637 #ifdef OLD_DSP_ROUTINES 01638 dsp->td.mf.energy = 0.0; 01639 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01640 #else 01641 dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0; 01642 #endif 01643 dsp->td.mf.current_sample = 0; 01644 } else { 01645 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01646 dsp->td.dtmf.current_digits = 0; 01647 /* Reinitialise the detector for the next block */ 01648 for (i = 0; i < 4; i++) { 01649 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01650 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01651 #ifdef OLD_DSP_ROUTINES 01652 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01653 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01654 #endif 01655 } 01656 #ifdef FAX_DETECT 01657 goertzel_reset (&dsp->td.dtmf.fax_tone); 01658 #endif 01659 #ifdef OLD_DSP_ROUTINES 01660 #ifdef FAX_DETECT 01661 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01662 #endif 01663 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01664 #else 01665 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0; 01666 #endif 01667 dsp->td.dtmf.energy = 0.0; 01668 dsp->td.dtmf.current_sample = 0; 01669 } 01670 }
|
|
Definition at line 1596 of file dsp.c. Referenced by __oh323_destroy(), ast_app_getvoice(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), handle_recordfile(), i4l_hangup(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), vpb_hangup(), and zt_hangup().
|
|
Get tcount (Threshold counter).
Definition at line 1721 of file dsp.c. References dsp, and ast_dsp::tcount.
|
|
Get tstate (Tone State).
Definition at line 1716 of file dsp.c. References dsp, and ast_dsp::tstate.
|
|
Get pending DTMF/MF digits.
Definition at line 1006 of file dsp.c. References mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, dsp, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td. 01007 { 01008 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01009 if (max > dsp->td.mf.current_digits) 01010 max = dsp->td.mf.current_digits; 01011 if (max > 0) { 01012 memcpy(buf, dsp->td.mf.digits, max); 01013 memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 01014 dsp->td.mf.current_digits -= max; 01015 } 01016 buf[max] = '\0'; 01017 return max; 01018 } else { 01019 if (max > dsp->td.dtmf.current_digits) 01020 max = dsp->td.dtmf.current_digits; 01021 if (max > 0) { 01022 memcpy (buf, dsp->td.dtmf.digits, max); 01023 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01024 dsp->td.dtmf.current_digits -= max; 01025 } 01026 buf[max] = '\0'; 01027 return max; 01028 } 01029 }
|
|
Definition at line 1573 of file dsp.c. References ast_dsp_prog_reset(), ast_dtmf_detect_init(), DEFAULT_THRESHOLD, dsp, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and malloc. Referenced by __oh323_new(), ast_app_getvoice(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), record_exec(), sip_dtmfmode(), sip_new(), and zt_new(). 01574 { 01575 struct ast_dsp *dsp; 01576 01577 dsp = malloc(sizeof(struct ast_dsp)); 01578 if (dsp) { 01579 memset(dsp, 0, sizeof(struct ast_dsp)); 01580 dsp->threshold = DEFAULT_THRESHOLD; 01581 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01582 dsp->busycount = DSP_HISTORY; 01583 /* Initialize DTMF detector */ 01584 ast_dtmf_detect_init(&dsp->td.dtmf); 01585 /* Initialize initial DSP progress detect parameters */ 01586 ast_dsp_prog_reset(dsp); 01587 } 01588 return dsp; 01589 }
|
|
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 1363 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_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, dsp, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, ast_channel::name, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit. Referenced by do_chanreads(), mgcp_rtp_read(), misdn_tx2ast_frm(), oh323_rtp_read(), sip_rtp_read(), and zt_read(). 01364 { 01365 int silence; 01366 int res; 01367 int digit; 01368 int x; 01369 short *shortdata; 01370 unsigned char *odata; 01371 int len; 01372 int writeback = 0; 01373 01374 #define FIX_INF(inf) do { \ 01375 if (writeback) { \ 01376 switch(inf->subclass) { \ 01377 case AST_FORMAT_SLINEAR: \ 01378 break; \ 01379 case AST_FORMAT_ULAW: \ 01380 for (x=0;x<len;x++) \ 01381 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01382 break; \ 01383 case AST_FORMAT_ALAW: \ 01384 for (x=0;x<len;x++) \ 01385 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01386 break; \ 01387 } \ 01388 } \ 01389 } while(0) 01390 01391 if (!af) 01392 return NULL; 01393 if (af->frametype != AST_FRAME_VOICE) 01394 return af; 01395 odata = af->data; 01396 len = af->datalen; 01397 /* Make sure we have short data */ 01398 switch(af->subclass) { 01399 case AST_FORMAT_SLINEAR: 01400 shortdata = af->data; 01401 len = af->datalen / 2; 01402 break; 01403 case AST_FORMAT_ULAW: 01404 shortdata = alloca(af->datalen * 2); 01405 if (!shortdata) { 01406 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01407 return af; 01408 } 01409 for (x=0;x<len;x++) 01410 shortdata[x] = AST_MULAW(odata[x]); 01411 break; 01412 case AST_FORMAT_ALAW: 01413 shortdata = alloca(af->datalen * 2); 01414 if (!shortdata) { 01415 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01416 return af; 01417 } 01418 for (x=0;x<len;x++) 01419 shortdata[x] = AST_ALAW(odata[x]); 01420 break; 01421 default: 01422 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01423 return af; 01424 } 01425 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01426 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01427 memset(&dsp->f, 0, sizeof(dsp->f)); 01428 dsp->f.frametype = AST_FRAME_NULL; 01429 return &dsp->f; 01430 } 01431 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01432 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01433 memset(&dsp->f, 0, sizeof(dsp->f)); 01434 dsp->f.frametype = AST_FRAME_CONTROL; 01435 dsp->f.subclass = AST_CONTROL_BUSY; 01436 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01437 return &dsp->f; 01438 } 01439 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01440 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01441 #if 0 01442 if (digit) 01443 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01444 #endif 01445 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01446 if (!dsp->thinkdigit) { 01447 if (digit) { 01448 /* Looks like we might have something. 01449 * Request a conference mute for the moment */ 01450 memset(&dsp->f, 0, sizeof(dsp->f)); 01451 dsp->f.frametype = AST_FRAME_DTMF; 01452 dsp->f.subclass = 'm'; 01453 dsp->thinkdigit = 'x'; 01454 FIX_INF(af); 01455 if (chan) 01456 ast_queue_frame(chan, af); 01457 ast_frfree(af); 01458 return &dsp->f; 01459 } 01460 } else { 01461 if (digit) { 01462 /* Thought we saw one last time. Pretty sure we really have now */ 01463 if (dsp->thinkdigit) { 01464 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01465 /* If we found a digit, and we're changing digits, go 01466 ahead and send this one, but DON'T stop confmute because 01467 we're detecting something else, too... */ 01468 memset(&dsp->f, 0, sizeof(dsp->f)); 01469 dsp->f.frametype = AST_FRAME_DTMF; 01470 dsp->f.subclass = dsp->thinkdigit; 01471 FIX_INF(af); 01472 if (chan) 01473 ast_queue_frame(chan, af); 01474 ast_frfree(af); 01475 } 01476 dsp->thinkdigit = digit; 01477 return &dsp->f; 01478 } 01479 dsp->thinkdigit = digit; 01480 } else { 01481 if (dsp->thinkdigit) { 01482 memset(&dsp->f, 0, sizeof(dsp->f)); 01483 if (dsp->thinkdigit != 'x') { 01484 /* If we found a digit, send it now */ 01485 dsp->f.frametype = AST_FRAME_DTMF; 01486 dsp->f.subclass = dsp->thinkdigit; 01487 dsp->thinkdigit = 0; 01488 } else { 01489 dsp->f.frametype = AST_FRAME_DTMF; 01490 dsp->f.subclass = 'u'; 01491 dsp->thinkdigit = 0; 01492 } 01493 FIX_INF(af); 01494 if (chan) 01495 ast_queue_frame(chan, af); 01496 ast_frfree(af); 01497 return &dsp->f; 01498 } 01499 } 01500 } 01501 } else if (!digit) { 01502 /* Only check when there is *not* a hit... */ 01503 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01504 if (dsp->td.mf.current_digits) { 01505 memset(&dsp->f, 0, sizeof(dsp->f)); 01506 dsp->f.frametype = AST_FRAME_DTMF; 01507 dsp->f.subclass = dsp->td.mf.digits[0]; 01508 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01509 dsp->td.mf.current_digits--; 01510 FIX_INF(af); 01511 if (chan) 01512 ast_queue_frame(chan, af); 01513 ast_frfree(af); 01514 return &dsp->f; 01515 } 01516 } else { 01517 if (dsp->td.dtmf.current_digits) { 01518 memset(&dsp->f, 0, sizeof(dsp->f)); 01519 dsp->f.frametype = AST_FRAME_DTMF; 01520 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01521 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01522 dsp->td.dtmf.current_digits--; 01523 FIX_INF(af); 01524 if (chan) 01525 ast_queue_frame(chan, af); 01526 ast_frfree(af); 01527 return &dsp->f; 01528 } 01529 } 01530 } 01531 } 01532 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01533 res = __ast_dsp_call_progress(dsp, shortdata, len); 01534 if (res) { 01535 switch(res) { 01536 case AST_CONTROL_ANSWER: 01537 case AST_CONTROL_BUSY: 01538 case AST_CONTROL_RINGING: 01539 case AST_CONTROL_CONGESTION: 01540 case AST_CONTROL_HANGUP: 01541 memset(&dsp->f, 0, sizeof(dsp->f)); 01542 dsp->f.frametype = AST_FRAME_CONTROL; 01543 dsp->f.subclass = res; 01544 dsp->f.src = "dsp_progress"; 01545 if (chan) 01546 ast_queue_frame(chan, &dsp->f); 01547 break; 01548 default: 01549 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01550 } 01551 } 01552 } 01553 FIX_INF(af); 01554 return af; 01555 }
|
|
Definition at line 1557 of file dsp.c. References dsp, ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, and progress::size. Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone(). 01558 { 01559 int max = 0; 01560 int x; 01561 01562 dsp->gsamp_size = modes[dsp->progmode].size; 01563 dsp->gsamps = 0; 01564 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { 01565 if (modes[dsp->progmode].freqs[x]) { 01566 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01567 max = x + 1; 01568 } 01569 } 01570 dsp->freqcount = max; 01571 }
|
|
Reset total silence count.
Definition at line 1672 of file dsp.c. References dsp, ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3. 01673 { 01674 int x; 01675 01676 dsp->totalsilence = 0; 01677 dsp->gsamps = 0; 01678 for (x=0;x<4;x++) 01679 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01680 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01681 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01682 }
|
|
Set number of required cadences for busy.
Definition at line 1606 of file dsp.c. References ast_dsp::busycount, dsp, and DSP_HISTORY. Referenced by zt_new(). 01607 { 01608 if (cadences < 4) 01609 cadences = 4; 01610 if (cadences > DSP_HISTORY) 01611 cadences = DSP_HISTORY; 01612 dsp->busycount = cadences; 01613 }
|
|
Set expected lengths of the busy tone.
Definition at line 1615 of file dsp.c. References ast_log(), ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, dsp, and LOG_DEBUG. Referenced by zt_new(). 01616 { 01617 dsp->busy_tonelength = tonelength; 01618 dsp->busy_quietlength = quietlength; 01619 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01620 }
|
|
Set zone for doing progress detection.
Definition at line 1702 of file dsp.c. References aliases, ast_dsp_prog_reset(), dsp, name, and ast_dsp::progmode. Referenced by zt_new(). 01703 { 01704 int x; 01705 01706 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) { 01707 if (!strcasecmp(aliases[x].name, zone)) { 01708 dsp->progmode = aliases[x].mode; 01709 ast_dsp_prog_reset(dsp); 01710 return 0; 01711 } 01712 } 01713 return -1; 01714 }
|
|
Select feature set.
Definition at line 1591 of file dsp.c. References dsp, and ast_dsp::features. Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_dtmfmode(), sip_new(), and zt_new().
|
|
Set threshold value for silence.
Definition at line 1601 of file dsp.c. References dsp, and ast_dsp::threshold. Referenced by do_waiting(), handle_recordfile(), and record_exec().
|
|
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1345 of file dsp.c. References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass. Referenced by background_detect_exec(), handle_recordfile(), and record_exec(). 01346 { 01347 short *s; 01348 int len; 01349 01350 if (f->frametype != AST_FRAME_VOICE) { 01351 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01352 return 0; 01353 } 01354 if (f->subclass != AST_FORMAT_SLINEAR) { 01355 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01356 return 0; 01357 } 01358 s = f->data; 01359 len = f->datalen/2; 01360 return __ast_dsp_silence(dsp, s, len, totalsilence); 01361 }
|
|
Definition at line 338 of file dsp.c. References goertzel_init(), and s. Referenced by ast_dsp_digitmode(), and ast_dsp_new(). 00339 { 00340 int i; 00341 00342 #ifdef OLD_DSP_ROUTINES 00343 s->hit1 = 00344 s->mhit = 00345 s->hit3 = 00346 s->hit4 = 00347 s->hit2 = 0; 00348 #else 00349 s->hits[0] = s->hits[1] = s->hits[2] = 0; 00350 #endif 00351 for (i = 0; i < 4; i++) { 00352 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00353 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00354 #ifdef OLD_DSP_ROUTINES 00355 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102); 00356 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102); 00357 #endif 00358 s->energy = 0.0; 00359 } 00360 #ifdef FAX_DETECT 00361 /* Same for the fax dector */ 00362 goertzel_init (&s->fax_tone, fax_freq, 102); 00363 00364 #ifdef OLD_DSP_ROUTINES 00365 /* Same for the fax dector 2nd harmonic */ 00366 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102); 00367 #endif 00368 #endif /* FAX_DETECT */ 00369 s->current_sample = 0; 00370 s->detected_digits = 0; 00371 s->current_digits = 0; 00372 memset(&s->digits, 0, sizeof(s->digits)); 00373 s->lost_digits = 0; 00374 s->digits[0] = '\0'; 00375 }
|
|
Definition at line 377 of file dsp.c. References goertzel_init(), mf_tones, and s. Referenced by ast_dsp_digitmode(). 00378 { 00379 int i; 00380 #ifdef OLD_DSP_ROUTINES 00381 s->hit1 = 00382 s->hit2 = 0; 00383 #else 00384 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00385 #endif 00386 for (i = 0; i < 6; i++) { 00387 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00388 #ifdef OLD_DSP_ROUTINES 00389 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160); 00390 s->energy = 0.0; 00391 #endif 00392 } 00393 s->current_digits = 0; 00394 memset(&s->digits, 0, sizeof(s->digits)); 00395 s->current_sample = 0; 00396 s->detected_digits = 0; 00397 s->lost_digits = 0; 00398 s->digits[0] = '\0'; 00399 s->mhit = 0; 00400 }
|
|
Definition at line 402 of file dsp.c. Referenced by __ast_dsp_digitdetect(). 00404 { 00405 float row_energy[4]; 00406 float col_energy[4]; 00407 #ifdef FAX_DETECT 00408 float fax_energy; 00409 #ifdef OLD_DSP_ROUTINES 00410 float fax_energy_2nd; 00411 #endif 00412 #endif /* FAX_DETECT */ 00413 float famp; 00414 float v1; 00415 int i; 00416 int j; 00417 int sample; 00418 int best_row; 00419 int best_col; 00420 int hit; 00421 int limit; 00422 00423 hit = 0; 00424 for (sample = 0; sample < samples; sample = limit) { 00425 /* 102 is optimised to meet the DTMF specs. */ 00426 if ((samples - sample) >= (102 - s->current_sample)) 00427 limit = sample + (102 - s->current_sample); 00428 else 00429 limit = samples; 00430 #if defined(USE_3DNOW) 00431 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00432 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00433 #ifdef OLD_DSP_ROUTINES 00434 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00435 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00436 #endif 00437 /* XXX Need to fax detect for 3dnow too XXX */ 00438 #warning "Fax Support Broken" 00439 #else 00440 /* The following unrolled loop takes only 35% (rough estimate) of the 00441 time of a rolled loop on the machine on which it was developed */ 00442 for (j=sample;j<limit;j++) { 00443 famp = amp[j]; 00444 s->energy += famp*famp; 00445 /* With GCC 2.95, the following unrolled code seems to take about 35% 00446 (rough estimate) as long as a neat little 0-3 loop */ 00447 v1 = s->row_out[0].v2; 00448 s->row_out[0].v2 = s->row_out[0].v3; 00449 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; 00450 v1 = s->col_out[0].v2; 00451 s->col_out[0].v2 = s->col_out[0].v3; 00452 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; 00453 v1 = s->row_out[1].v2; 00454 s->row_out[1].v2 = s->row_out[1].v3; 00455 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; 00456 v1 = s->col_out[1].v2; 00457 s->col_out[1].v2 = s->col_out[1].v3; 00458 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; 00459 v1 = s->row_out[2].v2; 00460 s->row_out[2].v2 = s->row_out[2].v3; 00461 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; 00462 v1 = s->col_out[2].v2; 00463 s->col_out[2].v2 = s->col_out[2].v3; 00464 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; 00465 v1 = s->row_out[3].v2; 00466 s->row_out[3].v2 = s->row_out[3].v3; 00467 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; 00468 v1 = s->col_out[3].v2; 00469 s->col_out[3].v2 = s->col_out[3].v3; 00470 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; 00471 #ifdef FAX_DETECT 00472 /* Update fax tone */ 00473 v1 = s->fax_tone.v2; 00474 s->fax_tone.v2 = s->fax_tone.v3; 00475 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; 00476 #endif /* FAX_DETECT */ 00477 #ifdef OLD_DSP_ROUTINES 00478 v1 = s->col_out2nd[0].v2; 00479 s->col_out2nd[0].v2 = s->col_out2nd[0].v3; 00480 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; 00481 v1 = s->row_out2nd[0].v2; 00482 s->row_out2nd[0].v2 = s->row_out2nd[0].v3; 00483 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; 00484 v1 = s->col_out2nd[1].v2; 00485 s->col_out2nd[1].v2 = s->col_out2nd[1].v3; 00486 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; 00487 v1 = s->row_out2nd[1].v2; 00488 s->row_out2nd[1].v2 = s->row_out2nd[1].v3; 00489 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; 00490 v1 = s->col_out2nd[2].v2; 00491 s->col_out2nd[2].v2 = s->col_out2nd[2].v3; 00492 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; 00493 v1 = s->row_out2nd[2].v2; 00494 s->row_out2nd[2].v2 = s->row_out2nd[2].v3; 00495 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; 00496 v1 = s->col_out2nd[3].v2; 00497 s->col_out2nd[3].v2 = s->col_out2nd[3].v3; 00498 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; 00499 v1 = s->row_out2nd[3].v2; 00500 s->row_out2nd[3].v2 = s->row_out2nd[3].v3; 00501 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; 00502 #ifdef FAX_DETECT 00503 /* Update fax tone */ 00504 v1 = s->fax_tone.v2; 00505 s->fax_tone2nd.v2 = s->fax_tone2nd.v3; 00506 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; 00507 #endif /* FAX_DETECT */ 00508 #endif 00509 } 00510 #endif 00511 s->current_sample += (limit - sample); 00512 if (s->current_sample < 102) { 00513 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00514 /* If we had a hit last time, go ahead and clear this out since likely it 00515 will be another hit */ 00516 for (i=sample;i<limit;i++) 00517 amp[i] = 0; 00518 *writeback = 1; 00519 } 00520 continue; 00521 } 00522 #ifdef FAX_DETECT 00523 /* Detect the fax energy, too */ 00524 fax_energy = goertzel_result(&s->fax_tone); 00525 #endif 00526 /* We are at the end of a DTMF detection block */ 00527 /* Find the peak row and the peak column */ 00528 row_energy[0] = goertzel_result (&s->row_out[0]); 00529 col_energy[0] = goertzel_result (&s->col_out[0]); 00530 00531 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00532 row_energy[i] = goertzel_result (&s->row_out[i]); 00533 if (row_energy[i] > row_energy[best_row]) 00534 best_row = i; 00535 col_energy[i] = goertzel_result (&s->col_out[i]); 00536 if (col_energy[i] > col_energy[best_col]) 00537 best_col = i; 00538 } 00539 hit = 0; 00540 /* Basic signal level test and the twist test */ 00541 if (row_energy[best_row] >= DTMF_THRESHOLD && 00542 col_energy[best_col] >= DTMF_THRESHOLD && 00543 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00544 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00545 /* Relative peak test */ 00546 for (i = 0; i < 4; i++) { 00547 if ((i != best_col && 00548 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00549 (i != best_row 00550 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00551 break; 00552 } 00553 } 00554 #ifdef OLD_DSP_ROUTINES 00555 /* ... and second harmonic test */ 00556 if (i >= 4 && 00557 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy && 00558 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] 00559 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { 00560 #else 00561 /* ... and fraction of total energy test */ 00562 if (i >= 4 && 00563 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) { 00564 #endif 00565 /* Got a hit */ 00566 hit = dtmf_positions[(best_row << 2) + best_col]; 00567 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00568 /* Zero out frame data if this is part DTMF */ 00569 for (i=sample;i<limit;i++) 00570 amp[i] = 0; 00571 *writeback = 1; 00572 } 00573 /* Look for two successive similar results */ 00574 /* The logic in the next test is: 00575 We need two successive identical clean detects, with 00576 something different preceeding it. This can work with 00577 back to back differing digits. More importantly, it 00578 can work with nasty phones that give a very wobbly start 00579 to a digit */ 00580 #ifdef OLD_DSP_ROUTINES 00581 if (hit == s->hit3 && s->hit3 != s->hit2) { 00582 s->mhit = hit; 00583 s->digit_hits[(best_row << 2) + best_col]++; 00584 s->detected_digits++; 00585 if (s->current_digits < MAX_DTMF_DIGITS) { 00586 s->digits[s->current_digits++] = hit; 00587 s->digits[s->current_digits] = '\0'; 00588 } else { 00589 s->lost_digits++; 00590 } 00591 } 00592 #else 00593 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0]) { 00594 s->mhit = hit; 00595 s->digit_hits[(best_row << 2) + best_col]++; 00596 s->detected_digits++; 00597 if (s->current_digits < MAX_DTMF_DIGITS) { 00598 s->digits[s->current_digits++] = hit; 00599 s->digits[s->current_digits] = '\0'; 00600 } else { 00601 s->lost_digits++; 00602 } 00603 } 00604 #endif 00605 } 00606 } 00607 #ifdef FAX_DETECT 00608 if (!hit && (fax_energy >= FAX_THRESHOLD) && 00609 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) && 00610 (faxdetect)) { 00611 #if 0 00612 printf("Fax energy/Second Harmonic: %f\n", fax_energy); 00613 #endif 00614 /* XXX Probably need better checking than just this the energy XXX */ 00615 hit = 'f'; 00616 s->fax_hits++; 00617 } else { 00618 if (s->fax_hits > 5) { 00619 hit = 'f'; 00620 s->mhit = 'f'; 00621 s->detected_digits++; 00622 if (s->current_digits < MAX_DTMF_DIGITS) { 00623 s->digits[s->current_digits++] = hit; 00624 s->digits[s->current_digits] = '\0'; 00625 } else { 00626 s->lost_digits++; 00627 } 00628 } 00629 s->fax_hits = 0; 00630 } 00631 #endif /* FAX_DETECT */ 00632 #ifdef OLD_DSP_ROUTINES 00633 s->hit1 = s->hit2; 00634 s->hit2 = s->hit3; 00635 s->hit3 = hit; 00636 #else 00637 s->hits[0] = s->hits[1]; 00638 s->hits[1] = s->hits[2]; 00639 s->hits[2] = hit; 00640 #endif 00641 /* Reinitialise the detector for the next block */ 00642 for (i = 0; i < 4; i++) { 00643 goertzel_reset(&s->row_out[i]); 00644 goertzel_reset(&s->col_out[i]); 00645 #ifdef OLD_DSP_ROUTINES 00646 goertzel_reset(&s->row_out2nd[i]); 00647 goertzel_reset(&s->col_out2nd[i]); 00648 #endif 00649 } 00650 #ifdef FAX_DETECT 00651 goertzel_reset (&s->fax_tone); 00652 #ifdef OLD_DSP_ROUTINES 00653 goertzel_reset (&s->fax_tone2nd); 00654 #endif 00655 #endif 00656 s->energy = 0.0; 00657 s->current_sample = 0; 00658 } 00659 if ((!s->mhit) || (s->mhit != hit)) { 00660 s->mhit = 0; 00661 return(0); 00662 } 00663 return (hit); 00664 }
|
|
Definition at line 296 of file dsp.c. References s. Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), and ast_mf_detect_init(). 00297 { 00298 s->v2 = s->v3 = 0.0; 00299 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0)); 00300 #ifndef OLD_DSP_ROUTINES 00301 s->samples = samples; 00302 #endif 00303 }
|
|
Definition at line 305 of file dsp.c. References s. Referenced by ast_dsp_digitreset().
|
|
Definition at line 291 of file dsp.c. References s. Referenced by __ast_dsp_call_progress().
|
|
Definition at line 272 of file dsp.c. References s. Referenced by __ast_dsp_call_progress(), and goertzel_update(). 00273 { 00274 float v1; 00275 float fsamp = sample; 00276 00277 v1 = s->v2; 00278 s->v2 = s->v3; 00279 s->v3 = s->fac * s->v2 - v1 + fsamp; 00280 }
|
|
Definition at line 282 of file dsp.c. References goertzel_sample(), and s. 00283 { 00284 int i; 00285 00286 for (i=0;i<count;i++) 00287 goertzel_sample(s, samps[i]); 00288 }
|
|
Definition at line 673 of file dsp.c. References MF_GSIZE, s, and warning(). Referenced by __ast_dsp_digitdetect(). 00675 { 00676 #ifdef OLD_DSP_ROUTINES 00677 float tone_energy[6]; 00678 int best1; 00679 int best2; 00680 float max; 00681 int sofarsogood; 00682 #else 00683 float energy[6]; 00684 int best; 00685 int second_best; 00686 #endif 00687 float famp; 00688 float v1; 00689 int i; 00690 int j; 00691 int sample; 00692 int hit; 00693 int limit; 00694 00695 hit = 0; 00696 for (sample = 0; sample < samples; sample = limit) { 00697 /* 80 is optimised to meet the MF specs. */ 00698 if ((samples - sample) >= (MF_GSIZE - s->current_sample)) 00699 limit = sample + (MF_GSIZE - s->current_sample); 00700 else 00701 limit = samples; 00702 #if defined(USE_3DNOW) 00703 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00704 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00705 #ifdef OLD_DSP_ROUTINES 00706 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00707 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00708 #endif 00709 /* XXX Need to fax detect for 3dnow too XXX */ 00710 #warning "Fax Support Broken" 00711 #else 00712 /* The following unrolled loop takes only 35% (rough estimate) of the 00713 time of a rolled loop on the machine on which it was developed */ 00714 for (j = sample; j < limit; j++) { 00715 famp = amp[j]; 00716 #ifdef OLD_DSP_ROUTINES 00717 s->energy += famp*famp; 00718 #endif 00719 /* With GCC 2.95, the following unrolled code seems to take about 35% 00720 (rough estimate) as long as a neat little 0-3 loop */ 00721 v1 = s->tone_out[0].v2; 00722 s->tone_out[0].v2 = s->tone_out[0].v3; 00723 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp; 00724 v1 = s->tone_out[1].v2; 00725 s->tone_out[1].v2 = s->tone_out[1].v3; 00726 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp; 00727 v1 = s->tone_out[2].v2; 00728 s->tone_out[2].v2 = s->tone_out[2].v3; 00729 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp; 00730 v1 = s->tone_out[3].v2; 00731 s->tone_out[3].v2 = s->tone_out[3].v3; 00732 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp; 00733 v1 = s->tone_out[4].v2; 00734 s->tone_out[4].v2 = s->tone_out[4].v3; 00735 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp; 00736 v1 = s->tone_out[5].v2; 00737 s->tone_out[5].v2 = s->tone_out[5].v3; 00738 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp; 00739 #ifdef OLD_DSP_ROUTINES 00740 v1 = s->tone_out2nd[0].v2; 00741 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3; 00742 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp; 00743 v1 = s->tone_out2nd[1].v2; 00744 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3; 00745 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp; 00746 v1 = s->tone_out2nd[2].v2; 00747 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3; 00748 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp; 00749 v1 = s->tone_out2nd[3].v2; 00750 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3; 00751 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp; 00752 v1 = s->tone_out2nd[4].v2; 00753 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3; 00754 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp; 00755 v1 = s->tone_out2nd[3].v2; 00756 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3; 00757 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp; 00758 #endif 00759 } 00760 #endif 00761 s->current_sample += (limit - sample); 00762 if (s->current_sample < MF_GSIZE) { 00763 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00764 /* If we had a hit last time, go ahead and clear this out since likely it 00765 will be another hit */ 00766 for (i=sample;i<limit;i++) 00767 amp[i] = 0; 00768 *writeback = 1; 00769 } 00770 continue; 00771 } 00772 #ifdef OLD_DSP_ROUTINES 00773 /* We're at the end of an MF detection block. Go ahead and calculate 00774 all the energies. */ 00775 for (i=0;i<6;i++) { 00776 tone_energy[i] = goertzel_result(&s->tone_out[i]); 00777 } 00778 /* Find highest */ 00779 best1 = 0; 00780 max = tone_energy[0]; 00781 for (i=1;i<6;i++) { 00782 if (tone_energy[i] > max) { 00783 max = tone_energy[i]; 00784 best1 = i; 00785 } 00786 } 00787 00788 /* Find 2nd highest */ 00789 if (best1) { 00790 max = tone_energy[0]; 00791 best2 = 0; 00792 } else { 00793 max = tone_energy[1]; 00794 best2 = 1; 00795 } 00796 00797 for (i=0;i<6;i++) { 00798 if (i == best1) continue; 00799 if (tone_energy[i] > max) { 00800 max = tone_energy[i]; 00801 best2 = i; 00802 } 00803 } 00804 hit = 0; 00805 if (best1 != best2) 00806 sofarsogood=1; 00807 else 00808 sofarsogood=0; 00809 /* Check for relative energies */ 00810 for (i=0;i<6;i++) { 00811 if (i == best1) 00812 continue; 00813 if (i == best2) 00814 continue; 00815 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) { 00816 sofarsogood = 0; 00817 break; 00818 } 00819 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) { 00820 sofarsogood = 0; 00821 break; 00822 } 00823 } 00824 00825 if (sofarsogood) { 00826 /* Check for 2nd harmonic */ 00827 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 00828 sofarsogood = 0; 00829 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2]) 00830 sofarsogood = 0; 00831 } 00832 if (sofarsogood) { 00833 hit = mf_hit[best1][best2]; 00834 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00835 /* Zero out frame data if this is part DTMF */ 00836 for (i=sample;i<limit;i++) 00837 amp[i] = 0; 00838 *writeback = 1; 00839 } 00840 /* Look for two consecutive clean hits */ 00841 if ((hit == s->hit3) && (s->hit3 != s->hit2)) { 00842 s->mhit = hit; 00843 s->detected_digits++; 00844 if (s->current_digits < MAX_DTMF_DIGITS - 2) { 00845 s->digits[s->current_digits++] = hit; 00846 s->digits[s->current_digits] = '\0'; 00847 } else { 00848 s->lost_digits++; 00849 } 00850 } 00851 } 00852 00853 s->hit1 = s->hit2; 00854 s->hit2 = s->hit3; 00855 s->hit3 = hit; 00856 /* Reinitialise the detector for the next block */ 00857 for (i = 0; i < 6; i++) { 00858 goertzel_reset(&s->tone_out[i]); 00859 goertzel_reset(&s->tone_out2nd[i]); 00860 } 00861 s->energy = 0.0; 00862 s->current_sample = 0; 00863 } 00864 #else 00865 /* We're at the end of an MF detection block. */ 00866 /* Find the two highest energies. The spec says to look for 00867 two tones and two tones only. Taking this literally -ie 00868 only two tones pass the minimum threshold - doesn't work 00869 well. The sinc function mess, due to rectangular windowing 00870 ensure that! Find the two highest energies and ensure they 00871 are considerably stronger than any of the others. */ 00872 energy[0] = goertzel_result(&s->tone_out[0]); 00873 energy[1] = goertzel_result(&s->tone_out[1]); 00874 if (energy[0] > energy[1]) { 00875 best = 0; 00876 second_best = 1; 00877 } else { 00878 best = 1; 00879 second_best = 0; 00880 } 00881 /*endif*/ 00882 for (i=2;i<6;i++) { 00883 energy[i] = goertzel_result(&s->tone_out[i]); 00884 if (energy[i] >= energy[best]) { 00885 second_best = best; 00886 best = i; 00887 } else if (energy[i] >= energy[second_best]) { 00888 second_best = i; 00889 } 00890 } 00891 /* Basic signal level and twist tests */ 00892 hit = 0; 00893 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00894 && energy[best] < energy[second_best]*BELL_MF_TWIST 00895 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00896 /* Relative peak test */ 00897 hit = -1; 00898 for (i=0;i<6;i++) { 00899 if (i != best && i != second_best) { 00900 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00901 /* The best two are not clearly the best */ 00902 hit = 0; 00903 break; 00904 } 00905 } 00906 } 00907 } 00908 if (hit) { 00909 /* Get the values into ascending order */ 00910 if (second_best < best) { 00911 i = best; 00912 best = second_best; 00913 second_best = i; 00914 } 00915 best = best*5 + second_best - 1; 00916 hit = bell_mf_positions[best]; 00917 /* Look for two successive similar results */ 00918 /* The logic in the next test is: 00919 For KP we need 4 successive identical clean detects, with 00920 two blocks of something different preceeding it. For anything 00921 else we need two successive identical clean detects, with 00922 two blocks of something different preceeding it. */ 00923 if (hit == s->hits[4] && hit == s->hits[3] && 00924 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])|| 00925 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 00926 hit != s->hits[0]))) { 00927 s->detected_digits++; 00928 if (s->current_digits < MAX_DTMF_DIGITS) { 00929 s->digits[s->current_digits++] = hit; 00930 s->digits[s->current_digits] = '\0'; 00931 } else { 00932 s->lost_digits++; 00933 } 00934 } 00935 } else { 00936 hit = 0; 00937 } 00938 s->hits[0] = s->hits[1]; 00939 s->hits[1] = s->hits[2]; 00940 s->hits[2] = s->hits[3]; 00941 s->hits[3] = s->hits[4]; 00942 s->hits[4] = hit; 00943 /* Reinitialise the detector for the next block */ 00944 for (i = 0; i < 6; i++) 00945 goertzel_reset(&s->tone_out[i]); 00946 s->current_sample = 0; 00947 } 00948 #endif 00949 if ((!s->mhit) || (s->mhit != hit)) { 00950 s->mhit = 0; 00951 return(0); 00952 } 00953 return (hit); 00954 }
|
|
Definition at line 986 of file dsp.c. References TONE_MIN_THRESH, and TONE_THRESH. Referenced by __ast_dsp_call_progress(). 00987 { 00988 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00989 /* Make sure absolute levels are high enough */ 00990 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 00991 return 0; 00992 /* Amplify ignored stuff */ 00993 i2 *= TONE_THRESH; 00994 i1 *= TONE_THRESH; 00995 e *= TONE_THRESH; 00996 /* Check first tone */ 00997 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 00998 return 0; 00999 /* And second */ 01000 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 01001 return 0; 01002 /* Guess it's there... */ 01003 return 1; 01004 }
|
|
Referenced by add_header(), ast_dsp_set_call_progress_zone(), and find_alias(). |
|
|
|
Initial value: { 1209.0, 1336.0, 1477.0, 1633.0 } |
|
|
|
Initial value: { 697.0, 770.0, 852.0, 941.0 } |
|
|
|
Initial value: { 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0 } Definition at line 248 of file dsp.c. Referenced by ast_mf_detect_init(). |
|
Referenced by ast_dsp_prog_reset(). |