#include "asterisk.h"
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.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 "asterisk/utils.h"
#include "asterisk/options.h"
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 | BUSYDETECT_MARTIN |
#define | DEFAULT_THRESHOLD 512 |
#define | DSP_HISTORY 15 |
#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 | MAX_DTMF_DIGITS 128 |
#define | MF_GSIZE 120 |
#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) |
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. | |
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 [] |
Steve Underwood <steveu@coppice.org>
Definition in file dsp.c.
#define DEFAULT_THRESHOLD 512 |
#define DSP_HISTORY 15 |
Remember last 15 units
Definition at line 125 of file dsp.c.
Referenced by __ast_dsp_silence(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().
#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_DETECT |
#define FIX_INF | ( | inf | ) |
Referenced by ast_dsp_process().
#define MAX_DTMF_DIGITS 128 |
#define MF_GSIZE 120 |
#define TONE_MIN_THRESH 1e8 |
How much tone there should be at least to attempt
Definition at line 131 of file dsp.c.
Referenced by __ast_dsp_call_progress(), and pair_there().
#define TONE_THRESH 10.0 |
How much louder the tone should be than channel energy
Definition at line 130 of file dsp.c.
Referenced by __ast_dsp_call_progress(), and pair_there().
enum busy_detect |
Definition at line 116 of file dsp.c.
00116 { 00117 BUSY_PERCENT = 10, /*!< The percentage difference between the two last tone periods */ 00118 BUSY_PAT_PERCENT = 8, /*!< The percentage difference between measured and actual pattern */ 00119 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */ 00120 BUSY_MIN = 150, /*!< Busy must be at least 150 ms in half-cadence */ 00121 BUSY_MAX = 600 /*!< Busy can't be longer than 600 ms in half-cadence */ 00122 };
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 77 of file dsp.c.
00077 { 00078 /*! For US modes { */ 00079 HZ_350 = 0, 00080 HZ_440, 00081 HZ_480, 00082 HZ_620, 00083 HZ_950, 00084 HZ_1400, 00085 HZ_1800, /*!< } */ 00086 00087 /*! For CR/BR modes */ 00088 HZ_425 = 0, 00089 00090 /*! For UK mode */ 00091 HZ_400 = 0 00092 };
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 65 of file dsp.c.
00065 { 00066 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ 00067 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */ 00068 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */ 00069 };
enum gsamp_thresh |
All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)
Definition at line 134 of file dsp.c.
00134 { 00135 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */ 00136 THRESH_TALK = 2, /*!< Talk detection does not work continuously */ 00137 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */ 00138 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */ 00139 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */ 00140 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */ 00141 };
enum prog_mode |
Definition at line 71 of file dsp.c.
00071 { 00072 PROG_MODE_NA = 0, 00073 PROG_MODE_CR, 00074 PROG_MODE_UK 00075 };
static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len | |||
) | [static] |
Definition at line 1074 of file dsp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_NOTICE, LOG_WARNING, pair_there(), PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_call_progress(), and ast_dsp_process().
01075 { 01076 int x; 01077 int y; 01078 int pass; 01079 int newstate = DSP_TONE_STATE_SILENCE; 01080 int res = 0; 01081 while(len) { 01082 /* Take the lesser of the number of samples we need and what we have */ 01083 pass = len; 01084 if (pass > dsp->gsamp_size - dsp->gsamps) 01085 pass = dsp->gsamp_size - dsp->gsamps; 01086 for (x=0;x<pass;x++) { 01087 for (y=0;y<dsp->freqcount;y++) 01088 goertzel_sample(&dsp->freqs[y], s[x]); 01089 dsp->genergy += s[x] * s[x]; 01090 } 01091 s += pass; 01092 dsp->gsamps += pass; 01093 len -= pass; 01094 if (dsp->gsamps == dsp->gsamp_size) { 01095 float hz[7]; 01096 for (y=0;y<7;y++) 01097 hz[y] = goertzel_result(&dsp->freqs[y]); 01098 #if 0 01099 printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n"); 01100 printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 01101 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); 01102 #endif 01103 switch(dsp->progmode) { 01104 case PROG_MODE_NA: 01105 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01106 newstate = DSP_TONE_STATE_BUSY; 01107 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01108 newstate = DSP_TONE_STATE_RINGING; 01109 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01110 newstate = DSP_TONE_STATE_DIALTONE; 01111 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01112 newstate = DSP_TONE_STATE_SPECIAL1; 01113 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01114 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 01115 newstate = DSP_TONE_STATE_SPECIAL2; 01116 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01117 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 01118 newstate = DSP_TONE_STATE_SPECIAL3; 01119 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01120 newstate = DSP_TONE_STATE_TALKING; 01121 } else 01122 newstate = DSP_TONE_STATE_SILENCE; 01123 break; 01124 case PROG_MODE_CR: 01125 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01126 newstate = DSP_TONE_STATE_RINGING; 01127 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01128 newstate = DSP_TONE_STATE_TALKING; 01129 } else 01130 newstate = DSP_TONE_STATE_SILENCE; 01131 break; 01132 case PROG_MODE_UK: 01133 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 01134 newstate = DSP_TONE_STATE_HUNGUP; 01135 } 01136 break; 01137 default: 01138 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01139 } 01140 if (newstate == dsp->tstate) { 01141 dsp->tcount++; 01142 if (dsp->ringtimeout) 01143 dsp->ringtimeout++; 01144 switch (dsp->tstate) { 01145 case DSP_TONE_STATE_RINGING: 01146 if ((dsp->features & DSP_PROGRESS_RINGING) && 01147 (dsp->tcount==THRESH_RING)) { 01148 res = AST_CONTROL_RINGING; 01149 dsp->ringtimeout= 1; 01150 } 01151 break; 01152 case DSP_TONE_STATE_BUSY: 01153 if ((dsp->features & DSP_PROGRESS_BUSY) && 01154 (dsp->tcount==THRESH_BUSY)) { 01155 res = AST_CONTROL_BUSY; 01156 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01157 } 01158 break; 01159 case DSP_TONE_STATE_TALKING: 01160 if ((dsp->features & DSP_PROGRESS_TALK) && 01161 (dsp->tcount==THRESH_TALK)) { 01162 res = AST_CONTROL_ANSWER; 01163 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01164 } 01165 break; 01166 case DSP_TONE_STATE_SPECIAL3: 01167 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01168 (dsp->tcount==THRESH_CONGESTION)) { 01169 res = AST_CONTROL_CONGESTION; 01170 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01171 } 01172 break; 01173 case DSP_TONE_STATE_HUNGUP: 01174 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01175 (dsp->tcount==THRESH_HANGUP)) { 01176 res = AST_CONTROL_HANGUP; 01177 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01178 } 01179 break; 01180 } 01181 if (dsp->ringtimeout==THRESH_RING2ANSWER) { 01182 #if 0 01183 ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n"); 01184 #endif 01185 res = AST_CONTROL_ANSWER; 01186 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01187 } 01188 } else { 01189 #if 0 01190 ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01191 ast_log(LOG_NOTICE, "Start state %d\n", newstate); 01192 #endif 01193 dsp->tstate = newstate; 01194 dsp->tcount = 1; 01195 } 01196 01197 /* Reset goertzel */ 01198 for (x=0;x<7;x++) 01199 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01200 dsp->gsamps = 0; 01201 dsp->genergy = 0.0; 01202 } 01203 } 01204 #if 0 01205 if (res) 01206 printf("Returning %d\n", res); 01207 #endif 01208 return res; 01209 }
static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | writeback | |||
) | [static] |
Definition at line 999 of file dsp.c.
References ast_dsp::digitmode, 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().
01000 { 01001 int res; 01002 01003 if (dsp->digitmode & DSP_DIGITMODE_MF) 01004 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 01005 else 01006 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT); 01007 return res; 01008 }
static int __ast_dsp_silence | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence | |||
) | [static] |
Definition at line 1224 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().
01225 { 01226 int accum; 01227 int x; 01228 int res = 0; 01229 01230 if (!len) 01231 return 0; 01232 accum = 0; 01233 for (x=0;x<len; x++) 01234 accum += abs(s[x]); 01235 accum /= len; 01236 if (accum < dsp->threshold) { 01237 /* Silent */ 01238 dsp->totalsilence += len/8; 01239 #ifdef DEBUG_DSP_BUSYDETECT 01240 fprintf(stderr, "SILENCE: len = %d, level = %d\n", dsp->totalsilence, accum); 01241 #endif 01242 if (dsp->totalnoise) { 01243 /* Move and save history */ 01244 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicnoise[0])); 01245 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01246 /* check if previous tone differs BUSY_PERCENT from the one before it */ 01247 int tone1 = dsp->historicnoise[DSP_HISTORY - 1]; 01248 int tone2 = dsp->historicnoise[DSP_HISTORY - 2]; 01249 if (tone1 < tone2) { 01250 if ((tone1 + tone1*BUSY_PERCENT/100) >= tone2) 01251 dsp->busymaybe = 1; 01252 else 01253 dsp->busymaybe = 0; 01254 } else { 01255 if ((tone1 - tone1*BUSY_PERCENT/100) <= tone2) 01256 dsp->busymaybe = 1; 01257 else 01258 dsp->busymaybe = 0; 01259 } 01260 } 01261 dsp->totalnoise = 0; 01262 res = 1; 01263 } else { 01264 /* Not silent */ 01265 dsp->totalnoise += len/8; 01266 #ifdef DEBUG_DSP_BUSYDETECT 01267 fprintf(stderr, "NOISE: len = %d, level = %d\n", dsp->totalnoise, accum); 01268 #endif 01269 if (dsp->totalsilence) { 01270 /* Move and save history */ 01271 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, (dsp->busycount-1)*sizeof(dsp->historicsilence[0])); 01272 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01273 } 01274 dsp->totalsilence = 0; 01275 } 01276 if (totalsilence) 01277 *totalsilence = dsp->totalsilence; 01278 return res; 01279 }
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 1282 of file dsp.c.
References ast_log(), 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().
01283 { 01284 int res = 0, x; 01285 int avgsilence = 0, hitsilence = 0; 01286 int avgtone = 0, hittone = 0; 01287 #ifdef DEBUG_DSP_BUSYDETECT 01288 char buf[16]; 01289 char silence_list[64]="", tone_list[64]=""; 01290 #endif 01291 01292 if (!dsp->busymaybe) 01293 return res; 01294 dsp->busymaybe = 0; 01295 01296 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01297 avgsilence += dsp->historicsilence[x]; 01298 avgtone += dsp->historicnoise[x]; 01299 } 01300 avgsilence /= dsp->busycount; 01301 avgtone /= dsp->busycount; 01302 #ifdef DEBUG_DSP_BUSYDETECT 01303 sprintf(silence_list,"Silences: "); 01304 sprintf(tone_list,"Tones: "); 01305 #endif 01306 for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) { 01307 #ifdef DEBUG_DSP_BUSYDETECT 01308 snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]); 01309 strcat(silence_list, buf); 01310 snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]); 01311 strcat(tone_list, buf); 01312 #endif 01313 if (!dsp->busytoneonly) { 01314 if (avgsilence > dsp->historicsilence[x]) { 01315 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01316 hitsilence++; 01317 } else { 01318 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01319 hitsilence++; 01320 } 01321 } 01322 if (avgtone > dsp->historicnoise[x]) { 01323 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01324 hittone++; 01325 } else { 01326 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01327 hittone++; 01328 } 01329 } 01330 #ifdef DEBUG_DSP_BUSYDETECT 01331 fprintf(stderr, "BUSY DETECTOR\n"); 01332 fprintf(stderr, "%s\n", tone_list); 01333 fprintf(stderr, "%s\n", silence_list) 01334 #endif 01335 if ((dsp->busytoneonly || 01336 (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) && 01337 (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01338 if (dsp->busycompare) { 01339 if (dsp->busytoneonly) { 01340 res = 1; 01341 ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare"); 01342 } else { 01343 if (avgtone > avgsilence) { 01344 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01345 res = 1; 01346 } else { 01347 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01348 res = 1; 01349 } 01350 } 01351 } else { 01352 res = 1; 01353 } 01354 } 01355 /* If we know the expected busy tone length, check we are in the range */ 01356 if (res && (dsp->busy_tonelength > 0)) { 01357 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) { 01358 if(option_debug) { 01359 ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength); 01360 } 01361 res = 0; 01362 } 01363 } 01364 /* If we know the expected busy tone silent-period length, check we are in the range */ 01365 if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) { 01366 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) { 01367 if(option_debug) { 01368 ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength); 01369 } 01370 res = 0; 01371 } 01372 } 01373 if (res && option_debug) 01374 ast_log(LOG_NOTICE, "Detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01375 return res; 01376 }
Scans for progress indication in audio.
Definition at line 1211 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.
01212 { 01213 if (inf->frametype != AST_FRAME_VOICE) { 01214 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01215 return 0; 01216 } 01217 if (inf->subclass != AST_FORMAT_SLINEAR) { 01218 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01219 return 0; 01220 } 01221 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01222 }
Return non-zero if DTMF hit was found.
Definition at line 1010 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.
01011 { 01012 short *s; 01013 int len; 01014 int ign=0; 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 s = inf->data; 01025 len = inf->datalen / 2; 01026 return __ast_dsp_digitdetect(dsp, s, len, &ign); 01027 }
int ast_dsp_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1807 of file dsp.c.
References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_setoption(), mgcp_new(), sip_new(), and ss_thread().
01808 { 01809 int new; 01810 int old; 01811 01812 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01813 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01814 if (old != new) { 01815 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01816 if (new & DSP_DIGITMODE_MF) 01817 ast_mf_detect_init(&dsp->td.mf); 01818 else 01819 ast_dtmf_detect_init(&dsp->td.dtmf); 01820 } 01821 dsp->digitmode = digitmode; 01822 return 0; 01823 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1744 of file dsp.c.
References dtmf_detect_state_t::col_out, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_sample, dtmf_detect_state_t::current_sample, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, dtmf_detect_state_t::energy, dtmf_detect_state_t::fax_tone, goertzel_reset(), mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, ast_dsp::mf, mf_detect_state_t::mhit, dtmf_detect_state_t::mhit, dtmf_detect_state_t::row_out, ast_dsp::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out.
Referenced by ss_thread().
01745 { 01746 int i; 01747 01748 dsp->thinkdigit = 0; 01749 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01750 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01751 dsp->td.mf.current_digits = 0; 01752 /* Reinitialise the detector for the next block */ 01753 for (i = 0; i < 6; i++) { 01754 goertzel_reset(&dsp->td.mf.tone_out[i]); 01755 #ifdef OLD_DSP_ROUTINES 01756 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01757 #endif 01758 } 01759 #ifdef OLD_DSP_ROUTINES 01760 dsp->td.mf.energy = 0.0; 01761 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01762 #else 01763 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; 01764 #endif 01765 dsp->td.mf.current_sample = 0; 01766 } else { 01767 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01768 dsp->td.dtmf.current_digits = 0; 01769 /* Reinitialise the detector for the next block */ 01770 for (i = 0; i < 4; i++) { 01771 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01772 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01773 #ifdef OLD_DSP_ROUTINES 01774 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01775 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01776 #endif 01777 } 01778 #ifdef FAX_DETECT 01779 goertzel_reset (&dsp->td.dtmf.fax_tone); 01780 #endif 01781 #ifdef OLD_DSP_ROUTINES 01782 #ifdef FAX_DETECT 01783 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01784 #endif 01785 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01786 #else 01787 dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0; 01788 #endif 01789 dsp->td.dtmf.energy = 0.0; 01790 dsp->td.dtmf.current_sample = 0; 01791 } 01792 }
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 Zap 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 1849 of file dsp.c.
References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, f, and ast_dsp::freqcount.
Referenced by ast_frame_free().
01850 { 01851 struct ast_dsp *dsp; 01852 01853 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP); 01854 01855 dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f)); 01856 01857 if (dsp->freqcount != -1) 01858 return; 01859 01860 ast_dsp_free(dsp); 01861 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1691 of file dsp.c.
References AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::f, free, and ast_dsp::freqcount.
Referenced by __ast_play_and_record(), __oh323_destroy(), ast_dsp_frame_freed(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), dahdi_hangup(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), and ss_thread().
01692 { 01693 if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) { 01694 /* If this flag is still set, that means that the dsp's destruction 01695 * been torn down, while we still have a frame out there being used. 01696 * When ast_frfree() gets called on that frame, this ast_trans_pvt 01697 * will get destroyed, too. */ 01698 01699 /* Set the magic hint that this has been requested to be destroyed. */ 01700 dsp->freqcount = -1; 01701 01702 return; 01703 } 01704 free(dsp); 01705 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1844 of file dsp.c.
References ast_dsp::tcount.
01845 { 01846 return dsp->tcount; 01847 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1839 of file dsp.c.
References ast_dsp::tstate.
01840 { 01841 return dsp->tstate; 01842 }
int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, | |
char * | buf, | |||
int | max | |||
) |
Get pending DTMF/MF digits.
Definition at line 1049 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_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.
01050 { 01051 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01052 if (max > dsp->td.mf.current_digits) 01053 max = dsp->td.mf.current_digits; 01054 if (max > 0) { 01055 memcpy(buf, dsp->td.mf.digits, max); 01056 memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 01057 dsp->td.mf.current_digits -= max; 01058 } 01059 buf[max] = '\0'; 01060 return max; 01061 } else { 01062 if (max > dsp->td.dtmf.current_digits) 01063 max = dsp->td.dtmf.current_digits; 01064 if (max > 0) { 01065 memcpy (buf, dsp->td.dtmf.digits, max); 01066 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01067 dsp->td.dtmf.current_digits -= max; 01068 } 01069 buf[max] = '\0'; 01070 return max; 01071 } 01072 }
struct ast_dsp* ast_dsp_new | ( | void | ) |
Definition at line 1656 of file dsp.c.
References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, 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(), and sip_new().
01657 { 01658 struct ast_dsp *dsp; 01659 01660 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01661 dsp->threshold = DEFAULT_THRESHOLD; 01662 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01663 dsp->busycount = DSP_HISTORY; 01664 dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT; 01665 #ifdef BUSYDETECT_TONEONLY 01666 dsp->busytoneonly = 1; 01667 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01668 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE"); 01669 #endif 01670 #else 01671 dsp->busytoneonly = 0; 01672 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01673 dsp->busycompare = 1; 01674 #else 01675 dsp->busycompare = 0; 01676 #endif 01677 #endif 01678 /* Initialize DTMF detector */ 01679 ast_dtmf_detect_init(&dsp->td.dtmf); 01680 /* Initialize initial DSP progress detect parameters */ 01681 ast_dsp_prog_reset(dsp); 01682 } 01683 return dsp; 01684 }
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 1442 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_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, 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_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, len(), LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.
Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().
01443 { 01444 int silence; 01445 int res; 01446 int digit; 01447 int x; 01448 short *shortdata; 01449 unsigned char *odata; 01450 int len; 01451 int writeback = 0; 01452 01453 #define FIX_INF(inf) do { \ 01454 if (writeback) { \ 01455 switch(inf->subclass) { \ 01456 case AST_FORMAT_SLINEAR: \ 01457 break; \ 01458 case AST_FORMAT_ULAW: \ 01459 for (x=0;x<len;x++) \ 01460 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01461 break; \ 01462 case AST_FORMAT_ALAW: \ 01463 for (x=0;x<len;x++) \ 01464 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01465 break; \ 01466 } \ 01467 } \ 01468 } while(0) 01469 01470 if (!af) 01471 return NULL; 01472 if (af->frametype != AST_FRAME_VOICE) 01473 return af; 01474 odata = af->data; 01475 len = af->datalen; 01476 /* Make sure we have short data */ 01477 switch(af->subclass) { 01478 case AST_FORMAT_SLINEAR: 01479 shortdata = af->data; 01480 len = af->datalen / 2; 01481 break; 01482 case AST_FORMAT_ULAW: 01483 shortdata = alloca(af->datalen * 2); 01484 for (x = 0;x < len; x++) 01485 shortdata[x] = AST_MULAW(odata[x]); 01486 break; 01487 case AST_FORMAT_ALAW: 01488 shortdata = alloca(af->datalen * 2); 01489 for (x = 0; x < len; x++) 01490 shortdata[x] = AST_ALAW(odata[x]); 01491 break; 01492 default: 01493 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01494 return af; 01495 } 01496 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01497 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01498 memset(&dsp->f, 0, sizeof(dsp->f)); 01499 dsp->f.frametype = AST_FRAME_NULL; 01500 ast_frfree(af); 01501 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01502 return &dsp->f; 01503 } 01504 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01505 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01506 memset(&dsp->f, 0, sizeof(dsp->f)); 01507 dsp->f.frametype = AST_FRAME_CONTROL; 01508 dsp->f.subclass = AST_CONTROL_BUSY; 01509 ast_frfree(af); 01510 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01511 return &dsp->f; 01512 } 01513 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01514 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01515 #if 0 01516 if (digit) 01517 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01518 #endif 01519 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01520 if (!dsp->thinkdigit) { 01521 if (digit) { 01522 /* Looks like we might have something. 01523 * Request a conference mute for the moment */ 01524 memset(&dsp->f, 0, sizeof(dsp->f)); 01525 dsp->f.frametype = AST_FRAME_DTMF; 01526 dsp->f.subclass = 'm'; 01527 dsp->thinkdigit = 'x'; 01528 FIX_INF(af); 01529 if (chan) 01530 ast_queue_frame(chan, af); 01531 ast_frfree(af); 01532 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01533 return &dsp->f; 01534 } 01535 } else { 01536 if (digit) { 01537 /* Thought we saw one last time. Pretty sure we really have now */ 01538 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01539 /* If we found a digit, and we're changing digits, go 01540 ahead and send this one, but DON'T stop confmute because 01541 we're detecting something else, too... */ 01542 memset(&dsp->f, 0, sizeof(dsp->f)); 01543 dsp->f.frametype = AST_FRAME_DTMF_END; 01544 dsp->f.subclass = dsp->thinkdigit; 01545 FIX_INF(af); 01546 if (chan) 01547 ast_queue_frame(chan, af); 01548 ast_frfree(af); 01549 } else { 01550 dsp->thinkdigit = digit; 01551 memset(&dsp->f, 0, sizeof(dsp->f)); 01552 dsp->f.frametype = AST_FRAME_DTMF_BEGIN; 01553 dsp->f.subclass = dsp->thinkdigit; 01554 FIX_INF(af); 01555 if (chan) 01556 ast_queue_frame(chan, af); 01557 ast_frfree(af); 01558 } 01559 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01560 return &dsp->f; 01561 } else { 01562 memset(&dsp->f, 0, sizeof(dsp->f)); 01563 if (dsp->thinkdigit != 'x') { 01564 /* If we found a digit, send it now */ 01565 dsp->f.frametype = AST_FRAME_DTMF_END; 01566 dsp->f.subclass = dsp->thinkdigit; 01567 dsp->thinkdigit = 0; 01568 } else { 01569 dsp->f.frametype = AST_FRAME_DTMF; 01570 dsp->f.subclass = 'u'; 01571 dsp->thinkdigit = 0; 01572 } 01573 FIX_INF(af); 01574 if (chan) 01575 ast_queue_frame(chan, af); 01576 ast_frfree(af); 01577 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01578 return &dsp->f; 01579 } 01580 } 01581 } else if (!digit) { 01582 /* Only check when there is *not* a hit... */ 01583 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01584 if (dsp->td.mf.current_digits) { 01585 memset(&dsp->f, 0, sizeof(dsp->f)); 01586 dsp->f.frametype = AST_FRAME_DTMF; 01587 dsp->f.subclass = dsp->td.mf.digits[0]; 01588 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01589 dsp->td.mf.current_digits--; 01590 FIX_INF(af); 01591 if (chan) 01592 ast_queue_frame(chan, af); 01593 ast_frfree(af); 01594 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01595 return &dsp->f; 01596 } 01597 } else { 01598 if (dsp->td.dtmf.current_digits) { 01599 memset(&dsp->f, 0, sizeof(dsp->f)); 01600 dsp->f.frametype = AST_FRAME_DTMF_END; 01601 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01602 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01603 dsp->td.dtmf.current_digits--; 01604 FIX_INF(af); 01605 if (chan) 01606 ast_queue_frame(chan, af); 01607 ast_frfree(af); 01608 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); 01609 return &dsp->f; 01610 } 01611 } 01612 } 01613 } 01614 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01615 res = __ast_dsp_call_progress(dsp, shortdata, len); 01616 if (res) { 01617 switch(res) { 01618 case AST_CONTROL_ANSWER: 01619 case AST_CONTROL_BUSY: 01620 case AST_CONTROL_RINGING: 01621 case AST_CONTROL_CONGESTION: 01622 case AST_CONTROL_HANGUP: 01623 memset(&dsp->f, 0, sizeof(dsp->f)); 01624 dsp->f.frametype = AST_FRAME_CONTROL; 01625 dsp->f.subclass = res; 01626 dsp->f.src = "dsp_progress"; 01627 if (chan) 01628 ast_queue_frame(chan, &dsp->f); 01629 break; 01630 default: 01631 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01632 } 01633 } 01634 } 01635 FIX_INF(af); 01636 return af; 01637 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1639 of file dsp.c.
References ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, ast_dsp::ringtimeout, and progress::size.
Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().
01640 { 01641 int max = 0; 01642 int x; 01643 01644 dsp->gsamp_size = modes[dsp->progmode].size; 01645 dsp->gsamps = 0; 01646 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { 01647 if (modes[dsp->progmode].freqs[x]) { 01648 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01649 max = x + 1; 01650 } 01651 } 01652 dsp->freqcount = max; 01653 dsp->ringtimeout= 0; 01654 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1794 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.
01795 { 01796 int x; 01797 01798 dsp->totalsilence = 0; 01799 dsp->gsamps = 0; 01800 for (x=0;x<4;x++) 01801 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01802 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01803 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01804 dsp->ringtimeout= 0; 01805 }
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 1724 of file dsp.c.
References ast_dsp::busycompare.
Referenced by dahdi_new().
01725 { 01726 if (compare > 0) 01727 dsp->busycompare = 1; 01728 else 01729 dsp->busycompare = 0; 01730 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1715 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01716 { 01717 if (cadences < 4) 01718 cadences = 4; 01719 if (cadences > DSP_HISTORY) 01720 cadences = DSP_HISTORY; 01721 dsp->busycount = cadences; 01722 }
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 1732 of file dsp.c.
References ast_log(), ast_dsp::busy_pattern_fuzzy, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busytoneonly, and LOG_DEBUG.
Referenced by dahdi_new().
01733 { 01734 dsp->busy_tonelength = tonelength; 01735 if (quietlength > 0) 01736 dsp->busy_quietlength = quietlength; 01737 else 01738 dsp->busytoneonly = 1; 01739 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01740 if( fuzzy > 0 && fuzzy < 50 ) 01741 dsp->busy_pattern_fuzzy = fuzzy; 01742 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1825 of file dsp.c.
References aliases, ast_dsp_prog_reset(), name, and ast_dsp::progmode.
Referenced by dahdi_new().
01826 { 01827 int x; 01828 01829 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) { 01830 if (!strcasecmp(aliases[x].name, zone)) { 01831 dsp->progmode = aliases[x].mode; 01832 ast_dsp_prog_reset(dsp); 01833 return 0; 01834 } 01835 } 01836 return -1; 01837 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1686 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(), and sip_new().
void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, | |
int | threshold | |||
) |
Set threshold value for silence.
Definition at line 1707 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), dahdi_new(), do_waiting(), handle_recordfile(), and isAnsweringMachine().
01708 { 01709 if (threshold < 256) 01710 dsp->threshold = 256; 01711 else 01712 dsp->threshold = threshold; 01713 }
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1424 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().
01425 { 01426 short *s; 01427 int len; 01428 01429 if (f->frametype != AST_FRAME_VOICE) { 01430 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01431 return 0; 01432 } 01433 if (f->subclass != AST_FORMAT_SLINEAR) { 01434 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01435 return 0; 01436 } 01437 s = f->data; 01438 len = f->datalen/2; 01439 return __ast_dsp_silence(dsp, s, len, totalsilence); 01440 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 367 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_dsp_digitmode(), and ast_dsp_new().
00368 { 00369 int i; 00370 00371 #ifdef OLD_DSP_ROUTINES 00372 s->hit1 = 00373 s->mhit = 00374 s->hit3 = 00375 s->hit4 = 00376 s->hit2 = 0; 00377 #else 00378 s->lasthit = 0; 00379 #endif 00380 for (i = 0; i < 4; i++) { 00381 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00382 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00383 #ifdef OLD_DSP_ROUTINES 00384 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102); 00385 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102); 00386 #endif 00387 s->energy = 0.0; 00388 } 00389 #ifdef FAX_DETECT 00390 /* Same for the fax dector */ 00391 goertzel_init (&s->fax_tone, fax_freq, 102); 00392 00393 #ifdef OLD_DSP_ROUTINES 00394 /* Same for the fax dector 2nd harmonic */ 00395 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102); 00396 #endif 00397 #endif /* FAX_DETECT */ 00398 s->current_sample = 0; 00399 s->detected_digits = 0; 00400 s->current_digits = 0; 00401 memset(&s->digits, 0, sizeof(s->digits)); 00402 s->lost_digits = 0; 00403 s->digits[0] = '\0'; 00404 }
static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 406 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_dsp_digitmode().
00407 { 00408 int i; 00409 #ifdef OLD_DSP_ROUTINES 00410 s->hit1 = 00411 s->hit2 = 0; 00412 #else 00413 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00414 #endif 00415 for (i = 0; i < 6; i++) { 00416 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00417 #ifdef OLD_DSP_ROUTINES 00418 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160); 00419 s->energy = 0.0; 00420 #endif 00421 } 00422 s->current_digits = 0; 00423 memset(&s->digits, 0, sizeof(s->digits)); 00424 s->current_sample = 0; 00425 s->detected_digits = 0; 00426 s->lost_digits = 0; 00427 s->digits[0] = '\0'; 00428 s->mhit = 0; 00429 }
static int dtmf_detect | ( | dtmf_detect_state_t * | s, | |
int16_t | amp[], | |||
int | samples, | |||
int | digitmode, | |||
int * | writeback, | |||
int | faxdetect | |||
) | [static] |
Definition at line 431 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(), MAX_DTMF_DIGITS, and s.
Referenced by __ast_dsp_digitdetect().
00433 { 00434 float row_energy[4]; 00435 float col_energy[4]; 00436 #ifdef FAX_DETECT 00437 float fax_energy; 00438 #ifdef OLD_DSP_ROUTINES 00439 float fax_energy_2nd; 00440 #endif 00441 #endif /* FAX_DETECT */ 00442 float famp; 00443 float v1; 00444 int i; 00445 int j; 00446 int sample; 00447 int best_row; 00448 int best_col; 00449 int hit; 00450 int limit; 00451 00452 hit = 0; 00453 for (sample = 0; sample < samples; sample = limit) { 00454 /* 102 is optimised to meet the DTMF specs. */ 00455 if ((samples - sample) >= (102 - s->current_sample)) 00456 limit = sample + (102 - s->current_sample); 00457 else 00458 limit = samples; 00459 #if defined(USE_3DNOW) 00460 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00461 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00462 #ifdef OLD_DSP_ROUTINES 00463 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00464 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00465 #endif 00466 /* XXX Need to fax detect for 3dnow too XXX */ 00467 #warning "Fax Support Broken" 00468 #else 00469 /* The following unrolled loop takes only 35% (rough estimate) of the 00470 time of a rolled loop on the machine on which it was developed */ 00471 for (j=sample;j<limit;j++) { 00472 famp = amp[j]; 00473 s->energy += famp*famp; 00474 /* With GCC 2.95, the following unrolled code seems to take about 35% 00475 (rough estimate) as long as a neat little 0-3 loop */ 00476 v1 = s->row_out[0].v2; 00477 s->row_out[0].v2 = s->row_out[0].v3; 00478 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; 00479 v1 = s->col_out[0].v2; 00480 s->col_out[0].v2 = s->col_out[0].v3; 00481 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; 00482 v1 = s->row_out[1].v2; 00483 s->row_out[1].v2 = s->row_out[1].v3; 00484 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; 00485 v1 = s->col_out[1].v2; 00486 s->col_out[1].v2 = s->col_out[1].v3; 00487 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; 00488 v1 = s->row_out[2].v2; 00489 s->row_out[2].v2 = s->row_out[2].v3; 00490 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; 00491 v1 = s->col_out[2].v2; 00492 s->col_out[2].v2 = s->col_out[2].v3; 00493 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; 00494 v1 = s->row_out[3].v2; 00495 s->row_out[3].v2 = s->row_out[3].v3; 00496 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; 00497 v1 = s->col_out[3].v2; 00498 s->col_out[3].v2 = s->col_out[3].v3; 00499 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; 00500 #ifdef FAX_DETECT 00501 /* Update fax tone */ 00502 v1 = s->fax_tone.v2; 00503 s->fax_tone.v2 = s->fax_tone.v3; 00504 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; 00505 #endif /* FAX_DETECT */ 00506 #ifdef OLD_DSP_ROUTINES 00507 v1 = s->col_out2nd[0].v2; 00508 s->col_out2nd[0].v2 = s->col_out2nd[0].v3; 00509 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; 00510 v1 = s->row_out2nd[0].v2; 00511 s->row_out2nd[0].v2 = s->row_out2nd[0].v3; 00512 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; 00513 v1 = s->col_out2nd[1].v2; 00514 s->col_out2nd[1].v2 = s->col_out2nd[1].v3; 00515 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; 00516 v1 = s->row_out2nd[1].v2; 00517 s->row_out2nd[1].v2 = s->row_out2nd[1].v3; 00518 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; 00519 v1 = s->col_out2nd[2].v2; 00520 s->col_out2nd[2].v2 = s->col_out2nd[2].v3; 00521 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; 00522 v1 = s->row_out2nd[2].v2; 00523 s->row_out2nd[2].v2 = s->row_out2nd[2].v3; 00524 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; 00525 v1 = s->col_out2nd[3].v2; 00526 s->col_out2nd[3].v2 = s->col_out2nd[3].v3; 00527 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; 00528 v1 = s->row_out2nd[3].v2; 00529 s->row_out2nd[3].v2 = s->row_out2nd[3].v3; 00530 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; 00531 #ifdef FAX_DETECT 00532 /* Update fax tone */ 00533 v1 = s->fax_tone.v2; 00534 s->fax_tone2nd.v2 = s->fax_tone2nd.v3; 00535 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; 00536 #endif /* FAX_DETECT */ 00537 #endif 00538 } 00539 #endif 00540 s->current_sample += (limit - sample); 00541 if (s->current_sample < 102) { 00542 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00543 /* If we had a hit last time, go ahead and clear this out since likely it 00544 will be another hit */ 00545 for (i=sample;i<limit;i++) 00546 amp[i] = 0; 00547 *writeback = 1; 00548 } 00549 continue; 00550 } 00551 #ifdef FAX_DETECT 00552 /* Detect the fax energy, too */ 00553 fax_energy = goertzel_result(&s->fax_tone); 00554 #endif 00555 /* We are at the end of a DTMF detection block */ 00556 /* Find the peak row and the peak column */ 00557 row_energy[0] = goertzel_result (&s->row_out[0]); 00558 col_energy[0] = goertzel_result (&s->col_out[0]); 00559 00560 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00561 row_energy[i] = goertzel_result (&s->row_out[i]); 00562 if (row_energy[i] > row_energy[best_row]) 00563 best_row = i; 00564 col_energy[i] = goertzel_result (&s->col_out[i]); 00565 if (col_energy[i] > col_energy[best_col]) 00566 best_col = i; 00567 } 00568 hit = 0; 00569 /* Basic signal level test and the twist test */ 00570 if (row_energy[best_row] >= DTMF_THRESHOLD && 00571 col_energy[best_col] >= DTMF_THRESHOLD && 00572 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00573 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00574 /* Relative peak test */ 00575 for (i = 0; i < 4; i++) { 00576 if ((i != best_col && 00577 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00578 (i != best_row 00579 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00580 break; 00581 } 00582 } 00583 #ifdef OLD_DSP_ROUTINES 00584 /* ... and second harmonic test */ 00585 if (i >= 4 && 00586 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy && 00587 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] 00588 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { 00589 #else 00590 /* ... and fraction of total energy test */ 00591 if (i >= 4 && 00592 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) { 00593 #endif 00594 /* Got a hit */ 00595 hit = dtmf_positions[(best_row << 2) + best_col]; 00596 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00597 /* Zero out frame data if this is part DTMF */ 00598 for (i=sample;i<limit;i++) 00599 amp[i] = 0; 00600 *writeback = 1; 00601 } 00602 #ifdef OLD_DSP_ROUTINES 00603 /* Look for two successive similar results */ 00604 /* The logic in the next test is: 00605 We need two successive identical clean detects, with 00606 something different preceeding it. This can work with 00607 back to back differing digits. More importantly, it 00608 can work with nasty phones that give a very wobbly start 00609 to a digit */ 00610 if (hit == s->hit3 && s->hit3 != s->hit2) { 00611 s->mhit = hit; 00612 s->digit_hits[(best_row << 2) + best_col]++; 00613 s->detected_digits++; 00614 if (s->current_digits < MAX_DTMF_DIGITS) { 00615 s->digits[s->current_digits++] = hit; 00616 s->digits[s->current_digits] = '\0'; 00617 } else { 00618 s->lost_digits++; 00619 } 00620 } 00621 #endif 00622 } 00623 } 00624 00625 #ifndef OLD_DSP_ROUTINES 00626 /* Look for two successive similar results */ 00627 /* The logic in the next test is: 00628 We need two successive identical clean detects, with 00629 something different preceeding it. This can work with 00630 back to back differing digits. More importantly, it 00631 can work with nasty phones that give a very wobbly start 00632 to a digit */ 00633 if (hit == s->lasthit && hit != s->mhit) { 00634 if (hit) { 00635 s->digit_hits[(best_row << 2) + best_col]++; 00636 s->detected_digits++; 00637 if (s->current_digits < MAX_DTMF_DIGITS) { 00638 s->digits[s->current_digits++] = hit; 00639 s->digits[s->current_digits] = '\0'; 00640 } else { 00641 s->lost_digits++; 00642 } 00643 } 00644 s->mhit = hit; 00645 } 00646 #endif 00647 00648 #ifdef FAX_DETECT 00649 if (!hit && (fax_energy >= FAX_THRESHOLD) && 00650 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) && 00651 (faxdetect)) { 00652 #if 0 00653 printf("Fax energy/Second Harmonic: %f\n", fax_energy); 00654 #endif 00655 /* XXX Probably need better checking than just this the energy XXX */ 00656 hit = 'f'; 00657 s->fax_hits++; 00658 } else { 00659 if (s->fax_hits > 5) { 00660 hit = 'f'; 00661 s->mhit = 'f'; 00662 s->detected_digits++; 00663 if (s->current_digits < MAX_DTMF_DIGITS) { 00664 s->digits[s->current_digits++] = hit; 00665 s->digits[s->current_digits] = '\0'; 00666 } else { 00667 s->lost_digits++; 00668 } 00669 } 00670 s->fax_hits = 0; 00671 } 00672 #endif /* FAX_DETECT */ 00673 #ifdef OLD_DSP_ROUTINES 00674 s->hit1 = s->hit2; 00675 s->hit2 = s->hit3; 00676 s->hit3 = hit; 00677 #else 00678 s->lasthit = hit; 00679 #endif 00680 /* Reinitialise the detector for the next block */ 00681 for (i = 0; i < 4; i++) { 00682 goertzel_reset(&s->row_out[i]); 00683 goertzel_reset(&s->col_out[i]); 00684 #ifdef OLD_DSP_ROUTINES 00685 goertzel_reset(&s->row_out2nd[i]); 00686 goertzel_reset(&s->col_out2nd[i]); 00687 #endif 00688 } 00689 #ifdef FAX_DETECT 00690 goertzel_reset (&s->fax_tone); 00691 #ifdef OLD_DSP_ROUTINES 00692 goertzel_reset (&s->fax_tone2nd); 00693 #endif 00694 #endif 00695 s->energy = 0.0; 00696 s->current_sample = 0; 00697 } 00698 #ifdef OLD_DSP_ROUTINES 00699 if ((!s->mhit) || (s->mhit != hit)) { 00700 s->mhit = 0; 00701 return(0); 00702 } 00703 return (hit); 00704 #else 00705 return (s->mhit); /* return the debounced hit */ 00706 #endif 00707 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 321 of file dsp.c.
References s.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), and ast_mf_detect_init().
00322 { 00323 s->v2 = s->v3 = 0.0; 00324 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0)); 00325 #ifndef OLD_DSP_ROUTINES 00326 s->samples = samples; 00327 #endif 00328 }
static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 316 of file dsp.c.
References s.
Referenced by __ast_dsp_call_progress(), dtmf_detect(), and mf_detect().
static void goertzel_sample | ( | goertzel_state_t * | s, | |
short | sample | |||
) | [inline, static] |
static void goertzel_update | ( | goertzel_state_t * | s, | |
short * | samps, | |||
int | count | |||
) | [inline, static] |
Definition at line 307 of file dsp.c.
References goertzel_sample(), and s.
00308 { 00309 int i; 00310 00311 for (i=0;i<count;i++) 00312 goertzel_sample(s, samps[i]); 00313 }
static int mf_detect | ( | mf_detect_state_t * | s, | |
int16_t | amp[], | |||
int | samples, | |||
int | digitmode, | |||
int * | writeback | |||
) | [static] |
Definition at line 716 of file dsp.c.
References DSP_DIGITMODE_NOQUELCH, goertzel_result(), MAX_DTMF_DIGITS, MF_GSIZE, and s.
Referenced by __ast_dsp_digitdetect().
00718 { 00719 #ifdef OLD_DSP_ROUTINES 00720 float tone_energy[6]; 00721 int best1; 00722 int best2; 00723 float max; 00724 int sofarsogood; 00725 #else 00726 float energy[6]; 00727 int best; 00728 int second_best; 00729 #endif 00730 float famp; 00731 float v1; 00732 int i; 00733 int j; 00734 int sample; 00735 int hit; 00736 int limit; 00737 00738 hit = 0; 00739 for (sample = 0; sample < samples; sample = limit) { 00740 /* 80 is optimised to meet the MF specs. */ 00741 if ((samples - sample) >= (MF_GSIZE - s->current_sample)) 00742 limit = sample + (MF_GSIZE - s->current_sample); 00743 else 00744 limit = samples; 00745 #if defined(USE_3DNOW) 00746 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00747 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00748 #ifdef OLD_DSP_ROUTINES 00749 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00750 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00751 #endif 00752 /* XXX Need to fax detect for 3dnow too XXX */ 00753 #warning "Fax Support Broken" 00754 #else 00755 /* The following unrolled loop takes only 35% (rough estimate) of the 00756 time of a rolled loop on the machine on which it was developed */ 00757 for (j = sample; j < limit; j++) { 00758 famp = amp[j]; 00759 #ifdef OLD_DSP_ROUTINES 00760 s->energy += famp*famp; 00761 #endif 00762 /* With GCC 2.95, the following unrolled code seems to take about 35% 00763 (rough estimate) as long as a neat little 0-3 loop */ 00764 v1 = s->tone_out[0].v2; 00765 s->tone_out[0].v2 = s->tone_out[0].v3; 00766 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp; 00767 v1 = s->tone_out[1].v2; 00768 s->tone_out[1].v2 = s->tone_out[1].v3; 00769 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp; 00770 v1 = s->tone_out[2].v2; 00771 s->tone_out[2].v2 = s->tone_out[2].v3; 00772 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp; 00773 v1 = s->tone_out[3].v2; 00774 s->tone_out[3].v2 = s->tone_out[3].v3; 00775 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp; 00776 v1 = s->tone_out[4].v2; 00777 s->tone_out[4].v2 = s->tone_out[4].v3; 00778 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp; 00779 v1 = s->tone_out[5].v2; 00780 s->tone_out[5].v2 = s->tone_out[5].v3; 00781 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp; 00782 #ifdef OLD_DSP_ROUTINES 00783 v1 = s->tone_out2nd[0].v2; 00784 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3; 00785 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp; 00786 v1 = s->tone_out2nd[1].v2; 00787 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3; 00788 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp; 00789 v1 = s->tone_out2nd[2].v2; 00790 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3; 00791 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp; 00792 v1 = s->tone_out2nd[3].v2; 00793 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3; 00794 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp; 00795 v1 = s->tone_out2nd[4].v2; 00796 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3; 00797 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp; 00798 v1 = s->tone_out2nd[3].v2; 00799 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3; 00800 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp; 00801 #endif 00802 } 00803 #endif 00804 s->current_sample += (limit - sample); 00805 if (s->current_sample < MF_GSIZE) { 00806 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00807 /* If we had a hit last time, go ahead and clear this out since likely it 00808 will be another hit */ 00809 for (i=sample;i<limit;i++) 00810 amp[i] = 0; 00811 *writeback = 1; 00812 } 00813 continue; 00814 } 00815 #ifdef OLD_DSP_ROUTINES 00816 /* We're at the end of an MF detection block. Go ahead and calculate 00817 all the energies. */ 00818 for (i=0;i<6;i++) { 00819 tone_energy[i] = goertzel_result(&s->tone_out[i]); 00820 } 00821 /* Find highest */ 00822 best1 = 0; 00823 max = tone_energy[0]; 00824 for (i=1;i<6;i++) { 00825 if (tone_energy[i] > max) { 00826 max = tone_energy[i]; 00827 best1 = i; 00828 } 00829 } 00830 00831 /* Find 2nd highest */ 00832 if (best1) { 00833 max = tone_energy[0]; 00834 best2 = 0; 00835 } else { 00836 max = tone_energy[1]; 00837 best2 = 1; 00838 } 00839 00840 for (i=0;i<6;i++) { 00841 if (i == best1) continue; 00842 if (tone_energy[i] > max) { 00843 max = tone_energy[i]; 00844 best2 = i; 00845 } 00846 } 00847 hit = 0; 00848 if (best1 != best2) 00849 sofarsogood=1; 00850 else 00851 sofarsogood=0; 00852 /* Check for relative energies */ 00853 for (i=0;i<6;i++) { 00854 if (i == best1) 00855 continue; 00856 if (i == best2) 00857 continue; 00858 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) { 00859 sofarsogood = 0; 00860 break; 00861 } 00862 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) { 00863 sofarsogood = 0; 00864 break; 00865 } 00866 } 00867 00868 if (sofarsogood) { 00869 /* Check for 2nd harmonic */ 00870 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 00871 sofarsogood = 0; 00872 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2]) 00873 sofarsogood = 0; 00874 } 00875 if (sofarsogood) { 00876 hit = mf_hit[best1][best2]; 00877 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00878 /* Zero out frame data if this is part DTMF */ 00879 for (i=sample;i<limit;i++) 00880 amp[i] = 0; 00881 *writeback = 1; 00882 } 00883 /* Look for two consecutive clean hits */ 00884 if ((hit == s->hit3) && (s->hit3 != s->hit2)) { 00885 s->mhit = hit; 00886 s->detected_digits++; 00887 if (s->current_digits < MAX_DTMF_DIGITS - 2) { 00888 s->digits[s->current_digits++] = hit; 00889 s->digits[s->current_digits] = '\0'; 00890 } else { 00891 s->lost_digits++; 00892 } 00893 } 00894 } 00895 00896 s->hit1 = s->hit2; 00897 s->hit2 = s->hit3; 00898 s->hit3 = hit; 00899 /* Reinitialise the detector for the next block */ 00900 for (i = 0; i < 6; i++) { 00901 goertzel_reset(&s->tone_out[i]); 00902 goertzel_reset(&s->tone_out2nd[i]); 00903 } 00904 s->energy = 0.0; 00905 s->current_sample = 0; 00906 } 00907 #else 00908 /* We're at the end of an MF detection block. */ 00909 /* Find the two highest energies. The spec says to look for 00910 two tones and two tones only. Taking this literally -ie 00911 only two tones pass the minimum threshold - doesn't work 00912 well. The sinc function mess, due to rectangular windowing 00913 ensure that! Find the two highest energies and ensure they 00914 are considerably stronger than any of the others. */ 00915 energy[0] = goertzel_result(&s->tone_out[0]); 00916 energy[1] = goertzel_result(&s->tone_out[1]); 00917 if (energy[0] > energy[1]) { 00918 best = 0; 00919 second_best = 1; 00920 } else { 00921 best = 1; 00922 second_best = 0; 00923 } 00924 /*endif*/ 00925 for (i=2;i<6;i++) { 00926 energy[i] = goertzel_result(&s->tone_out[i]); 00927 if (energy[i] >= energy[best]) { 00928 second_best = best; 00929 best = i; 00930 } else if (energy[i] >= energy[second_best]) { 00931 second_best = i; 00932 } 00933 } 00934 /* Basic signal level and twist tests */ 00935 hit = 0; 00936 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00937 && energy[best] < energy[second_best]*BELL_MF_TWIST 00938 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00939 /* Relative peak test */ 00940 hit = -1; 00941 for (i=0;i<6;i++) { 00942 if (i != best && i != second_best) { 00943 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00944 /* The best two are not clearly the best */ 00945 hit = 0; 00946 break; 00947 } 00948 } 00949 } 00950 } 00951 if (hit) { 00952 /* Get the values into ascending order */ 00953 if (second_best < best) { 00954 i = best; 00955 best = second_best; 00956 second_best = i; 00957 } 00958 best = best*5 + second_best - 1; 00959 hit = bell_mf_positions[best]; 00960 /* Look for two successive similar results */ 00961 /* The logic in the next test is: 00962 For KP we need 4 successive identical clean detects, with 00963 two blocks of something different preceeding it. For anything 00964 else we need two successive identical clean detects, with 00965 two blocks of something different preceeding it. */ 00966 if (hit == s->hits[4] && hit == s->hits[3] && 00967 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])|| 00968 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 00969 hit != s->hits[0]))) { 00970 s->detected_digits++; 00971 if (s->current_digits < MAX_DTMF_DIGITS) { 00972 s->digits[s->current_digits++] = hit; 00973 s->digits[s->current_digits] = '\0'; 00974 } else { 00975 s->lost_digits++; 00976 } 00977 } 00978 } else { 00979 hit = 0; 00980 } 00981 s->hits[0] = s->hits[1]; 00982 s->hits[1] = s->hits[2]; 00983 s->hits[2] = s->hits[3]; 00984 s->hits[3] = s->hits[4]; 00985 s->hits[4] = hit; 00986 /* Reinitialise the detector for the next block */ 00987 for (i = 0; i < 6; i++) 00988 goertzel_reset(&s->tone_out[i]); 00989 s->current_sample = 0; 00990 } 00991 #endif 00992 if ((!s->mhit) || (s->mhit != hit)) { 00993 s->mhit = 0; 00994 return(0); 00995 } 00996 return (hit); 00997 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 1029 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
01030 { 01031 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 01032 /* Make sure absolute levels are high enough */ 01033 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 01034 return 0; 01035 /* Amplify ignored stuff */ 01036 i2 *= TONE_THRESH; 01037 i1 *= TONE_THRESH; 01038 e *= TONE_THRESH; 01039 /* Check first tone */ 01040 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 01041 return 0; 01042 /* And second */ 01043 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 01044 return 0; 01045 /* Guess it's there... */ 01046 return 1; 01047 }
Referenced by ast_dsp_set_call_progress_zone(), and find_alias().
char bell_mf_positions[] = "1247C-358A--69*---0B----#" [static] |
float dtmf_col[] [static] |
char dtmf_positions[] = "123A" "456B" "789C" "*0#D" [static] |
float dtmf_row[] [static] |
float mf_tones[] [static] |
Referenced by ast_dsp_prog_reset(), and setrem().