#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_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 1789 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().
01790 { 01791 int new; 01792 int old; 01793 01794 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01795 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01796 if (old != new) { 01797 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01798 if (new & DSP_DIGITMODE_MF) 01799 ast_mf_detect_init(&dsp->td.mf); 01800 else 01801 ast_dtmf_detect_init(&dsp->td.dtmf); 01802 } 01803 dsp->digitmode = digitmode; 01804 return 0; 01805 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1726 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().
01727 { 01728 int i; 01729 01730 dsp->thinkdigit = 0; 01731 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01732 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01733 dsp->td.mf.current_digits = 0; 01734 /* Reinitialise the detector for the next block */ 01735 for (i = 0; i < 6; i++) { 01736 goertzel_reset(&dsp->td.mf.tone_out[i]); 01737 #ifdef OLD_DSP_ROUTINES 01738 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01739 #endif 01740 } 01741 #ifdef OLD_DSP_ROUTINES 01742 dsp->td.mf.energy = 0.0; 01743 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01744 #else 01745 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; 01746 #endif 01747 dsp->td.mf.current_sample = 0; 01748 } else { 01749 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01750 dsp->td.dtmf.current_digits = 0; 01751 /* Reinitialise the detector for the next block */ 01752 for (i = 0; i < 4; i++) { 01753 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01754 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01755 #ifdef OLD_DSP_ROUTINES 01756 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01757 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01758 #endif 01759 } 01760 #ifdef FAX_DETECT 01761 goertzel_reset (&dsp->td.dtmf.fax_tone); 01762 #endif 01763 #ifdef OLD_DSP_ROUTINES 01764 #ifdef FAX_DETECT 01765 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01766 #endif 01767 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01768 #else 01769 dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0; 01770 #endif 01771 dsp->td.dtmf.energy = 0.0; 01772 dsp->td.dtmf.current_sample = 0; 01773 } 01774 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1684 of file dsp.c.
References free.
Referenced by __ast_play_and_record(), __oh323_destroy(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), dahdi_hangup(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), and ss_thread().
01685 { 01686 free(dsp); 01687 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1826 of file dsp.c.
References ast_dsp::tcount.
01827 { 01828 return dsp->tcount; 01829 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1821 of file dsp.c.
References ast_dsp::tstate.
01822 { 01823 return dsp->tstate; 01824 }
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 1649 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().
01650 { 01651 struct ast_dsp *dsp; 01652 01653 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01654 dsp->threshold = DEFAULT_THRESHOLD; 01655 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01656 dsp->busycount = DSP_HISTORY; 01657 dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT; 01658 #ifdef BUSYDETECT_TONEONLY 01659 dsp->busytoneonly = 1; 01660 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01661 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE"); 01662 #endif 01663 #else 01664 dsp->busytoneonly = 0; 01665 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01666 dsp->busycompare = 1; 01667 #else 01668 dsp->busycompare = 0; 01669 #endif 01670 #endif 01671 /* Initialize DTMF detector */ 01672 ast_dtmf_detect_init(&dsp->td.dtmf); 01673 /* Initialize initial DSP progress detect parameters */ 01674 ast_dsp_prog_reset(dsp); 01675 } 01676 return dsp; 01677 }
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_frfree, ast_frisolate(), 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_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 return ast_frisolate(&dsp->f); 01502 } 01503 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01504 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01505 memset(&dsp->f, 0, sizeof(dsp->f)); 01506 dsp->f.frametype = AST_FRAME_CONTROL; 01507 dsp->f.subclass = AST_CONTROL_BUSY; 01508 ast_frfree(af); 01509 return ast_frisolate(&dsp->f); 01510 } 01511 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01512 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01513 #if 0 01514 if (digit) 01515 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01516 #endif 01517 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01518 if (!dsp->thinkdigit) { 01519 if (digit) { 01520 /* Looks like we might have something. 01521 * Request a conference mute for the moment */ 01522 memset(&dsp->f, 0, sizeof(dsp->f)); 01523 dsp->f.frametype = AST_FRAME_DTMF; 01524 dsp->f.subclass = 'm'; 01525 dsp->thinkdigit = 'x'; 01526 FIX_INF(af); 01527 if (chan) 01528 ast_queue_frame(chan, af); 01529 ast_frfree(af); 01530 return ast_frisolate(&dsp->f); 01531 } 01532 } else { 01533 if (digit) { 01534 /* Thought we saw one last time. Pretty sure we really have now */ 01535 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01536 /* If we found a digit, and we're changing digits, go 01537 ahead and send this one, but DON'T stop confmute because 01538 we're detecting something else, too... */ 01539 memset(&dsp->f, 0, sizeof(dsp->f)); 01540 dsp->f.frametype = AST_FRAME_DTMF_END; 01541 dsp->f.subclass = dsp->thinkdigit; 01542 FIX_INF(af); 01543 if (chan) 01544 ast_queue_frame(chan, af); 01545 ast_frfree(af); 01546 } else { 01547 dsp->thinkdigit = digit; 01548 memset(&dsp->f, 0, sizeof(dsp->f)); 01549 dsp->f.frametype = AST_FRAME_DTMF_BEGIN; 01550 dsp->f.subclass = dsp->thinkdigit; 01551 FIX_INF(af); 01552 if (chan) 01553 ast_queue_frame(chan, af); 01554 ast_frfree(af); 01555 } 01556 return ast_frisolate(&dsp->f); 01557 } else { 01558 memset(&dsp->f, 0, sizeof(dsp->f)); 01559 if (dsp->thinkdigit != 'x') { 01560 /* If we found a digit, send it now */ 01561 dsp->f.frametype = AST_FRAME_DTMF_END; 01562 dsp->f.subclass = dsp->thinkdigit; 01563 dsp->thinkdigit = 0; 01564 } else { 01565 dsp->f.frametype = AST_FRAME_DTMF; 01566 dsp->f.subclass = 'u'; 01567 dsp->thinkdigit = 0; 01568 } 01569 FIX_INF(af); 01570 if (chan) 01571 ast_queue_frame(chan, af); 01572 ast_frfree(af); 01573 return ast_frisolate(&dsp->f); 01574 } 01575 } 01576 } else if (!digit) { 01577 /* Only check when there is *not* a hit... */ 01578 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01579 if (dsp->td.mf.current_digits) { 01580 memset(&dsp->f, 0, sizeof(dsp->f)); 01581 dsp->f.frametype = AST_FRAME_DTMF; 01582 dsp->f.subclass = dsp->td.mf.digits[0]; 01583 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01584 dsp->td.mf.current_digits--; 01585 FIX_INF(af); 01586 if (chan) 01587 ast_queue_frame(chan, af); 01588 ast_frfree(af); 01589 return ast_frisolate(&dsp->f); 01590 } 01591 } else { 01592 if (dsp->td.dtmf.current_digits) { 01593 memset(&dsp->f, 0, sizeof(dsp->f)); 01594 dsp->f.frametype = AST_FRAME_DTMF_END; 01595 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01596 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01597 dsp->td.dtmf.current_digits--; 01598 FIX_INF(af); 01599 if (chan) 01600 ast_queue_frame(chan, af); 01601 ast_frfree(af); 01602 return ast_frisolate(&dsp->f); 01603 } 01604 } 01605 } 01606 } 01607 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01608 res = __ast_dsp_call_progress(dsp, shortdata, len); 01609 if (res) { 01610 switch(res) { 01611 case AST_CONTROL_ANSWER: 01612 case AST_CONTROL_BUSY: 01613 case AST_CONTROL_RINGING: 01614 case AST_CONTROL_CONGESTION: 01615 case AST_CONTROL_HANGUP: 01616 memset(&dsp->f, 0, sizeof(dsp->f)); 01617 dsp->f.frametype = AST_FRAME_CONTROL; 01618 dsp->f.subclass = res; 01619 dsp->f.src = "dsp_progress"; 01620 if (chan) 01621 ast_queue_frame(chan, &dsp->f); 01622 break; 01623 default: 01624 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01625 } 01626 } 01627 } 01628 FIX_INF(af); 01629 return af; 01630 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1632 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().
01633 { 01634 int max = 0; 01635 int x; 01636 01637 dsp->gsamp_size = modes[dsp->progmode].size; 01638 dsp->gsamps = 0; 01639 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { 01640 if (modes[dsp->progmode].freqs[x]) { 01641 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01642 max = x + 1; 01643 } 01644 } 01645 dsp->freqcount = max; 01646 dsp->ringtimeout= 0; 01647 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1776 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.
01777 { 01778 int x; 01779 01780 dsp->totalsilence = 0; 01781 dsp->gsamps = 0; 01782 for (x=0;x<4;x++) 01783 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01784 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01785 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01786 dsp->ringtimeout= 0; 01787 }
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 1706 of file dsp.c.
References ast_dsp::busycompare.
Referenced by dahdi_new().
01707 { 01708 if (compare > 0) 01709 dsp->busycompare = 1; 01710 else 01711 dsp->busycompare = 0; 01712 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1697 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by dahdi_new().
01698 { 01699 if (cadences < 4) 01700 cadences = 4; 01701 if (cadences > DSP_HISTORY) 01702 cadences = DSP_HISTORY; 01703 dsp->busycount = cadences; 01704 }
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 1714 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().
01715 { 01716 dsp->busy_tonelength = tonelength; 01717 if (quietlength > 0) 01718 dsp->busy_quietlength = quietlength; 01719 else 01720 dsp->busytoneonly = 1; 01721 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01722 if( fuzzy > 0 && fuzzy < 50 ) 01723 dsp->busy_pattern_fuzzy = fuzzy; 01724 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1807 of file dsp.c.
References aliases, ast_dsp_prog_reset(), name, and ast_dsp::progmode.
Referenced by dahdi_new().
01808 { 01809 int x; 01810 01811 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) { 01812 if (!strcasecmp(aliases[x].name, zone)) { 01813 dsp->progmode = aliases[x].mode; 01814 ast_dsp_prog_reset(dsp); 01815 return 0; 01816 } 01817 } 01818 return -1; 01819 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1679 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 1689 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), dahdi_new(), do_waiting(), handle_recordfile(), and isAnsweringMachine().
01690 { 01691 if (threshold < 256) 01692 dsp->threshold = 256; 01693 else 01694 dsp->threshold = threshold; 01695 }
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().