#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk.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"
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 | BUSY_MAX 3100 |
#define | BUSY_MIN 75 |
#define | BUSY_PAT_PERCENT 7 |
#define | BUSY_PERCENT 10 |
#define | BUSY_THRESHOLD 100 |
#define | BUSYDETECT_MARTIN |
#define | COUNT_THRESH 3 |
#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 | GSAMP_SIZE_CR 188 |
#define | GSAMP_SIZE_NA 183 |
#define | GSAMP_SIZE_UK 160 |
#define | HZ_1400 5 |
#define | HZ_1800 6 |
#define | HZ_350 0 |
#define | HZ_400 0 |
#define | HZ_425 0 |
#define | HZ_440 1 |
#define | HZ_480 2 |
#define | HZ_620 3 |
#define | HZ_950 4 |
#define | MAX_DTMF_DIGITS 128 |
#define | MF_GSIZE 120 |
#define | PROG_MODE_CR 1 |
#define | PROG_MODE_NA 0 |
#define | PROG_MODE_UK 2 |
#define | TONE_MIN_THRESH 1e8 |
#define | TONE_THRESH 10.0 |
#define | UK_HANGUP_THRESH 60 |
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 BUSY_MAX 3100 |
#define BUSY_MIN 75 |
#define BUSY_PAT_PERCENT 7 |
#define BUSY_PERCENT 10 |
#define BUSY_THRESHOLD 100 |
#define COUNT_THRESH 3 |
#define DEFAULT_THRESHOLD 512 |
#define DSP_HISTORY 15 |
Definition at line 113 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 FIX_INF | ( | inf | ) |
Referenced by ast_dsp_process().
#define HZ_1400 5 |
#define HZ_1800 6 |
#define HZ_350 0 |
#define HZ_400 0 |
#define HZ_425 0 |
#define HZ_440 1 |
#define HZ_480 2 |
#define HZ_620 3 |
#define HZ_950 4 |
#define MAX_DTMF_DIGITS 128 |
#define MF_GSIZE 120 |
#define PROG_MODE_CR 1 |
#define PROG_MODE_NA 0 |
#define PROG_MODE_UK 2 |
#define TONE_MIN_THRESH 1e8 |
#define TONE_THRESH 10.0 |
#define UK_HANGUP_THRESH 60 |
static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len | |||
) | [static] |
Definition at line 1031 of file dsp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), COUNT_THRESH, dsp, 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_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::tcount, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, UK_HANGUP_THRESH, goertzel_state_t::v2, and goertzel_state_t::v3.
Referenced by ast_dsp_call_progress(), and ast_dsp_process().
01032 { 01033 int x; 01034 int y; 01035 int pass; 01036 int newstate = DSP_TONE_STATE_SILENCE; 01037 int res = 0; 01038 int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH; 01039 while(len) { 01040 /* Take the lesser of the number of samples we need and what we have */ 01041 pass = len; 01042 if (pass > dsp->gsamp_size - dsp->gsamps) 01043 pass = dsp->gsamp_size - dsp->gsamps; 01044 for (x=0;x<pass;x++) { 01045 for (y=0;y<dsp->freqcount;y++) 01046 goertzel_sample(&dsp->freqs[y], s[x]); 01047 dsp->genergy += s[x] * s[x]; 01048 } 01049 s += pass; 01050 dsp->gsamps += pass; 01051 len -= pass; 01052 if (dsp->gsamps == dsp->gsamp_size) { 01053 float hz[7]; 01054 for (y=0;y<7;y++) 01055 hz[y] = goertzel_result(&dsp->freqs[y]); 01056 #if 0 01057 printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n"); 01058 printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n", 01059 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); 01060 #endif 01061 switch(dsp->progmode) { 01062 case PROG_MODE_NA: 01063 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { 01064 newstate = DSP_TONE_STATE_BUSY; 01065 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) { 01066 newstate = DSP_TONE_STATE_RINGING; 01067 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) { 01068 newstate = DSP_TONE_STATE_DIALTONE; 01069 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) { 01070 newstate = DSP_TONE_STATE_SPECIAL1; 01071 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) { 01072 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) 01073 newstate = DSP_TONE_STATE_SPECIAL2; 01074 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { 01075 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) 01076 newstate = DSP_TONE_STATE_SPECIAL3; 01077 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01078 newstate = DSP_TONE_STATE_TALKING; 01079 } else 01080 newstate = DSP_TONE_STATE_SILENCE; 01081 break; 01082 case PROG_MODE_CR: 01083 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { 01084 newstate = DSP_TONE_STATE_RINGING; 01085 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { 01086 newstate = DSP_TONE_STATE_TALKING; 01087 } else 01088 newstate = DSP_TONE_STATE_SILENCE; 01089 break; 01090 case PROG_MODE_UK: 01091 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { 01092 newstate = DSP_TONE_STATE_HUNGUP; 01093 } 01094 break; 01095 default: 01096 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode); 01097 } 01098 if (newstate == dsp->tstate) { 01099 dsp->tcount++; 01100 if (dsp->tcount == thresh) { 01101 if ((dsp->features & DSP_PROGRESS_BUSY) && 01102 dsp->tstate == DSP_TONE_STATE_BUSY) { 01103 res = AST_CONTROL_BUSY; 01104 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01105 } else if ((dsp->features & DSP_PROGRESS_TALK) && 01106 dsp->tstate == DSP_TONE_STATE_TALKING) { 01107 res = AST_CONTROL_ANSWER; 01108 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01109 } else if ((dsp->features & DSP_PROGRESS_RINGING) && 01110 dsp->tstate == DSP_TONE_STATE_RINGING) 01111 res = AST_CONTROL_RINGING; 01112 else if ((dsp->features & DSP_PROGRESS_CONGESTION) && 01113 dsp->tstate == DSP_TONE_STATE_SPECIAL3) { 01114 res = AST_CONTROL_CONGESTION; 01115 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01116 } else if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) && 01117 dsp->tstate == DSP_TONE_STATE_HUNGUP) { 01118 res = AST_CONTROL_HANGUP; 01119 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; 01120 } 01121 } 01122 } else { 01123 #if 0 01124 printf("Newstate: %d\n", newstate); 01125 #endif 01126 dsp->tstate = newstate; 01127 dsp->tcount = 1; 01128 } 01129 01130 /* Reset goertzel */ 01131 for (x=0;x<7;x++) 01132 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01133 dsp->gsamps = 0; 01134 dsp->genergy = 0.0; 01135 } 01136 } 01137 #if 0 01138 if (res) 01139 printf("Returning %d\n", res); 01140 #endif 01141 return res; 01142 }
static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | writeback | |||
) | [static] |
Definition at line 956 of file dsp.c.
References ast_dsp::digitmode, dsp, 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().
00957 { 00958 int res; 00959 00960 if (dsp->digitmode & DSP_DIGITMODE_MF) 00961 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback); 00962 else 00963 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT); 00964 return res; 00965 }
static int __ast_dsp_silence | ( | struct ast_dsp * | dsp, | |
short * | s, | |||
int | len, | |||
int * | totalsilence | |||
) | [static] |
Definition at line 1157 of file dsp.c.
References ast_dsp::busycount, ast_dsp::busymaybe, dsp, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::totalnoise, and ast_dsp::totalsilence.
Referenced by ast_dsp_process(), and ast_dsp_silence().
01158 { 01159 int accum; 01160 int x; 01161 int res = 0; 01162 01163 if (!len) 01164 return 0; 01165 accum = 0; 01166 for (x=0;x<len; x++) 01167 accum += abs(s[x]); 01168 accum /= len; 01169 if (accum < dsp->threshold) { 01170 /* Silent */ 01171 dsp->totalsilence += len/8; 01172 if (dsp->totalnoise) { 01173 /* Move and save history */ 01174 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); 01175 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; 01176 /* we don't want to check for busydetect that frequently */ 01177 #if 0 01178 dsp->busymaybe = 1; 01179 #endif 01180 } 01181 dsp->totalnoise = 0; 01182 res = 1; 01183 } else { 01184 /* Not silent */ 01185 dsp->totalnoise += len/8; 01186 if (dsp->totalsilence) { 01187 int silence1 = dsp->historicsilence[DSP_HISTORY - 1]; 01188 int silence2 = dsp->historicsilence[DSP_HISTORY - 2]; 01189 /* Move and save history */ 01190 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0])); 01191 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; 01192 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ 01193 if (silence1 < silence2) { 01194 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) 01195 dsp->busymaybe = 1; 01196 else 01197 dsp->busymaybe = 0; 01198 } else { 01199 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) 01200 dsp->busymaybe = 1; 01201 else 01202 dsp->busymaybe = 0; 01203 } 01204 } 01205 dsp->totalsilence = 0; 01206 } 01207 if (totalsilence) 01208 *totalsilence = dsp->totalsilence; 01209 return res; 01210 }
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 1213 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, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, and LOG_NOTICE.
Referenced by ast_dsp_busydetect(), and ast_dsp_process().
01214 { 01215 int res = 0, x; 01216 #ifndef BUSYDETECT_TONEONLY 01217 int avgsilence = 0, hitsilence = 0; 01218 #endif 01219 int avgtone = 0, hittone = 0; 01220 if (!dsp->busymaybe) 01221 return res; 01222 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01223 #ifndef BUSYDETECT_TONEONLY 01224 avgsilence += dsp->historicsilence[x]; 01225 #endif 01226 avgtone += dsp->historicnoise[x]; 01227 } 01228 #ifndef BUSYDETECT_TONEONLY 01229 avgsilence /= dsp->busycount; 01230 #endif 01231 avgtone /= dsp->busycount; 01232 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { 01233 #ifndef BUSYDETECT_TONEONLY 01234 if (avgsilence > dsp->historicsilence[x]) { 01235 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) 01236 hitsilence++; 01237 } else { 01238 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) 01239 hitsilence++; 01240 } 01241 #endif 01242 if (avgtone > dsp->historicnoise[x]) { 01243 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) 01244 hittone++; 01245 } else { 01246 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 01247 hittone++; 01248 } 01249 } 01250 #ifndef BUSYDETECT_TONEONLY 01251 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 01252 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 01253 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { 01254 #else 01255 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { 01256 #endif 01257 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE 01258 #ifdef BUSYDETECT_TONEONLY 01259 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE 01260 #endif 01261 if (avgtone > avgsilence) { 01262 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) 01263 res = 1; 01264 } else { 01265 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) 01266 res = 1; 01267 } 01268 #else 01269 res = 1; 01270 #endif 01271 } 01272 /* If we know the expected busy tone length, check we are in the range */ 01273 if (res && (dsp->busy_tonelength > 0)) { 01274 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { 01275 #if 0 01276 ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n", 01277 avgtone, dsp->busy_tonelength); 01278 #endif 01279 res = 0; 01280 } 01281 } 01282 #ifndef BUSYDETECT_TONEONLY 01283 /* If we know the expected busy tone silent-period length, check we are in the range */ 01284 if (res && (dsp->busy_quietlength > 0)) { 01285 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { 01286 #if 0 01287 ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n", 01288 avgsilence, dsp->busy_quietlength); 01289 #endif 01290 res = 0; 01291 } 01292 } 01293 #endif 01294 #if 1 01295 if (res) 01296 ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); 01297 #endif 01298 return res; 01299 }
Scans for progress indication in audio.
Definition at line 1144 of file dsp.c.
References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.
01145 { 01146 if (inf->frametype != AST_FRAME_VOICE) { 01147 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01148 return 0; 01149 } 01150 if (inf->subclass != AST_FORMAT_SLINEAR) { 01151 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01152 return 0; 01153 } 01154 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01155 }
Return non-zero if DTMF hit was found.
Definition at line 967 of file dsp.c.
References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.
00968 { 00969 short *s; 00970 int len; 00971 int ign=0; 00972 00973 if (inf->frametype != AST_FRAME_VOICE) { 00974 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00975 return 0; 00976 } 00977 if (inf->subclass != AST_FORMAT_SLINEAR) { 00978 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00979 return 0; 00980 } 00981 s = inf->data; 00982 len = inf->datalen / 2; 00983 return __ast_dsp_digitdetect(dsp, s, len, &ign); 00984 }
int ast_dsp_digitmode | ( | struct ast_dsp * | dsp, | |
int | digitmode | |||
) |
Set digit mode.
Definition at line 1686 of file dsp.c.
References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_dsp::digitmode, dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.
Referenced by i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().
01687 { 01688 int new; 01689 int old; 01690 01691 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01692 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01693 if (old != new) { 01694 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01695 if (new & DSP_DIGITMODE_MF) 01696 ast_mf_detect_init(&dsp->td.mf); 01697 else 01698 ast_dtmf_detect_init(&dsp->td.dtmf); 01699 } 01700 dsp->digitmode = digitmode; 01701 return 0; 01702 }
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1624 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, 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().
01625 { 01626 int i; 01627 01628 dsp->thinkdigit = 0; 01629 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01630 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01631 dsp->td.mf.current_digits = 0; 01632 /* Reinitialise the detector for the next block */ 01633 for (i = 0; i < 6; i++) { 01634 goertzel_reset(&dsp->td.mf.tone_out[i]); 01635 #ifdef OLD_DSP_ROUTINES 01636 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01637 #endif 01638 } 01639 #ifdef OLD_DSP_ROUTINES 01640 dsp->td.mf.energy = 0.0; 01641 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01642 #else 01643 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; 01644 #endif 01645 dsp->td.mf.current_sample = 0; 01646 } else { 01647 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01648 dsp->td.dtmf.current_digits = 0; 01649 /* Reinitialise the detector for the next block */ 01650 for (i = 0; i < 4; i++) { 01651 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01652 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01653 #ifdef OLD_DSP_ROUTINES 01654 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01655 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01656 #endif 01657 } 01658 #ifdef FAX_DETECT 01659 goertzel_reset (&dsp->td.dtmf.fax_tone); 01660 #endif 01661 #ifdef OLD_DSP_ROUTINES 01662 #ifdef FAX_DETECT 01663 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01664 #endif 01665 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01666 #else 01667 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0; 01668 #endif 01669 dsp->td.dtmf.energy = 0.0; 01670 dsp->td.dtmf.current_sample = 0; 01671 } 01672 }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1598 of file dsp.c.
Referenced by __oh323_destroy(), ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), do_waiting(), handle_recordfile(), i4l_hangup(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), ss_thread(), vpb_hangup(), and zt_hangup().
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, | |
char * | buf, | |||
int | max | |||
) |
Get pending DTMF/MF digits.
Definition at line 1006 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, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.
01007 { 01008 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01009 if (max > dsp->td.mf.current_digits) 01010 max = dsp->td.mf.current_digits; 01011 if (max > 0) { 01012 memcpy(buf, dsp->td.mf.digits, max); 01013 memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 01014 dsp->td.mf.current_digits -= max; 01015 } 01016 buf[max] = '\0'; 01017 return max; 01018 } else { 01019 if (max > dsp->td.dtmf.current_digits) 01020 max = dsp->td.dtmf.current_digits; 01021 if (max > 0) { 01022 memcpy (buf, dsp->td.dtmf.digits, max); 01023 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01024 dsp->td.dtmf.current_digits -= max; 01025 } 01026 buf[max] = '\0'; 01027 return max; 01028 } 01029 }
struct ast_dsp* ast_dsp_new | ( | void | ) |
Definition at line 1575 of file dsp.c.
References ast_dsp_prog_reset(), ast_dtmf_detect_init(), DEFAULT_THRESHOLD, dsp, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and malloc.
Referenced by __oh323_new(), ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), i4l_answer(), i4l_startrec(), mgcp_new(), misdn_set_opt_exec(), mkif(), sip_dtmfmode(), sip_new(), and zt_new().
01576 { 01577 struct ast_dsp *dsp; 01578 01579 dsp = malloc(sizeof(struct ast_dsp)); 01580 if (dsp) { 01581 memset(dsp, 0, sizeof(struct ast_dsp)); 01582 dsp->threshold = DEFAULT_THRESHOLD; 01583 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01584 dsp->busycount = DSP_HISTORY; 01585 /* Initialize DTMF detector */ 01586 ast_dtmf_detect_init(&dsp->td.dtmf); 01587 /* Initialize initial DSP progress detect parameters */ 01588 ast_dsp_prog_reset(dsp); 01589 } 01590 return dsp; 01591 }
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 1365 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_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, 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, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, ast_channel::name, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.
Referenced by do_chanreads(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), and zt_read().
01366 { 01367 int silence; 01368 int res; 01369 int digit; 01370 int x; 01371 short *shortdata; 01372 unsigned char *odata; 01373 int len; 01374 int writeback = 0; 01375 01376 #define FIX_INF(inf) do { \ 01377 if (writeback) { \ 01378 switch(inf->subclass) { \ 01379 case AST_FORMAT_SLINEAR: \ 01380 break; \ 01381 case AST_FORMAT_ULAW: \ 01382 for (x=0;x<len;x++) \ 01383 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \ 01384 break; \ 01385 case AST_FORMAT_ALAW: \ 01386 for (x=0;x<len;x++) \ 01387 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \ 01388 break; \ 01389 } \ 01390 } \ 01391 } while(0) 01392 01393 if (!af) 01394 return NULL; 01395 if (af->frametype != AST_FRAME_VOICE) 01396 return af; 01397 odata = af->data; 01398 len = af->datalen; 01399 /* Make sure we have short data */ 01400 switch(af->subclass) { 01401 case AST_FORMAT_SLINEAR: 01402 shortdata = af->data; 01403 len = af->datalen / 2; 01404 break; 01405 case AST_FORMAT_ULAW: 01406 shortdata = alloca(af->datalen * 2); 01407 if (!shortdata) { 01408 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01409 return af; 01410 } 01411 for (x=0;x<len;x++) 01412 shortdata[x] = AST_MULAW(odata[x]); 01413 break; 01414 case AST_FORMAT_ALAW: 01415 shortdata = alloca(af->datalen * 2); 01416 if (!shortdata) { 01417 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01418 return af; 01419 } 01420 for (x=0;x<len;x++) 01421 shortdata[x] = AST_ALAW(odata[x]); 01422 break; 01423 default: 01424 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); 01425 return af; 01426 } 01427 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01428 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01429 memset(&dsp->f, 0, sizeof(dsp->f)); 01430 dsp->f.frametype = AST_FRAME_NULL; 01431 return &dsp->f; 01432 } 01433 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01434 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01435 memset(&dsp->f, 0, sizeof(dsp->f)); 01436 dsp->f.frametype = AST_FRAME_CONTROL; 01437 dsp->f.subclass = AST_CONTROL_BUSY; 01438 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01439 return &dsp->f; 01440 } 01441 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01442 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01443 #if 0 01444 if (digit) 01445 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01446 #endif 01447 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01448 if (!dsp->thinkdigit) { 01449 if (digit) { 01450 /* Looks like we might have something. 01451 * Request a conference mute for the moment */ 01452 memset(&dsp->f, 0, sizeof(dsp->f)); 01453 dsp->f.frametype = AST_FRAME_DTMF; 01454 dsp->f.subclass = 'm'; 01455 dsp->thinkdigit = 'x'; 01456 FIX_INF(af); 01457 if (chan) 01458 ast_queue_frame(chan, af); 01459 ast_frfree(af); 01460 return &dsp->f; 01461 } 01462 } else { 01463 if (digit) { 01464 /* Thought we saw one last time. Pretty sure we really have now */ 01465 if (dsp->thinkdigit) { 01466 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01467 /* If we found a digit, and we're changing digits, go 01468 ahead and send this one, but DON'T stop confmute because 01469 we're detecting something else, too... */ 01470 memset(&dsp->f, 0, sizeof(dsp->f)); 01471 dsp->f.frametype = AST_FRAME_DTMF; 01472 dsp->f.subclass = dsp->thinkdigit; 01473 FIX_INF(af); 01474 if (chan) 01475 ast_queue_frame(chan, af); 01476 ast_frfree(af); 01477 } 01478 dsp->thinkdigit = digit; 01479 return &dsp->f; 01480 } 01481 dsp->thinkdigit = digit; 01482 } else { 01483 if (dsp->thinkdigit) { 01484 memset(&dsp->f, 0, sizeof(dsp->f)); 01485 if (dsp->thinkdigit != 'x') { 01486 /* If we found a digit, send it now */ 01487 dsp->f.frametype = AST_FRAME_DTMF; 01488 dsp->f.subclass = dsp->thinkdigit; 01489 dsp->thinkdigit = 0; 01490 } else { 01491 dsp->f.frametype = AST_FRAME_DTMF; 01492 dsp->f.subclass = 'u'; 01493 dsp->thinkdigit = 0; 01494 } 01495 FIX_INF(af); 01496 if (chan) 01497 ast_queue_frame(chan, af); 01498 ast_frfree(af); 01499 return &dsp->f; 01500 } 01501 } 01502 } 01503 } else if (!digit) { 01504 /* Only check when there is *not* a hit... */ 01505 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01506 if (dsp->td.mf.current_digits) { 01507 memset(&dsp->f, 0, sizeof(dsp->f)); 01508 dsp->f.frametype = AST_FRAME_DTMF; 01509 dsp->f.subclass = dsp->td.mf.digits[0]; 01510 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01511 dsp->td.mf.current_digits--; 01512 FIX_INF(af); 01513 if (chan) 01514 ast_queue_frame(chan, af); 01515 ast_frfree(af); 01516 return &dsp->f; 01517 } 01518 } else { 01519 if (dsp->td.dtmf.current_digits) { 01520 memset(&dsp->f, 0, sizeof(dsp->f)); 01521 dsp->f.frametype = AST_FRAME_DTMF; 01522 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01523 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01524 dsp->td.dtmf.current_digits--; 01525 FIX_INF(af); 01526 if (chan) 01527 ast_queue_frame(chan, af); 01528 ast_frfree(af); 01529 return &dsp->f; 01530 } 01531 } 01532 } 01533 } 01534 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01535 res = __ast_dsp_call_progress(dsp, shortdata, len); 01536 if (res) { 01537 switch(res) { 01538 case AST_CONTROL_ANSWER: 01539 case AST_CONTROL_BUSY: 01540 case AST_CONTROL_RINGING: 01541 case AST_CONTROL_CONGESTION: 01542 case AST_CONTROL_HANGUP: 01543 memset(&dsp->f, 0, sizeof(dsp->f)); 01544 dsp->f.frametype = AST_FRAME_CONTROL; 01545 dsp->f.subclass = res; 01546 dsp->f.src = "dsp_progress"; 01547 if (chan) 01548 ast_queue_frame(chan, &dsp->f); 01549 break; 01550 default: 01551 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01552 } 01553 } 01554 } 01555 FIX_INF(af); 01556 return af; 01557 }
static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | [static] |
Definition at line 1559 of file dsp.c.
References dsp, ast_dsp::freqcount, ast_dsp::freqs, progress::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, modes, ast_dsp::progmode, and progress::size.
Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().
01560 { 01561 int max = 0; 01562 int x; 01563 01564 dsp->gsamp_size = modes[dsp->progmode].size; 01565 dsp->gsamps = 0; 01566 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { 01567 if (modes[dsp->progmode].freqs[x]) { 01568 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size); 01569 max = x + 1; 01570 } 01571 } 01572 dsp->freqcount = max; 01573 }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1674 of file dsp.c.
References dsp, ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.
01675 { 01676 int x; 01677 01678 dsp->totalsilence = 0; 01679 dsp->gsamps = 0; 01680 for (x=0;x<4;x++) 01681 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01682 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01683 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01684 }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, | |
int | cadences | |||
) |
Set number of required cadences for busy.
Definition at line 1608 of file dsp.c.
References ast_dsp::busycount, dsp, and DSP_HISTORY.
Referenced by zt_new().
01609 { 01610 if (cadences < 4) 01611 cadences = 4; 01612 if (cadences > DSP_HISTORY) 01613 cadences = DSP_HISTORY; 01614 dsp->busycount = cadences; 01615 }
void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, | |
int | tonelength, | |||
int | quietlength | |||
) |
Set expected lengths of the busy tone.
Definition at line 1617 of file dsp.c.
References ast_log(), ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, dsp, and LOG_DEBUG.
Referenced by zt_new().
01618 { 01619 dsp->busy_tonelength = tonelength; 01620 dsp->busy_quietlength = quietlength; 01621 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); 01622 }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, | |
char * | zone | |||
) |
Set zone for doing progress detection.
Definition at line 1704 of file dsp.c.
References aliases, ast_dsp_prog_reset(), dsp, name, and ast_dsp::progmode.
Referenced by zt_new().
01705 { 01706 int x; 01707 01708 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) { 01709 if (!strcasecmp(aliases[x].name, zone)) { 01710 dsp->progmode = aliases[x].mode; 01711 ast_dsp_prog_reset(dsp); 01712 return 0; 01713 } 01714 } 01715 return -1; 01716 }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, | |
int | features | |||
) |
Select feature set.
Definition at line 1593 of file dsp.c.
References dsp, and ast_dsp::features.
Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), i4l_answer(), i4l_startrec(), mgcp_new(), misdn_set_opt_exec(), mkif(), 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 1603 of file dsp.c.
References dsp, and ast_dsp::threshold.
Referenced by ast_play_and_prepend(), ast_play_and_record_full(), do_waiting(), and handle_recordfile().
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1347 of file dsp.c.
References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, dsp, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.
Referenced by ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), conf_run(), do_waiting(), and handle_recordfile().
01348 { 01349 short *s; 01350 int len; 01351 01352 if (f->frametype != AST_FRAME_VOICE) { 01353 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01354 return 0; 01355 } 01356 if (f->subclass != AST_FORMAT_SLINEAR) { 01357 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01358 return 0; 01359 } 01360 s = f->data; 01361 len = f->datalen/2; 01362 return __ast_dsp_silence(dsp, s, len, totalsilence); 01363 }
static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | [static] |
Definition at line 338 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_dsp_digitmode(), and ast_dsp_new().
00339 { 00340 int i; 00341 00342 #ifdef OLD_DSP_ROUTINES 00343 s->hit1 = 00344 s->mhit = 00345 s->hit3 = 00346 s->hit4 = 00347 s->hit2 = 0; 00348 #else 00349 s->hits[0] = s->hits[1] = s->hits[2] = 0; 00350 #endif 00351 for (i = 0; i < 4; i++) { 00352 goertzel_init (&s->row_out[i], dtmf_row[i], 102); 00353 goertzel_init (&s->col_out[i], dtmf_col[i], 102); 00354 #ifdef OLD_DSP_ROUTINES 00355 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102); 00356 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102); 00357 #endif 00358 s->energy = 0.0; 00359 } 00360 #ifdef FAX_DETECT 00361 /* Same for the fax dector */ 00362 goertzel_init (&s->fax_tone, fax_freq, 102); 00363 00364 #ifdef OLD_DSP_ROUTINES 00365 /* Same for the fax dector 2nd harmonic */ 00366 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102); 00367 #endif 00368 #endif /* FAX_DETECT */ 00369 s->current_sample = 0; 00370 s->detected_digits = 0; 00371 s->current_digits = 0; 00372 memset(&s->digits, 0, sizeof(s->digits)); 00373 s->lost_digits = 0; 00374 s->digits[0] = '\0'; 00375 }
static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | [static] |
Definition at line 377 of file dsp.c.
References goertzel_init(), and s.
Referenced by ast_dsp_digitmode().
00378 { 00379 int i; 00380 #ifdef OLD_DSP_ROUTINES 00381 s->hit1 = 00382 s->hit2 = 0; 00383 #else 00384 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0; 00385 #endif 00386 for (i = 0; i < 6; i++) { 00387 goertzel_init (&s->tone_out[i], mf_tones[i], 160); 00388 #ifdef OLD_DSP_ROUTINES 00389 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160); 00390 s->energy = 0.0; 00391 #endif 00392 } 00393 s->current_digits = 0; 00394 memset(&s->digits, 0, sizeof(s->digits)); 00395 s->current_sample = 0; 00396 s->detected_digits = 0; 00397 s->lost_digits = 0; 00398 s->digits[0] = '\0'; 00399 s->mhit = 0; 00400 }
static int dtmf_detect | ( | dtmf_detect_state_t * | s, | |
int16_t | amp[], | |||
int | samples, | |||
int | digitmode, | |||
int * | writeback, | |||
int | faxdetect | |||
) | [static] |
Definition at line 402 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().
00404 { 00405 float row_energy[4]; 00406 float col_energy[4]; 00407 #ifdef FAX_DETECT 00408 float fax_energy; 00409 #ifdef OLD_DSP_ROUTINES 00410 float fax_energy_2nd; 00411 #endif 00412 #endif /* FAX_DETECT */ 00413 float famp; 00414 float v1; 00415 int i; 00416 int j; 00417 int sample; 00418 int best_row; 00419 int best_col; 00420 int hit; 00421 int limit; 00422 00423 hit = 0; 00424 for (sample = 0; sample < samples; sample = limit) { 00425 /* 102 is optimised to meet the DTMF specs. */ 00426 if ((samples - sample) >= (102 - s->current_sample)) 00427 limit = sample + (102 - s->current_sample); 00428 else 00429 limit = samples; 00430 #if defined(USE_3DNOW) 00431 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00432 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00433 #ifdef OLD_DSP_ROUTINES 00434 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00435 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00436 #endif 00437 /* XXX Need to fax detect for 3dnow too XXX */ 00438 #warning "Fax Support Broken" 00439 #else 00440 /* The following unrolled loop takes only 35% (rough estimate) of the 00441 time of a rolled loop on the machine on which it was developed */ 00442 for (j=sample;j<limit;j++) { 00443 famp = amp[j]; 00444 s->energy += famp*famp; 00445 /* With GCC 2.95, the following unrolled code seems to take about 35% 00446 (rough estimate) as long as a neat little 0-3 loop */ 00447 v1 = s->row_out[0].v2; 00448 s->row_out[0].v2 = s->row_out[0].v3; 00449 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; 00450 v1 = s->col_out[0].v2; 00451 s->col_out[0].v2 = s->col_out[0].v3; 00452 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; 00453 v1 = s->row_out[1].v2; 00454 s->row_out[1].v2 = s->row_out[1].v3; 00455 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; 00456 v1 = s->col_out[1].v2; 00457 s->col_out[1].v2 = s->col_out[1].v3; 00458 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; 00459 v1 = s->row_out[2].v2; 00460 s->row_out[2].v2 = s->row_out[2].v3; 00461 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; 00462 v1 = s->col_out[2].v2; 00463 s->col_out[2].v2 = s->col_out[2].v3; 00464 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; 00465 v1 = s->row_out[3].v2; 00466 s->row_out[3].v2 = s->row_out[3].v3; 00467 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; 00468 v1 = s->col_out[3].v2; 00469 s->col_out[3].v2 = s->col_out[3].v3; 00470 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; 00471 #ifdef FAX_DETECT 00472 /* Update fax tone */ 00473 v1 = s->fax_tone.v2; 00474 s->fax_tone.v2 = s->fax_tone.v3; 00475 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; 00476 #endif /* FAX_DETECT */ 00477 #ifdef OLD_DSP_ROUTINES 00478 v1 = s->col_out2nd[0].v2; 00479 s->col_out2nd[0].v2 = s->col_out2nd[0].v3; 00480 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; 00481 v1 = s->row_out2nd[0].v2; 00482 s->row_out2nd[0].v2 = s->row_out2nd[0].v3; 00483 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; 00484 v1 = s->col_out2nd[1].v2; 00485 s->col_out2nd[1].v2 = s->col_out2nd[1].v3; 00486 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; 00487 v1 = s->row_out2nd[1].v2; 00488 s->row_out2nd[1].v2 = s->row_out2nd[1].v3; 00489 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; 00490 v1 = s->col_out2nd[2].v2; 00491 s->col_out2nd[2].v2 = s->col_out2nd[2].v3; 00492 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; 00493 v1 = s->row_out2nd[2].v2; 00494 s->row_out2nd[2].v2 = s->row_out2nd[2].v3; 00495 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; 00496 v1 = s->col_out2nd[3].v2; 00497 s->col_out2nd[3].v2 = s->col_out2nd[3].v3; 00498 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; 00499 v1 = s->row_out2nd[3].v2; 00500 s->row_out2nd[3].v2 = s->row_out2nd[3].v3; 00501 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; 00502 #ifdef FAX_DETECT 00503 /* Update fax tone */ 00504 v1 = s->fax_tone.v2; 00505 s->fax_tone2nd.v2 = s->fax_tone2nd.v3; 00506 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; 00507 #endif /* FAX_DETECT */ 00508 #endif 00509 } 00510 #endif 00511 s->current_sample += (limit - sample); 00512 if (s->current_sample < 102) { 00513 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00514 /* If we had a hit last time, go ahead and clear this out since likely it 00515 will be another hit */ 00516 for (i=sample;i<limit;i++) 00517 amp[i] = 0; 00518 *writeback = 1; 00519 } 00520 continue; 00521 } 00522 #ifdef FAX_DETECT 00523 /* Detect the fax energy, too */ 00524 fax_energy = goertzel_result(&s->fax_tone); 00525 #endif 00526 /* We are at the end of a DTMF detection block */ 00527 /* Find the peak row and the peak column */ 00528 row_energy[0] = goertzel_result (&s->row_out[0]); 00529 col_energy[0] = goertzel_result (&s->col_out[0]); 00530 00531 for (best_row = best_col = 0, i = 1; i < 4; i++) { 00532 row_energy[i] = goertzel_result (&s->row_out[i]); 00533 if (row_energy[i] > row_energy[best_row]) 00534 best_row = i; 00535 col_energy[i] = goertzel_result (&s->col_out[i]); 00536 if (col_energy[i] > col_energy[best_col]) 00537 best_col = i; 00538 } 00539 hit = 0; 00540 /* Basic signal level test and the twist test */ 00541 if (row_energy[best_row] >= DTMF_THRESHOLD && 00542 col_energy[best_col] >= DTMF_THRESHOLD && 00543 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && 00544 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { 00545 /* Relative peak test */ 00546 for (i = 0; i < 4; i++) { 00547 if ((i != best_col && 00548 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || 00549 (i != best_row 00550 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { 00551 break; 00552 } 00553 } 00554 #ifdef OLD_DSP_ROUTINES 00555 /* ... and second harmonic test */ 00556 if (i >= 4 && 00557 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy && 00558 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] 00559 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { 00560 #else 00561 /* ... and fraction of total energy test */ 00562 if (i >= 4 && 00563 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) { 00564 #endif 00565 /* Got a hit */ 00566 hit = dtmf_positions[(best_row << 2) + best_col]; 00567 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00568 /* Zero out frame data if this is part DTMF */ 00569 for (i=sample;i<limit;i++) 00570 amp[i] = 0; 00571 *writeback = 1; 00572 } 00573 /* Look for two successive similar results */ 00574 /* The logic in the next test is: 00575 We need two successive identical clean detects, with 00576 something different preceeding it. This can work with 00577 back to back differing digits. More importantly, it 00578 can work with nasty phones that give a very wobbly start 00579 to a digit */ 00580 #ifdef OLD_DSP_ROUTINES 00581 if (hit == s->hit3 && s->hit3 != s->hit2) { 00582 s->mhit = hit; 00583 s->digit_hits[(best_row << 2) + best_col]++; 00584 s->detected_digits++; 00585 if (s->current_digits < MAX_DTMF_DIGITS) { 00586 s->digits[s->current_digits++] = hit; 00587 s->digits[s->current_digits] = '\0'; 00588 } else { 00589 s->lost_digits++; 00590 } 00591 } 00592 #else 00593 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0]) { 00594 s->mhit = hit; 00595 s->digit_hits[(best_row << 2) + best_col]++; 00596 s->detected_digits++; 00597 if (s->current_digits < MAX_DTMF_DIGITS) { 00598 s->digits[s->current_digits++] = hit; 00599 s->digits[s->current_digits] = '\0'; 00600 } else { 00601 s->lost_digits++; 00602 } 00603 } 00604 #endif 00605 } 00606 } 00607 #ifdef FAX_DETECT 00608 if (!hit && (fax_energy >= FAX_THRESHOLD) && 00609 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) && 00610 (faxdetect)) { 00611 #if 0 00612 printf("Fax energy/Second Harmonic: %f\n", fax_energy); 00613 #endif 00614 /* XXX Probably need better checking than just this the energy XXX */ 00615 hit = 'f'; 00616 s->fax_hits++; 00617 } else { 00618 if (s->fax_hits > 5) { 00619 hit = 'f'; 00620 s->mhit = 'f'; 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 s->fax_hits = 0; 00630 } 00631 #endif /* FAX_DETECT */ 00632 #ifdef OLD_DSP_ROUTINES 00633 s->hit1 = s->hit2; 00634 s->hit2 = s->hit3; 00635 s->hit3 = hit; 00636 #else 00637 s->hits[0] = s->hits[1]; 00638 s->hits[1] = s->hits[2]; 00639 s->hits[2] = hit; 00640 #endif 00641 /* Reinitialise the detector for the next block */ 00642 for (i = 0; i < 4; i++) { 00643 goertzel_reset(&s->row_out[i]); 00644 goertzel_reset(&s->col_out[i]); 00645 #ifdef OLD_DSP_ROUTINES 00646 goertzel_reset(&s->row_out2nd[i]); 00647 goertzel_reset(&s->col_out2nd[i]); 00648 #endif 00649 } 00650 #ifdef FAX_DETECT 00651 goertzel_reset (&s->fax_tone); 00652 #ifdef OLD_DSP_ROUTINES 00653 goertzel_reset (&s->fax_tone2nd); 00654 #endif 00655 #endif 00656 s->energy = 0.0; 00657 s->current_sample = 0; 00658 } 00659 if ((!s->mhit) || (s->mhit != hit)) { 00660 s->mhit = 0; 00661 return(0); 00662 } 00663 return (hit); 00664 }
static void goertzel_init | ( | goertzel_state_t * | s, | |
float | freq, | |||
int | samples | |||
) | [inline, static] |
Definition at line 296 of file dsp.c.
References s.
Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), and ast_mf_detect_init().
00297 { 00298 s->v2 = s->v3 = 0.0; 00299 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0)); 00300 #ifndef OLD_DSP_ROUTINES 00301 s->samples = samples; 00302 #endif 00303 }
static void goertzel_reset | ( | goertzel_state_t * | s | ) | [inline, static] |
static float goertzel_result | ( | goertzel_state_t * | s | ) | [inline, static] |
Definition at line 291 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 282 of file dsp.c.
References goertzel_sample(), and s.
00283 { 00284 int i; 00285 00286 for (i=0;i<count;i++) 00287 goertzel_sample(s, samps[i]); 00288 }
static int mf_detect | ( | mf_detect_state_t * | s, | |
int16_t | amp[], | |||
int | samples, | |||
int | digitmode, | |||
int * | writeback | |||
) | [static] |
Definition at line 673 of file dsp.c.
References DSP_DIGITMODE_NOQUELCH, goertzel_result(), MAX_DTMF_DIGITS, MF_GSIZE, s, and warning().
Referenced by __ast_dsp_digitdetect().
00675 { 00676 #ifdef OLD_DSP_ROUTINES 00677 float tone_energy[6]; 00678 int best1; 00679 int best2; 00680 float max; 00681 int sofarsogood; 00682 #else 00683 float energy[6]; 00684 int best; 00685 int second_best; 00686 #endif 00687 float famp; 00688 float v1; 00689 int i; 00690 int j; 00691 int sample; 00692 int hit; 00693 int limit; 00694 00695 hit = 0; 00696 for (sample = 0; sample < samples; sample = limit) { 00697 /* 80 is optimised to meet the MF specs. */ 00698 if ((samples - sample) >= (MF_GSIZE - s->current_sample)) 00699 limit = sample + (MF_GSIZE - s->current_sample); 00700 else 00701 limit = samples; 00702 #if defined(USE_3DNOW) 00703 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); 00704 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); 00705 #ifdef OLD_DSP_ROUTINES 00706 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); 00707 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); 00708 #endif 00709 /* XXX Need to fax detect for 3dnow too XXX */ 00710 #warning "Fax Support Broken" 00711 #else 00712 /* The following unrolled loop takes only 35% (rough estimate) of the 00713 time of a rolled loop on the machine on which it was developed */ 00714 for (j = sample; j < limit; j++) { 00715 famp = amp[j]; 00716 #ifdef OLD_DSP_ROUTINES 00717 s->energy += famp*famp; 00718 #endif 00719 /* With GCC 2.95, the following unrolled code seems to take about 35% 00720 (rough estimate) as long as a neat little 0-3 loop */ 00721 v1 = s->tone_out[0].v2; 00722 s->tone_out[0].v2 = s->tone_out[0].v3; 00723 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp; 00724 v1 = s->tone_out[1].v2; 00725 s->tone_out[1].v2 = s->tone_out[1].v3; 00726 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp; 00727 v1 = s->tone_out[2].v2; 00728 s->tone_out[2].v2 = s->tone_out[2].v3; 00729 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp; 00730 v1 = s->tone_out[3].v2; 00731 s->tone_out[3].v2 = s->tone_out[3].v3; 00732 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp; 00733 v1 = s->tone_out[4].v2; 00734 s->tone_out[4].v2 = s->tone_out[4].v3; 00735 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp; 00736 v1 = s->tone_out[5].v2; 00737 s->tone_out[5].v2 = s->tone_out[5].v3; 00738 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp; 00739 #ifdef OLD_DSP_ROUTINES 00740 v1 = s->tone_out2nd[0].v2; 00741 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3; 00742 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp; 00743 v1 = s->tone_out2nd[1].v2; 00744 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3; 00745 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp; 00746 v1 = s->tone_out2nd[2].v2; 00747 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3; 00748 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp; 00749 v1 = s->tone_out2nd[3].v2; 00750 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3; 00751 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp; 00752 v1 = s->tone_out2nd[4].v2; 00753 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3; 00754 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp; 00755 v1 = s->tone_out2nd[3].v2; 00756 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3; 00757 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp; 00758 #endif 00759 } 00760 #endif 00761 s->current_sample += (limit - sample); 00762 if (s->current_sample < MF_GSIZE) { 00763 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) { 00764 /* If we had a hit last time, go ahead and clear this out since likely it 00765 will be another hit */ 00766 for (i=sample;i<limit;i++) 00767 amp[i] = 0; 00768 *writeback = 1; 00769 } 00770 continue; 00771 } 00772 #ifdef OLD_DSP_ROUTINES 00773 /* We're at the end of an MF detection block. Go ahead and calculate 00774 all the energies. */ 00775 for (i=0;i<6;i++) { 00776 tone_energy[i] = goertzel_result(&s->tone_out[i]); 00777 } 00778 /* Find highest */ 00779 best1 = 0; 00780 max = tone_energy[0]; 00781 for (i=1;i<6;i++) { 00782 if (tone_energy[i] > max) { 00783 max = tone_energy[i]; 00784 best1 = i; 00785 } 00786 } 00787 00788 /* Find 2nd highest */ 00789 if (best1) { 00790 max = tone_energy[0]; 00791 best2 = 0; 00792 } else { 00793 max = tone_energy[1]; 00794 best2 = 1; 00795 } 00796 00797 for (i=0;i<6;i++) { 00798 if (i == best1) continue; 00799 if (tone_energy[i] > max) { 00800 max = tone_energy[i]; 00801 best2 = i; 00802 } 00803 } 00804 hit = 0; 00805 if (best1 != best2) 00806 sofarsogood=1; 00807 else 00808 sofarsogood=0; 00809 /* Check for relative energies */ 00810 for (i=0;i<6;i++) { 00811 if (i == best1) 00812 continue; 00813 if (i == best2) 00814 continue; 00815 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) { 00816 sofarsogood = 0; 00817 break; 00818 } 00819 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) { 00820 sofarsogood = 0; 00821 break; 00822 } 00823 } 00824 00825 if (sofarsogood) { 00826 /* Check for 2nd harmonic */ 00827 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1]) 00828 sofarsogood = 0; 00829 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2]) 00830 sofarsogood = 0; 00831 } 00832 if (sofarsogood) { 00833 hit = mf_hit[best1][best2]; 00834 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) { 00835 /* Zero out frame data if this is part DTMF */ 00836 for (i=sample;i<limit;i++) 00837 amp[i] = 0; 00838 *writeback = 1; 00839 } 00840 /* Look for two consecutive clean hits */ 00841 if ((hit == s->hit3) && (s->hit3 != s->hit2)) { 00842 s->mhit = hit; 00843 s->detected_digits++; 00844 if (s->current_digits < MAX_DTMF_DIGITS - 2) { 00845 s->digits[s->current_digits++] = hit; 00846 s->digits[s->current_digits] = '\0'; 00847 } else { 00848 s->lost_digits++; 00849 } 00850 } 00851 } 00852 00853 s->hit1 = s->hit2; 00854 s->hit2 = s->hit3; 00855 s->hit3 = hit; 00856 /* Reinitialise the detector for the next block */ 00857 for (i = 0; i < 6; i++) { 00858 goertzel_reset(&s->tone_out[i]); 00859 goertzel_reset(&s->tone_out2nd[i]); 00860 } 00861 s->energy = 0.0; 00862 s->current_sample = 0; 00863 } 00864 #else 00865 /* We're at the end of an MF detection block. */ 00866 /* Find the two highest energies. The spec says to look for 00867 two tones and two tones only. Taking this literally -ie 00868 only two tones pass the minimum threshold - doesn't work 00869 well. The sinc function mess, due to rectangular windowing 00870 ensure that! Find the two highest energies and ensure they 00871 are considerably stronger than any of the others. */ 00872 energy[0] = goertzel_result(&s->tone_out[0]); 00873 energy[1] = goertzel_result(&s->tone_out[1]); 00874 if (energy[0] > energy[1]) { 00875 best = 0; 00876 second_best = 1; 00877 } else { 00878 best = 1; 00879 second_best = 0; 00880 } 00881 /*endif*/ 00882 for (i=2;i<6;i++) { 00883 energy[i] = goertzel_result(&s->tone_out[i]); 00884 if (energy[i] >= energy[best]) { 00885 second_best = best; 00886 best = i; 00887 } else if (energy[i] >= energy[second_best]) { 00888 second_best = i; 00889 } 00890 } 00891 /* Basic signal level and twist tests */ 00892 hit = 0; 00893 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD 00894 && energy[best] < energy[second_best]*BELL_MF_TWIST 00895 && energy[best]*BELL_MF_TWIST > energy[second_best]) { 00896 /* Relative peak test */ 00897 hit = -1; 00898 for (i=0;i<6;i++) { 00899 if (i != best && i != second_best) { 00900 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { 00901 /* The best two are not clearly the best */ 00902 hit = 0; 00903 break; 00904 } 00905 } 00906 } 00907 } 00908 if (hit) { 00909 /* Get the values into ascending order */ 00910 if (second_best < best) { 00911 i = best; 00912 best = second_best; 00913 second_best = i; 00914 } 00915 best = best*5 + second_best - 1; 00916 hit = bell_mf_positions[best]; 00917 /* Look for two successive similar results */ 00918 /* The logic in the next test is: 00919 For KP we need 4 successive identical clean detects, with 00920 two blocks of something different preceeding it. For anything 00921 else we need two successive identical clean detects, with 00922 two blocks of something different preceeding it. */ 00923 if (hit == s->hits[4] && hit == s->hits[3] && 00924 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])|| 00925 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && 00926 hit != s->hits[0]))) { 00927 s->detected_digits++; 00928 if (s->current_digits < MAX_DTMF_DIGITS) { 00929 s->digits[s->current_digits++] = hit; 00930 s->digits[s->current_digits] = '\0'; 00931 } else { 00932 s->lost_digits++; 00933 } 00934 } 00935 } else { 00936 hit = 0; 00937 } 00938 s->hits[0] = s->hits[1]; 00939 s->hits[1] = s->hits[2]; 00940 s->hits[2] = s->hits[3]; 00941 s->hits[3] = s->hits[4]; 00942 s->hits[4] = hit; 00943 /* Reinitialise the detector for the next block */ 00944 for (i = 0; i < 6; i++) 00945 goertzel_reset(&s->tone_out[i]); 00946 s->current_sample = 0; 00947 } 00948 #endif 00949 if ((!s->mhit) || (s->mhit != hit)) { 00950 s->mhit = 0; 00951 return(0); 00952 } 00953 return (hit); 00954 }
static int pair_there | ( | float | p1, | |
float | p2, | |||
float | i1, | |||
float | i2, | |||
float | e | |||
) | [inline, static] |
Definition at line 986 of file dsp.c.
References TONE_MIN_THRESH, and TONE_THRESH.
Referenced by __ast_dsp_call_progress().
00987 { 00988 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 00989 /* Make sure absolute levels are high enough */ 00990 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 00991 return 0; 00992 /* Amplify ignored stuff */ 00993 i2 *= TONE_THRESH; 00994 i1 *= TONE_THRESH; 00995 e *= TONE_THRESH; 00996 /* Check first tone */ 00997 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 00998 return 0; 00999 /* And second */ 01000 if ((p2 < i1) || (p2 < i2) || (p2 < e)) 01001 return 0; 01002 /* Guess it's there... */ 01003 return 1; 01004 }
Referenced by add_header(), 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().