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