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