Go to the source code of this file.
Defines | |
#define | DSP_FEATURE_SILENCE_SUPPRESS (1 << 0) |
#define | DSP_FEATURE_BUSY_DETECT (1 << 1) |
#define | DSP_FEATURE_CALL_PROGRESS (1 << 2) |
#define | DSP_FEATURE_DTMF_DETECT (1 << 3) |
#define | DSP_DIGITMODE_DTMF 0 |
#define | DSP_DIGITMODE_MF 1 |
#define | DSP_DIGITMODE_NOQUELCH (1 << 8) |
#define | DSP_DIGITMODE_MUTECONF (1 << 9) |
#define | DSP_DIGITMODE_MUTEMAX (1 << 10) |
#define | DSP_DIGITMODE_RELAXDTMF (1 << 11) |
Functions | |
ast_dsp * | ast_dsp_new (void) |
void | ast_dsp_free (struct ast_dsp *dsp) |
void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold) |
void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences) |
int | ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf) |
ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf, int needlock) |
int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
int | ast_dsp_busydetect (struct ast_dsp *dsp) |
int | ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *f) |
void | ast_dsp_reset (struct ast_dsp *dsp) |
void | ast_dsp_digitreset (struct ast_dsp *dsp) |
void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
int | ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max) |
int | ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode) |
|
Definition at line 22 of file dsp.h. Referenced by ast_dsp_digitmode(). |
|
Definition at line 23 of file dsp.h. Referenced by ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_getdigits(), and ast_dsp_process(). |
|
Definition at line 26 of file dsp.h. Referenced by ast_dsp_digitmode(), and ast_dsp_process(). |
|
Definition at line 27 of file dsp.h. Referenced by ast_dsp_digitmode(), and ast_dsp_process(). |
|
|
|
|
|
Definition at line 18 of file dsp.h. Referenced by ast_dsp_process(). |
|
Definition at line 19 of file dsp.h. Referenced by ast_dsp_process(). |
|
Definition at line 20 of file dsp.h. Referenced by ast_dsp_process(). |
|
Definition at line 17 of file dsp.h. Referenced by ast_dsp_new(), and ast_dsp_process(). |
|
Referenced by ast_dsp_process(). |
|
Definition at line 946 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.
00947 { 00948 if (inf->frametype != AST_FRAME_VOICE) { 00949 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00950 return 0; 00951 } 00952 if (inf->subclass != AST_FORMAT_SLINEAR) { 00953 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00954 return 0; 00955 } 00956 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 00957 } |
|
Definition at line 778 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.
00779 { 00780 short *s; 00781 int len; 00782 int ign=0; 00783 if (inf->frametype != AST_FRAME_VOICE) { 00784 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 00785 return 0; 00786 } 00787 if (inf->subclass != AST_FORMAT_SLINEAR) { 00788 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 00789 return 0; 00790 } 00791 s = inf->data; 00792 len = inf->datalen / 2; 00793 return __ast_dsp_digitdetect(dsp, s, len, &ign); 00794 } |
|
Definition at line 1422 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::td.
01423 { 01424 int new, old; 01425 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01426 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01427 if (old != new) { 01428 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01429 if (new & DSP_DIGITMODE_MF) 01430 ast_mf_detect_init(&dsp->td.mf); 01431 else 01432 ast_dtmf_detect_init(&dsp->td.dtmf); 01433 } 01434 dsp->digitmode = digitmode; 01435 return 0; 01436 } |
|
Definition at line 1377 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_MF, ast_dsp::td, and ast_dsp::thinkdigit.
01378 { 01379 int i; 01380 dsp->thinkdigit = 0; 01381 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01382 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01383 dsp->td.mf.current_digits = 0; 01384 /* Reinitialise the detector for the next block */ 01385 for (i = 0; i < 6; i++) { 01386 goertzel_reset(&dsp->td.mf.tone_out[i]); 01387 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01388 } 01389 dsp->td.mf.energy = 0.0; 01390 dsp->td.mf.current_sample = 0; 01391 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01392 } else { 01393 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01394 dsp->td.dtmf.current_digits = 0; 01395 /* Reinitialise the detector for the next block */ 01396 for (i = 0; i < 4; i++) { 01397 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01398 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01399 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01400 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01401 } 01402 goertzel_reset (&dsp->td.dtmf.fax_tone); 01403 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01404 dsp->td.dtmf.energy = 0.0; 01405 dsp->td.dtmf.current_sample = 0; 01406 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01407 } 01408 } |
|
Definition at line 1358 of file dsp.c. References free. Referenced by ast_app_getvoice().
01359 { 01360 free(dsp); 01361 } |
|
Definition at line 816 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_MF, and ast_dsp::td.
00819 { 00820 if (dsp->digitmode & DSP_DIGITMODE_MF) { 00821 if (max > dsp->td.mf.current_digits) 00822 max = dsp->td.mf.current_digits; 00823 if (max > 0) 00824 { 00825 memcpy (buf, dsp->td.mf.digits, max); 00826 memmove (dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 00827 dsp->td.mf.current_digits -= max; 00828 } 00829 buf[max] = '\0'; 00830 return max; 00831 } else { 00832 if (max > dsp->td.dtmf.current_digits) 00833 max = dsp->td.dtmf.current_digits; 00834 if (max > 0) 00835 { 00836 memcpy (buf, dsp->td.dtmf.digits, max); 00837 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 00838 dsp->td.dtmf.current_digits -= max; 00839 } 00840 buf[max] = '\0'; 00841 return max; 00842 } 00843 } |
|
Definition at line 1330 of file dsp.c. References ast_dsp::busycount, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::features, ast_dsp::freqs, HZ_1400, HZ_1800, HZ_350, HZ_440, HZ_480, HZ_620, HZ_950, malloc, ast_dsp::td, and ast_dsp::threshold. Referenced by ast_app_getvoice().
01331 { 01332 struct ast_dsp *dsp; 01333 dsp = malloc(sizeof(struct ast_dsp)); 01334 if (dsp) { 01335 memset(dsp, 0, sizeof(struct ast_dsp)); 01336 dsp->threshold = DEFAULT_THRESHOLD; 01337 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01338 dsp->busycount = DSP_HISTORY; 01339 /* Initialize goertzels */ 01340 goertzel_init(&dsp->freqs[HZ_350], 350.0); 01341 goertzel_init(&dsp->freqs[HZ_440], 440.0); 01342 goertzel_init(&dsp->freqs[HZ_480], 480.0); 01343 goertzel_init(&dsp->freqs[HZ_620], 620.0); 01344 goertzel_init(&dsp->freqs[HZ_950], 950.0); 01345 goertzel_init(&dsp->freqs[HZ_1400], 1400.0); 01346 goertzel_init(&dsp->freqs[HZ_1800], 1800.0); 01347 /* Initialize DTMF detector */ 01348 ast_dtmf_detect_init(&dsp->td.dtmf); 01349 } 01350 return dsp; 01351 } |
|
Definition at line 1139 of file dsp.c. References ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, 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_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, 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::f, ast_dsp::features, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.
01140 { 01141 int silence; 01142 int res; 01143 int digit; 01144 int x; 01145 unsigned short *shortdata; 01146 unsigned char *odata; 01147 int len; 01148 int writeback = 0; 01149 01150 #define FIX_INF(inf) do { \ 01151 if (writeback) { \ 01152 switch(inf->subclass) { \ 01153 case AST_FORMAT_SLINEAR: \ 01154 break; \ 01155 case AST_FORMAT_ULAW: \ 01156 for (x=0;x<len;x++) \ 01157 odata[x] = AST_LIN2MU(shortdata[x]); \ 01158 break; \ 01159 case AST_FORMAT_ALAW: \ 01160 for (x=0;x<len;x++) \ 01161 odata[x] = AST_LIN2A(shortdata[x]); \ 01162 break; \ 01163 } \ 01164 } \ 01165 } while(0) 01166 01167 if (!af) 01168 return NULL; 01169 if (af->frametype != AST_FRAME_VOICE) 01170 return af; 01171 odata = af->data; 01172 len = af->datalen; 01173 /* Make sure we have short data */ 01174 switch(af->subclass) { 01175 case AST_FORMAT_SLINEAR: 01176 shortdata = af->data; 01177 len = af->datalen / 2; 01178 break; 01179 case AST_FORMAT_ULAW: 01180 shortdata = alloca(af->datalen * 2); 01181 if (!shortdata) { 01182 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01183 return af; 01184 } 01185 for (x=0;x<len;x++) 01186 shortdata[x] = AST_MULAW(odata[x]); 01187 break; 01188 case AST_FORMAT_ALAW: 01189 shortdata = alloca(af->datalen * 2); 01190 if (!shortdata) { 01191 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01192 return af; 01193 } 01194 for (x=0;x<len;x++) 01195 shortdata[x] = AST_ALAW(odata[x]); 01196 break; 01197 default: 01198 ast_log(LOG_WARNING, "Unable to detect process %d frames\n", af->subclass); 01199 return af; 01200 } 01201 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01202 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01203 memset(&dsp->f, 0, sizeof(dsp->f)); 01204 dsp->f.frametype = AST_FRAME_NULL; 01205 return &dsp->f; 01206 } 01207 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01208 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01209 memset(&dsp->f, 0, sizeof(dsp->f)); 01210 dsp->f.frametype = AST_FRAME_CONTROL; 01211 dsp->f.subclass = AST_CONTROL_BUSY; 01212 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01213 return &dsp->f; 01214 } 01215 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01216 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01217 #if 0 01218 if (digit) 01219 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01220 #endif 01221 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01222 if (!dsp->thinkdigit) { 01223 if (digit) { 01224 /* Looks like we might have something. Request a conference mute for the moment */ 01225 memset(&dsp->f, 0, sizeof(dsp->f)); 01226 dsp->f.frametype = AST_FRAME_DTMF; 01227 dsp->f.subclass = 'm'; 01228 dsp->thinkdigit = 'x'; 01229 FIX_INF(af); 01230 if (chan) 01231 ast_queue_frame(chan, af, needlock); 01232 ast_frfree(af); 01233 return &dsp->f; 01234 } 01235 } else { 01236 if (digit) { 01237 /* Thought we saw one last time. Pretty sure we really have now */ 01238 if (dsp->thinkdigit) { 01239 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01240 /* If we found a digit, and we're changing digits, go 01241 ahead and send this one, but DON'T stop confmute because 01242 we're detecting something else, too... */ 01243 memset(&dsp->f, 0, sizeof(dsp->f)); 01244 dsp->f.frametype = AST_FRAME_DTMF; 01245 dsp->f.subclass = dsp->thinkdigit; 01246 FIX_INF(af); 01247 if (chan) 01248 ast_queue_frame(chan, af, needlock); 01249 ast_frfree(af); 01250 } 01251 dsp->thinkdigit = digit; 01252 return &dsp->f; 01253 } 01254 dsp->thinkdigit = digit; 01255 } else { 01256 if (dsp->thinkdigit) { 01257 memset(&dsp->f, 0, sizeof(dsp->f)); 01258 if (dsp->thinkdigit != 'x') { 01259 /* If we found a digit, send it now */ 01260 dsp->f.frametype = AST_FRAME_DTMF; 01261 dsp->f.subclass = dsp->thinkdigit; 01262 dsp->thinkdigit = 0; 01263 } else { 01264 dsp->f.frametype = AST_FRAME_DTMF; 01265 dsp->f.subclass = 'u'; 01266 dsp->thinkdigit = 0; 01267 } 01268 FIX_INF(af); 01269 if (chan) 01270 ast_queue_frame(chan, af, needlock); 01271 ast_frfree(af); 01272 return &dsp->f; 01273 } 01274 } 01275 } 01276 } else if (!digit) { 01277 /* Only check when there is *not* a hit... */ 01278 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01279 if (dsp->td.mf.current_digits) { 01280 memset(&dsp->f, 0, sizeof(dsp->f)); 01281 dsp->f.frametype = AST_FRAME_DTMF; 01282 dsp->f.subclass = dsp->td.mf.digits[0]; 01283 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01284 dsp->td.mf.current_digits--; 01285 FIX_INF(af); 01286 if (chan) 01287 ast_queue_frame(chan, af, needlock); 01288 ast_frfree(af); 01289 return &dsp->f; 01290 } 01291 } else { 01292 if (dsp->td.dtmf.current_digits) { 01293 memset(&dsp->f, 0, sizeof(dsp->f)); 01294 dsp->f.frametype = AST_FRAME_DTMF; 01295 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01296 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01297 dsp->td.dtmf.current_digits--; 01298 FIX_INF(af); 01299 if (chan) 01300 ast_queue_frame(chan, af, needlock); 01301 ast_frfree(af); 01302 return &dsp->f; 01303 } 01304 } 01305 } 01306 } 01307 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01308 res = __ast_dsp_call_progress(dsp, shortdata, len); 01309 memset(&dsp->f, 0, sizeof(dsp->f)); 01310 dsp->f.frametype = AST_FRAME_CONTROL; 01311 if (res) { 01312 switch(res) { 01313 case AST_CONTROL_ANSWER: 01314 case AST_CONTROL_BUSY: 01315 case AST_CONTROL_RINGING: 01316 case AST_CONTROL_CONGESTION: 01317 dsp->f.subclass = res; 01318 if (chan) 01319 ast_queue_frame(chan, &dsp->f, needlock); 01320 break; 01321 default: 01322 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01323 } 01324 } 01325 } 01326 FIX_INF(af); 01327 return af; 01328 } |
|
Definition at line 1410 of file dsp.c. References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.
01411 { 01412 int x; 01413 dsp->totalsilence = 0; 01414 dsp->gsamps = 0; 01415 for (x=0;x<4;x++) 01416 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01417 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01418 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01419 01420 } |
|
Definition at line 1368 of file dsp.c. References ast_dsp::busycount, and DSP_HISTORY.
01369 { 01370 if (cadences < 4) 01371 cadences = 4; 01372 if (cadences > DSP_HISTORY) 01373 cadences = DSP_HISTORY; 01374 dsp->busycount = cadences; 01375 } |
|
Definition at line 1353 of file dsp.c. References ast_dsp::features.
01354 { 01355 dsp->features = features; 01356 } |
|
Definition at line 1363 of file dsp.c. References ast_dsp::threshold.
01364 { 01365 dsp->threshold = threshold; 01366 } |
|
Definition at line 1121 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass. Referenced by ast_app_getvoice().
01122 { 01123 short *s; 01124 int len; 01125 01126 if (f->frametype != AST_FRAME_VOICE) { 01127 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01128 return 0; 01129 } 01130 if (f->subclass != AST_FORMAT_SLINEAR) { 01131 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01132 return 0; 01133 } 01134 s = f->data; 01135 len = f->datalen/2; 01136 return __ast_dsp_silence(dsp, s, len, totalsilence); 01137 } |