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