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