#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 dependency graph for dsp.c:
Go to the source code of this file.
Data Structures | |
struct | ast_dsp |
struct | dtmf_detect_state_t |
struct | goertzel_state_t |
struct | mf_detect_state_t |
struct | progalias |
struct | progress |
Defines | |
#define | BELL_MF_RELATIVE_PEAK 12.6 |
#define | BELL_MF_THRESHOLD 1.6e9 |
#define | BELL_MF_TWIST 4.0 |
#define | 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_free (struct ast_dsp *dsp) |
int | ast_dsp_get_tcount (struct ast_dsp *dsp) |
Get tcount (Threshold counter). | |
int | ast_dsp_get_tstate (struct ast_dsp *dsp) |
Get tstate (Tone State). | |
int | ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max) |
Get pending DTMF/MF digits. | |
ast_dsp * | ast_dsp_new (void) |
ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af) |
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled. | |
static void | ast_dsp_prog_reset (struct ast_dsp *dsp) |
void | ast_dsp_reset (struct ast_dsp *dsp) |
Reset total silence count. | |
void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences) |
Set number of required cadences for busy. | |
void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength) |
Set expected lengths of the busy tone. | |
int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
Set zone for doing progress detection. | |
void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
Select feature set. | |
void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold) |
Set threshold value for silence. | |
int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence. | |
static void | ast_dtmf_detect_init (dtmf_detect_state_t *s) |
static void | ast_mf_detect_init (mf_detect_state_t *s) |
static int | dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect) |
static void | goertzel_init (goertzel_state_t *s, float freq, int samples) |
static void | goertzel_reset (goertzel_state_t *s) |
static float | goertzel_result (goertzel_state_t *s) |
static void | goertzel_sample (goertzel_state_t *s, short sample) |
static void | goertzel_update (goertzel_state_t *s, short *samps, int count) |
static int | mf_detect (mf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback) |
static int | pair_there (float p1, float p2, float i1, float i2, float e) |
Variables | |
static struct progalias | aliases [] |
static char | bell_mf_positions [] = "1247C-358A--69*---0B----#" |
static float | dtmf_col [] |
static char | dtmf_positions [] = "123A" "456B" "789C" "*0#D" |
static float | dtmf_row [] |
static float | fax_freq = 1100.0 |
static float | mf_tones [] |
static struct progress | modes [] |
Definition in file dsp.c.
#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 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 |
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 1056 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().
01057 { 01058 int x; 01059 int y; 01060 int pass; 01061 int newstate = DSP_TONE_STATE_SILENCE; 01062 int res = 0; 01063 while(len) { 01064 /* Take the lesser of the number of samples we need and what we have */ 01065 pass = len; 01066 if (pass > dsp->gsamp_size - dsp->gsamps) 01067 pass = dsp->gsamp_size - dsp->gsamps; 01068 for (x=0;x<pass;x++) { 01069 for (y=0;y<dsp->freqcount;y++) 01070 goertzel_sample(&dsp->freqs[y], s[x]); 01071 dsp->genergy += s[x] * s[x]; 01072 } 01073 s += pass; 01074 dsp->gsamps += pass; 01075 len -= pass; 01076 if (dsp->gsamps == dsp->gsamp_size) { 01077 float hz[7]; 01078 for (y=0;y<7;y++) 01079 hz[y] = goertzel_result(&dsp->freqs[y]); 01080 #if 0 01081 printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n"); 01082 printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 01083 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); 01084 #endif 01085 switch(dsp->progmode) { 01086 case PROG_MODE_NA: 01087 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01088 newstate = DSP_TONE_STATE_BUSY; 01089 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01090 newstate = DSP_TONE_STATE_RINGING; 01091 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01092 newstate = DSP_TONE_STATE_DIALTONE; 01093 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01094 newstate = DSP_TONE_STATE_SPECIAL1; 01095 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01096 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 01097 newstate = DSP_TONE_STATE_SPECIAL2; 01098 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01099 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 01100 newstate = DSP_TONE_STATE_SPECIAL3; 01101 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01102 newstate = DSP_TONE_STATE_TALKING; 01103 } else 01104 newstate = DSP_TONE_STATE_SILENCE; 01105 break; 01106 case PROG_MODE_CR: 01107 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01108 newstate = DSP_TONE_STATE_RINGING; 01109 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01110 newstate = DSP_TONE_STATE_TALKING; 01111 } else 01112 newstate = DSP_TONE_STATE_SILENCE; 01113 break; 01114 case PROG_MODE_UK: 01115 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 01116 newstate = DSP_TONE_STATE_HUNGUP; 01117 } 01118 break; 01119 default: 01120 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01121 } 01122 if (newstate == dsp->tstate) { 01123 dsp->tcount++; 01124 if (dsp->ringtimeout) 01125 dsp->ringtimeout++; 01126 switch (dsp->tstate) { 01127 case DSP_TONE_STATE_RINGING: 01128 if ((dsp->features & DSP_PROGRESS_RINGING) && 01129 (dsp->tcount==THRESH_RING)) { 01130 res = AST_CONTROL_RINGING; 01131 dsp->ringtimeout= 1; 01132 } 01133 break; 01134 case DSP_TONE_STATE_BUSY: 01135 if ((dsp->features & DSP_PROGRESS_BUSY) && 01136 (dsp->tcount==THRESH_BUSY)) { 01137 res = AST_CONTROL_BUSY; 01138 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01139 } 01140 break; 01141 case DSP_TONE_STATE_TALKING: 01142 if ((dsp->features & DSP_PROGRESS_TALK) && 01143 (dsp->tcount==THRESH_TALK)) { 01144 res = AST_CONTROL_ANSWER; 01145 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01146 } 01147 break; 01148 case DSP_TONE_STATE_SPECIAL3: 01149 if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01150 (dsp->tcount==THRESH_CONGESTION)) { 01151 res = AST_CONTROL_CONGESTION; 01152 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01153 } 01154 break; 01155 case DSP_TONE_STATE_HUNGUP: 01156 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01157 (dsp->tcount==THRESH_HANGUP)) { 01158 res = AST_CONTROL_HANGUP; 01159 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01160 } 01161 break; 01162 } 01163 if (dsp->ringtimeout==THRESH_RING2ANSWER) { 01164 #if 0 01165 ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n"); 01166 #endif 01167 res = AST_CONTROL_ANSWER; 01168 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01169 } 01170 } else { 01171 #if 0 01172 ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount); 01173 ast_log(LOG_NOTICE, "Start state %d\n", newstate); 01174 #endif 01175 dsp->tstate = newstate; 01176 dsp->tcount = 1; 01177 } 01178 01179 /* Reset goertzel */ 01180 for (x=0;x<7;x++) 01181 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01182 dsp->gsamps = 0; 01183 dsp->genergy = 0.0; 01184 } 01185 } 01186 #if 0 01187 if (res) 01188 printf("Returning %d\n", res); 01189 #endif 01190 return res; 01191 }
static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | writeback | |||
) | [static] |
Definition at line 981 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().
00982 { 00983 int res; 00984 00985 if (dsp->digitmode & DSP_DIGITMODE_MF) 00986 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00987 else 00988 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT); 00989 return res; 00990 }
static int __ast_dsp_silence | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence | |||
) | [static] |
Definition at line 1206 of file dsp.c.
References 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().
01207 { 01208 int accum; 01209 int x; 01210 int res = 0; 01211 01212 if (!len) 01213 return 0; 01214 accum = 0; 01215 for (x=0;x<len; x++) 01216 accum += abs(s[x]); 01217 accum /= len; 01218 if (accum < dsp->threshold) { 01219 /* Silent */ 01220 dsp->totalsilence += len/8; 01221 if (dsp->totalnoise) { 01222 /* Move and save history */ 01223 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); 01224 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01225 /* we don't want to check for busydetect that frequently */ 01226 #if 0 01227 dsp->busymaybe = 1; 01228 #endif 01229 } 01230 dsp->totalnoise = 0; 01231 res = 1; 01232 } else { 01233 /* Not silent */ 01234 dsp->totalnoise += len/8; 01235 if (dsp->totalsilence) { 01236 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01237 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01238 /* Move and save history */ 01239 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0])); 01240 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01241 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01242 if (silence1 < silence2) { 01243 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) 01244 dsp->busymaybe = 1; 01245 else 01246 dsp->busymaybe = 0; 01247 } else { 01248 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) 01249 dsp->busymaybe = 1; 01250 else 01251 dsp->busymaybe = 0; 01252 } 01253 } 01254 dsp->totalsilence = 0; 01255 } 01256 if (totalsilence) 01257 *totalsilence = dsp->totalsilence; 01258 return res; 01259 }
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 1262 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().
01263 { 01264 int res = 0, x; 01265 #ifndef BUSYDETECT_TONEONLY 01266 int avgsilence = 0, hitsilence = 0; 01267 #endif 01268 int avgtone = 0, hittone = 0; 01269 if (!dsp->busymaybe) 01270 return res; 01271 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01272 #ifndef BUSYDETECT_TONEONLY 01273 avgsilence += dsp->historicsilence[x]; 01274 #endif 01275 avgtone += dsp->historicnoise[x]; 01276 } 01277 #ifndef BUSYDETECT_TONEONLY 01278 avgsilence /= dsp->busycount; 01279 #endif 01280 avgtone /= dsp->busycount; 01281 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01282 #ifndef BUSYDETECT_TONEONLY 01283 if (avgsilence > dsp->historicsilence[x]) { 01284 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01285 hitsilence++; 01286 } else { 01287 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01288 hitsilence++; 01289 } 01290 #endif 01291 if (avgtone > dsp->historicnoise[x]) { 01292 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01293 hittone++; 01294 } else { 01295 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01296 hittone++; 01297 } 01298 } 01299 #ifndef BUSYDETECT_TONEONLY 01300 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01301 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01302 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01303 #else 01304 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01305 #endif 01306 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01307 #ifdef BUSYDETECT_TONEONLY 01308 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE 01309 #endif 01310 if (avgtone > avgsilence) { 01311 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01312 res = 1; 01313 } else { 01314 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01315 res = 1; 01316 } 01317 #else 01318 res = 1; 01319 #endif 01320 } 01321 /* If we know the expected busy tone length, check we are in the range */ 01322 if (res && (dsp->busy_tonelength > 0)) { 01323 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01324 #if 0 01325 ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n", 01326 avgtone, dsp->busy_tonelength); 01327 #endif 01328 res = 0; 01329 } 01330 } 01331 #ifndef BUSYDETECT_TONEONLY 01332 /* If we know the expected busy tone silent-period length, check we are in the range */ 01333 if (res && (dsp->busy_quietlength > 0)) { 01334 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01335 #if 0 01336 ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n", 01337 avgsilence, dsp->busy_quietlength); 01338 #endif 01339 res = 0; 01340 } 01341 } 01342 #endif 01343 #ifndef BUSYDETECT_TONEONLY 01344 #if 1 01345 if (res) 01346 ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01347 #endif 01348 #endif 01349 return res; 01350 }
Scans for progress indication in audio.
Definition at line 1193 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.
01194 { 01195 if (inf->frametype != AST_FRAME_VOICE) { 01196 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01197 return 0; 01198 } 01199 if (inf->subclass != AST_FORMAT_SLINEAR) { 01200 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01201 return 0; 01202 } 01203 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01204 }
Return non-zero if DTMF hit was found.
Definition at line 992 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.
00993 { 00994 short *s; 00995 int len; 00996 int ign=0; 00997 00998 if (inf->frametype != AST_FRAME_VOICE) { 00999 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01000 return 0; 01001 } 01002 if (inf->subclass != AST_FORMAT_SLINEAR) { 01003 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01004 return 0; 01005 } 01006 s = inf->data; 01007 len = inf->datalen / 2; 01008 return __ast_dsp_digitdetect(dsp, s, len, &ign); 01009 }
int ast_dsp_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1732 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(), nv_background_detect_exec(), nv_detectfax_exec(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().
01733 { 01734 int new; 01735 int old; 01736 01737 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01738 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01739 if (old != new) { 01740 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01741 if (new & DSP_DIGITMODE_MF) 01742 ast_mf_detect_init(&dsp->td.mf); 01743 else 01744 ast_dtmf_detect_init(&dsp->td.dtmf); 01745 } 01746 dsp->digitmode = digitmode; 01747 return 0; 01748 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1669 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::hits, 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().
01670 { 01671 int i; 01672 01673 dsp->thinkdigit = 0; 01674 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01675 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01676 dsp->td.mf.current_digits = 0; 01677 /* Reinitialise the detector for the next block */ 01678 for (i = 0; i < 6; i++) { 01679 goertzel_reset(&dsp->td.mf.tone_out[i]); 01680 #ifdef OLD_DSP_ROUTINES 01681 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01682 #endif 01683 } 01684 #ifdef OLD_DSP_ROUTINES 01685 dsp->td.mf.energy = 0.0; 01686 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01687 #else 01688 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; 01689 #endif 01690 dsp->td.mf.current_sample = 0; 01691 } else { 01692 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01693 dsp->td.dtmf.current_digits = 0; 01694 /* Reinitialise the detector for the next block */ 01695 for (i = 0; i < 4; i++) { 01696 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01697 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01698 #ifdef OLD_DSP_ROUTINES 01699 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01700 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01701 #endif 01702 } 01703 #ifdef FAX_DETECT 01704 goertzel_reset (&dsp->td.dtmf.fax_tone); 01705 #endif 01706 #ifdef OLD_DSP_ROUTINES 01707 #ifdef FAX_DETECT 01708 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01709 #endif 01710 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01711 #else 01712 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0; 01713 #endif 01714 dsp->td.dtmf.energy = 0.0; 01715 dsp->td.dtmf.current_sample = 0; 01716 } 01717 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1643 of file dsp.c.
References free.
Referenced by __ast_play_and_record(), __oh323_destroy(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), nv_background_detect_exec(), nv_detectfax_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), and zt_hangup().
01644 { 01645 free(dsp); 01646 }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter).
Definition at line 1769 of file dsp.c.
References ast_dsp::tcount.
01770 { 01771 return dsp->tcount; 01772 }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State).
Definition at line 1764 of file dsp.c.
References ast_dsp::tstate.
01765 { 01766 return dsp->tstate; 01767 }
int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, | |
char * | buf, | |||
int | max | |||
) |
Get pending DTMF/MF digits.
Definition at line 1031 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.
01032 { 01033 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01034 if (max > dsp->td.mf.current_digits) 01035 max = dsp->td.mf.current_digits; 01036 if (max > 0) { 01037 memcpy(buf, dsp->td.mf.digits, max); 01038 memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 01039 dsp->td.mf.current_digits -= max; 01040 } 01041 buf[max] = '\0'; 01042 return max; 01043 } else { 01044 if (max > dsp->td.dtmf.current_digits) 01045 max = dsp->td.dtmf.current_digits; 01046 if (max > 0) { 01047 memcpy (buf, dsp->td.dtmf.digits, max); 01048 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01049 dsp->td.dtmf.current_digits -= max; 01050 } 01051 buf[max] = '\0'; 01052 return max; 01053 } 01054 }
struct ast_dsp* ast_dsp_new | ( | void | ) |
Definition at line 1622 of file dsp.c.
References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), 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(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), nv_background_detect_exec(), nv_detectfax_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().
01623 { 01624 struct ast_dsp *dsp; 01625 01626 if ((dsp = ast_calloc(1, sizeof(*dsp)))) { 01627 dsp->threshold = DEFAULT_THRESHOLD; 01628 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01629 dsp->busycount = DSP_HISTORY; 01630 /* Initialize DTMF detector */ 01631 ast_dtmf_detect_init(&dsp->td.dtmf); 01632 /* Initialize initial DSP progress detect parameters */ 01633 ast_dsp_prog_reset(dsp); 01634 } 01635 return dsp; 01636 }
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 1416 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_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, mf_detect_state_t::digits, dtmf_detect_state_t::digits, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.
Referenced by mgcp_rtp_read(), nv_background_detect_exec(), nv_detectfax_exec(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), and zt_read().
01417 { 01418 int silence; 01419 int res; 01420 int digit; 01421 int x; 01422 short *shortdata; 01423 unsigned char *odata; 01424 int len; 01425 int writeback = 0; 01426 01427 #define FIX_INF(inf) do { \ 01428 if (writeback) { \ 01429 switch(inf->subclass) { \ 01430 case AST_FORMAT_SLINEAR: \ 01431 break; \ 01432 case AST_FORMAT_ULAW: \ 01433 for (x=0;x<len;x++) \ 01434 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01435 break; \ 01436 case AST_FORMAT_ALAW: \ 01437 for (x=0;x<len;x++) \ 01438 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01439 break; \ 01440 } \ 01441 } \ 01442 } while(0) 01443 01444 if (!af) 01445 return NULL; 01446 if (af->frametype != AST_FRAME_VOICE) 01447 return af; 01448 odata = af->data; 01449 len = af->datalen; 01450 /* Make sure we have short data */ 01451 switch(af->subclass) { 01452 case AST_FORMAT_SLINEAR: 01453 shortdata = af->data; 01454 len = af->datalen / 2; 01455 break; 01456 case AST_FORMAT_ULAW: 01457 shortdata = alloca(af->datalen * 2); 01458 for (x = 0;x < len; x++) 01459 shortdata[x] = AST_MULAW(odata[x]); 01460 break; 01461 case AST_FORMAT_ALAW: 01462 shortdata = alloca(af->datalen * 2); 01463 for (x = 0; x < len; x++) 01464 shortdata[x] = AST_ALAW(odata[x]); 01465 break; 01466 default: 01467 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01468 return af; 01469 } 01470 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01471 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01472 memset(&dsp->f, 0, sizeof(dsp->f)); 01473 dsp->f.frametype = AST_FRAME_NULL; 01474 return &dsp->f; 01475 } 01476 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01477 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01478 memset(&dsp->f, 0, sizeof(dsp->f)); 01479 dsp->f.frametype = AST_FRAME_CONTROL; 01480 dsp->f.subclass = AST_CONTROL_BUSY; 01481 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01482 return &dsp->f; 01483 } 01484 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01485 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01486 #if 0 01487 if (digit) 01488 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01489 #endif 01490 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01491 if (!dsp->thinkdigit) { 01492 if (digit) { 01493 /* Looks like we might have something. 01494 * Request a conference mute for the moment */ 01495 memset(&dsp->f, 0, sizeof(dsp->f)); 01496 dsp->f.frametype = AST_FRAME_DTMF; 01497 dsp->f.subclass = 'm'; 01498 dsp->thinkdigit = 'x'; 01499 FIX_INF(af); 01500 if (chan) 01501 ast_queue_frame(chan, af); 01502 ast_frfree(af); 01503 return &dsp->f; 01504 } 01505 } else { 01506 if (digit) { 01507 /* Thought we saw one last time. Pretty sure we really have now */ 01508 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01509 /* If we found a digit, and we're changing digits, go 01510 ahead and send this one, but DON'T stop confmute because 01511 we're detecting something else, too... */ 01512 memset(&dsp->f, 0, sizeof(dsp->f)); 01513 dsp->f.frametype = AST_FRAME_DTMF_END; 01514 dsp->f.subclass = dsp->thinkdigit; 01515 FIX_INF(af); 01516 if (chan) 01517 ast_queue_frame(chan, af); 01518 ast_frfree(af); 01519 } else { 01520 dsp->thinkdigit = digit; 01521 memset(&dsp->f, 0, sizeof(dsp->f)); 01522 dsp->f.frametype = AST_FRAME_DTMF_BEGIN; 01523 dsp->f.subclass = dsp->thinkdigit; 01524 FIX_INF(af); 01525 if (chan) 01526 ast_queue_frame(chan, af); 01527 ast_frfree(af); 01528 } 01529 return &dsp->f; 01530 } else { 01531 memset(&dsp->f, 0, sizeof(dsp->f)); 01532 if (dsp->thinkdigit != 'x') { 01533 /* If we found a digit, send it now */ 01534 dsp->f.frametype = AST_FRAME_DTMF_END; 01535 dsp->f.subclass = dsp->thinkdigit; 01536 dsp->thinkdigit = 0; 01537 } else { 01538 dsp->f.frametype = AST_FRAME_DTMF; 01539 dsp->f.subclass = 'u'; 01540 dsp->thinkdigit = 0; 01541 } 01542 FIX_INF(af); 01543 if (chan) 01544 ast_queue_frame(chan, af); 01545 ast_frfree(af); 01546 return &dsp->f; 01547 } 01548 } 01549 } else if (!digit) { 01550 /* Only check when there is *not* a hit... */ 01551 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01552 if (dsp->td.mf.current_digits) { 01553 memset(&dsp->f, 0, sizeof(dsp->f)); 01554 dsp->f.frametype = AST_FRAME_DTMF; 01555 dsp->f.subclass = dsp->td.mf.digits[0]; 01556 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01557 dsp->td.mf.current_digits--; 01558 FIX_INF(af); 01559 if (chan) 01560 ast_queue_frame(chan, af); 01561 ast_frfree(af); 01562 return &dsp->f; 01563 } 01564 } else { 01565 if (dsp->td.dtmf.current_digits) { 01566 memset(&dsp->f, 0, sizeof(dsp->f)); 01567 dsp->f.frametype = AST_FRAME_DTMF_END; 01568 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01569 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01570 dsp->td.dtmf.current_digits--; 01571 FIX_INF(af); 01572 if (chan) 01573 ast_queue_frame(chan, af); 01574 ast_frfree(af); 01575 return &dsp->f; 01576 } 01577 } 01578 } 01579 } 01580 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01581 res = __ast_dsp_call_progress(dsp, shortdata, len); 01582 if (res) { 01583 switch(res) { 01584 case AST_CONTROL_ANSWER: 01585 case AST_CONTROL_BUSY: 01586 case AST_CONTROL_RINGING: 01587 case AST_CONTROL_CONGESTION: 01588 case AST_CONTROL_HANGUP: 01589 memset(&dsp->f, 0, sizeof(dsp->f)); 01590 dsp->f.frametype = AST_FRAME_CONTROL; 01591 dsp->f.subclass = res; 01592 dsp->f.src = "dsp_progress"; 01593 if (chan) 01594 ast_queue_frame(chan, &dsp->f); 01595 break; 01596 default: 01597 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01598 } 01599 } 01600 } 01601 FIX_INF(af); 01602 return af; 01603 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1605 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().
01606 { 01607 int max = 0; 01608 int x; 01609 01610 dsp->gsamp_size = modes[dsp->progmode].size; 01611 dsp->gsamps = 0; 01612 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { 01613 if (modes[dsp->progmode].freqs[x]) { 01614 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01615 max = x + 1; 01616 } 01617 } 01618 dsp->freqcount = max; 01619 dsp->ringtimeout= 0; 01620 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1719 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.
01720 { 01721 int x; 01722 01723 dsp->totalsilence = 0; 01724 dsp->gsamps = 0; 01725 for (x=0;x<4;x++) 01726 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01727 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01728 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01729 dsp->ringtimeout= 0; 01730 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1653 of file dsp.c.
References ast_dsp::busycount, and DSP_HISTORY.
Referenced by zt_new().
01654 { 01655 if (cadences < 4) 01656 cadences = 4; 01657 if (cadences > DSP_HISTORY) 01658 cadences = DSP_HISTORY; 01659 dsp->busycount = cadences; 01660 }
void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
int | tonelength, | |||
int | quietlength | |||
) |
Set expected lengths of the busy tone.
Definition at line 1662 of file dsp.c.
References ast_log(), ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and LOG_DEBUG.
Referenced by zt_new().
01663 { 01664 dsp->busy_tonelength = tonelength; 01665 dsp->busy_quietlength = quietlength; 01666 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01667 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1750 of file dsp.c.
References aliases, ast_dsp_prog_reset(), name, and ast_dsp::progmode.
Referenced by zt_new().
01751 { 01752 int x; 01753 01754 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) { 01755 if (!strcasecmp(aliases[x].name, zone)) { 01756 dsp->progmode = aliases[x].mode; 01757 ast_dsp_prog_reset(dsp); 01758 return 0; 01759 } 01760 } 01761 return -1; 01762 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1638 of file dsp.c.
References ast_dsp::features.
Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), nv_background_detect_exec(), nv_detectfax_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 1648 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), do_waiting(), handle_recordfile(), isAnsweringMachine(), nv_background_detect_exec(), and nv_detectfax_exec().
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1398 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(), isAnsweringMachine(), nv_background_detect_exec(), and nv_detectfax_exec().
01399 { 01400 short *s; 01401 int len; 01402 01403 if (f->frametype != AST_FRAME_VOICE) { 01404 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01405 return 0; 01406 } 01407 if (f->subclass != AST_FORMAT_SLINEAR) { 01408 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01409 return 0; 01410 } 01411 s = f->data; 01412 len = f->datalen/2; 01413 return __ast_dsp_silence(dsp, s, len, totalsilence); 01414 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 363 of file dsp.c.
References goertzel_init(), and s.
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->hits[0] = s->hits[1] = s->hits[2] = 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 goertzel_init(), and s.
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 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, s, and warning().
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 /* Look for two successive similar results */ 00599 /* The logic in the next test is: 00600 We need two successive identical clean detects, with 00601 something different preceeding it. This can work with 00602 back to back differing digits. More importantly, it 00603 can work with nasty phones that give a very wobbly start 00604 to a digit */ 00605 #ifdef OLD_DSP_ROUTINES 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 #else 00618 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0]) { 00619 s->mhit = hit; 00620 s->digit_hits[(best_row << 2) + best_col]++; 00621 s->detected_digits++; 00622 if (s->current_digits < MAX_DTMF_DIGITS) { 00623 s->digits[s->current_digits++] = hit; 00624 s->digits[s->current_digits] = '\0'; 00625 } else { 00626 s->lost_digits++; 00627 } 00628 } 00629 #endif 00630 } 00631 } 00632 #ifdef FAX_DETECT 00633 if (!hit && (fax_energy >= FAX_THRESHOLD) && 00634 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) && 00635 (faxdetect)) { 00636 #if 0 00637 printf("Fax energy/Second Harmonic: %f\n", fax_energy); 00638 #endif 00639 /* XXX Probably need better checking than just this the energy XXX */ 00640 hit = 'f'; 00641 s->fax_hits++; 00642 } else { 00643 if (s->fax_hits > 5) { 00644 hit = 'f'; 00645 s->mhit = 'f'; 00646 s->detected_digits++; 00647 if (s->current_digits < MAX_DTMF_DIGITS) { 00648 s->digits[s->current_digits++] = hit; 00649 s->digits[s->current_digits] = '\0'; 00650 } else { 00651 s->lost_digits++; 00652 } 00653 } 00654 s->fax_hits = 0; 00655 } 00656 #endif /* FAX_DETECT */ 00657 #ifdef OLD_DSP_ROUTINES 00658 s->hit1 = s->hit2; 00659 s->hit2 = s->hit3; 00660 s->hit3 = hit; 00661 #else 00662 s->hits[0] = s->hits[1]; 00663 s->hits[1] = s->hits[2]; 00664 s->hits[2] = hit; 00665 #endif 00666 /* Reinitialise the detector for the next block */ 00667 for (i = 0; i < 4; i++) { 00668 goertzel_reset(&s->row_out[i]); 00669 goertzel_reset(&s->col_out[i]); 00670 #ifdef OLD_DSP_ROUTINES 00671 goertzel_reset(&s->row_out2nd[i]); 00672 goertzel_reset(&s->col_out2nd[i]); 00673 #endif 00674 } 00675 #ifdef FAX_DETECT 00676 goertzel_reset (&s->fax_tone); 00677 #ifdef OLD_DSP_ROUTINES 00678 goertzel_reset (&s->fax_tone2nd); 00679 #endif 00680 #endif 00681 s->energy = 0.0; 00682 s->current_sample = 0; 00683 } 00684 if ((!s->mhit) || (s->mhit != hit)) { 00685 s->mhit = 0; 00686 return(0); 00687 } 00688 return (hit); 00689 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 320 of file dsp.c.
References s.
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] |
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 315 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 306 of file dsp.c.
References goertzel_sample(), and s.
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 698 of file dsp.c.
References DSP_DIGITMODE_NOQUELCH, goertzel_result(), MAX_DTMF_DIGITS, MF_GSIZE, s, and warning().
Referenced by __ast_dsp_digitdetect().
00700 { 00701 #ifdef OLD_DSP_ROUTINES 00702 float tone_energy[6]; 00703 int best1; 00704 int best2; 00705 float max; 00706 int sofarsogood; 00707 #else 00708 float energy[6]; 00709 int best; 00710 int second_best; 00711 #endif 00712 float famp; 00713 float v1; 00714 int i; 00715 int j; 00716 int sample; 00717 int hit; 00718 int limit; 00719 00720 hit = 0; 00721 for (sample = 0; sample < samples; sample = limit) { 00722 /* 80 is optimised to meet the MF specs. */ 00723 if ((samples - sample) >= (MF_GSIZE - s->current_sample)) 00724 limit = sample + (MF_GSIZE - s->current_sample); 00725 else 00726 limit = samples; 00727 #if defined(USE_3DNOW) 00728 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00729 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00730 #ifdef OLD_DSP_ROUTINES 00731 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00732 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00733 #endif 00734 /* XXX Need to fax detect for 3dnow too XXX */ 00735 #warning "Fax Support Broken" 00736 #else 00737 /* The following unrolled loop takes only 35% (rough estimate) of the 00738 time of a rolled loop on the machine on which it was developed */ 00739 for (j = sample; j < limit; j++) { 00740 famp = amp[j]; 00741 #ifdef OLD_DSP_ROUTINES 00742 s->energy += famp*famp; 00743 #endif 00744 /* With GCC 2.95, the following unrolled code seems to take about 35% 00745 (rough estimate) as long as a neat little 0-3 loop */ 00746 v1 = s->tone_out[0].v2; 00747 s->tone_out[0].v2 = s->tone_out[0].v3; 00748 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp; 00749 v1 = s->tone_out[1].v2; 00750 s->tone_out[1].v2 = s->tone_out[1].v3; 00751 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp; 00752 v1 = s->tone_out[2].v2; 00753 s->tone_out[2].v2 = s->tone_out[2].v3; 00754 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp; 00755 v1 = s->tone_out[3].v2; 00756 s->tone_out[3].v2 = s->tone_out[3].v3; 00757 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp; 00758 v1 = s->tone_out[4].v2; 00759 s->tone_out[4].v2 = s->tone_out[4].v3; 00760 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp; 00761 v1 = s->tone_out[5].v2; 00762 s->tone_out[5].v2 = s->tone_out[5].v3; 00763 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp; 00764 #ifdef OLD_DSP_ROUTINES 00765 v1 = s->tone_out2nd[0].v2; 00766 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3; 00767 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp; 00768 v1 = s->tone_out2nd[1].v2; 00769 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3; 00770 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp; 00771 v1 = s->tone_out2nd[2].v2; 00772 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3; 00773 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp; 00774 v1 = s->tone_out2nd[3].v2; 00775 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3; 00776 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp; 00777 v1 = s->tone_out2nd[4].v2; 00778 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3; 00779 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp; 00780 v1 = s->tone_out2nd[3].v2; 00781 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3; 00782 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp; 00783 #endif 00784 } 00785 #endif 00786 s->current_sample += (limit - sample); 00787 if (s->current_sample < MF_GSIZE) { 00788 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00789 /* If we had a hit last time, go ahead and clear this out since likely it 00790 will be another hit */ 00791 for (i=sample;i<limit;i++) 00792 amp[i] = 0; 00793 *writeback = 1; 00794 } 00795 continue; 00796 } 00797 #ifdef OLD_DSP_ROUTINES 00798 /* We're at the end of an MF detection block. Go ahead and calculate 00799 all the energies. */ 00800 for (i=0;i<6;i++) { 00801 tone_energy[i] = goertzel_result(&s->tone_out[i]); 00802 } 00803 /* Find highest */ 00804 best1 = 0; 00805 max = tone_energy[0]; 00806 for (i=1;i<6;i++) { 00807 if (tone_energy[i] > max) { 00808 max = tone_energy[i]; 00809 best1 = i; 00810 } 00811 } 00812 00813 /* Find 2nd highest */ 00814 if (best1) { 00815 max = tone_energy[0]; 00816 best2 = 0; 00817 } else { 00818 max = tone_energy[1]; 00819 best2 = 1; 00820 } 00821 00822 for (i=0;i<6;i++) { 00823 if (i == best1) continue; 00824 if (tone_energy[i] > max) { 00825 max = tone_energy[i]; 00826 best2 = i; 00827 } 00828 } 00829 hit = 0; 00830 if (best1 != best2) 00831 sofarsogood=1; 00832 else 00833 sofarsogood=0; 00834 /* Check for relative energies */ 00835 for (i=0;i<6;i++) { 00836 if (i == best1) 00837 continue; 00838 if (i == best2) 00839 continue; 00840 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) { 00841 sofarsogood = 0; 00842 break; 00843 } 00844 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) { 00845 sofarsogood = 0; 00846 break; 00847 } 00848 } 00849 00850 if (sofarsogood) { 00851 /* Check for 2nd harmonic */ 00852 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 00853 sofarsogood = 0; 00854 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2]) 00855 sofarsogood = 0; 00856 } 00857 if (sofarsogood) { 00858 hit = mf_hit[best1][best2]; 00859 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00860 /* Zero out frame data if this is part DTMF */ 00861 for (i=sample;i<limit;i++) 00862 amp[i] = 0; 00863 *writeback = 1; 00864 } 00865 /* Look for two consecutive clean hits */ 00866 if ((hit == s->hit3) && (s->hit3 != s->hit2)) { 00867 s->mhit = hit; 00868 s->detected_digits++; 00869 if (s->current_digits < MAX_DTMF_DIGITS - 2) { 00870 s->digits[s->current_digits++] = hit; 00871 s->digits[s->current_digits] = '\0'; 00872 } else { 00873 s->lost_digits++; 00874 } 00875 } 00876 } 00877 00878 s->hit1 = s->hit2; 00879 s->hit2 = s->hit3; 00880 s->hit3 = hit; 00881 /* Reinitialise the detector for the next block */ 00882 for (i = 0; i < 6; i++) { 00883 goertzel_reset(&s->tone_out[i]); 00884 goertzel_reset(&s->tone_out2nd[i]); 00885 } 00886 s->energy = 0.0; 00887 s->current_sample = 0; 00888 } 00889 #else 00890 /* We're at the end of an MF detection block. */ 00891 /* Find the two highest energies. The spec says to look for 00892 two tones and two tones only. Taking this literally -ie 00893 only two tones pass the minimum threshold - doesn't work 00894 well. The sinc function mess, due to rectangular windowing 00895 ensure that! Find the two highest energies and ensure they 00896 are considerably stronger than any of the others. */ 00897 energy[0] = goertzel_result(&s->tone_out[0]); 00898 energy[1] = goertzel_result(&s->tone_out[1]); 00899 if (energy[0] > energy[1]) { 00900 best = 0; 00901 second_best = 1; 00902 } else { 00903 best = 1; 00904 second_best = 0; 00905 } 00906 /*endif*/ 00907 for (i=2;i<6;i++) { 00908 energy[i] = goertzel_result(&s->tone_out[i]); 00909 if (energy[i] >= energy[best]) { 00910 second_best = best; 00911 best = i; 00912 } else if (energy[i] >= energy[second_best]) { 00913 second_best = i; 00914 } 00915 } 00916 /* Basic signal level and twist tests */ 00917 hit = 0; 00918 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00919 && energy[best] < energy[second_best]*BELL_MF_TWIST 00920 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00921 /* Relative peak test */ 00922 hit = -1; 00923 for (i=0;i<6;i++) { 00924 if (i != best && i != second_best) { 00925 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00926 /* The best two are not clearly the best */ 00927 hit = 0; 00928 break; 00929 } 00930 } 00931 } 00932 } 00933 if (hit) { 00934 /* Get the values into ascending order */ 00935 if (second_best < best) { 00936 i = best; 00937 best = second_best; 00938 second_best = i; 00939 } 00940 best = best*5 + second_best - 1; 00941 hit = bell_mf_positions[best]; 00942 /* Look for two successive similar results */ 00943 /* The logic in the next test is: 00944 For KP we need 4 successive identical clean detects, with 00945 two blocks of something different preceeding it. For anything 00946 else we need two successive identical clean detects, with 00947 two blocks of something different preceeding it. */ 00948 if (hit == s->hits[4] && hit == s->hits[3] && 00949 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])|| 00950 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 00951 hit != s->hits[0]))) { 00952 s->detected_digits++; 00953 if (s->current_digits < MAX_DTMF_DIGITS) { 00954 s->digits[s->current_digits++] = hit; 00955 s->digits[s->current_digits] = '\0'; 00956 } else { 00957 s->lost_digits++; 00958 } 00959 } 00960 } else { 00961 hit = 0; 00962 } 00963 s->hits[0] = s->hits[1]; 00964 s->hits[1] = s->hits[2]; 00965 s->hits[2] = s->hits[3]; 00966 s->hits[3] = s->hits[4]; 00967 s->hits[4] = hit; 00968 /* Reinitialise the detector for the next block */ 00969 for (i = 0; i < 6; i++) 00970 goertzel_reset(&s->tone_out[i]); 00971 s->current_sample = 0; 00972 } 00973 #endif 00974 if ((!s->mhit) || (s->mhit != hit)) { 00975 s->mhit = 0; 00976 return(0); 00977 } 00978 return (hit); 00979 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 1011 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
01012 { 01013 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 01014 /* Make sure absolute levels are high enough */ 01015 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 01016 return 0; 01017 /* Amplify ignored stuff */ 01018 i2 *= TONE_THRESH; 01019 i1 *= TONE_THRESH; 01020 e *= TONE_THRESH; 01021 /* Check first tone */ 01022 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 01023 return 0; 01024 /* And second */ 01025 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 01026 return 0; 01027 /* Guess it's there... */ 01028 return 1; 01029 }
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().