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 /* Detect DTMF digits */ |
#define | DSP_DIGITMODE_MF 1 /* Detect MF digits */ |
#define | DSP_DIGITMODE_NOQUELCH (1 << 8) /* Do not quelch DTMF from in-band */ |
#define | DSP_DIGITMODE_MUTECONF (1 << 9) /* Mute conference */ |
#define | DSP_DIGITMODE_MUTEMAX (1 << 10) /* Delay audio by a frame to try to extra quelch */ |
#define | DSP_DIGITMODE_RELAXDTMF (1 << 11) /* "Radio" mode (relaxed DTMF) */ |
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_reset(). |
|
Definition at line 24 of file dsp.h. Referenced by ast_dsp_reset(), and ast_dsp_set_threshold(). |
|
Definition at line 29 of file dsp.h. Referenced by ast_dsp_reset(). |
|
Definition at line 31 of file dsp.h. Referenced by ast_dsp_reset(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 1216 of file dsp.c. References DSP_HISTORY.
01223 { 01224 dsp->totalsilence += len/8; 01225 if (dsp->totalnoise) { 01226 /* Move and save history */ 01227 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); |
|
Definition at line 1048 of file dsp.c.
01051 { 01052 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ 01053 /* Make sure absolute levels are high enough */ 01054 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) 01055 return 0; 01056 /* Amplify ignored stuff */ 01057 i2 *= TONE_THRESH; 01058 i1 *= TONE_THRESH; 01059 e *= TONE_THRESH; 01060 /* Check first tone */ 01061 if ((p1 < i1) || (p1 < i2) || (p1 < e)) 01062 return 0; 01063 /* And second */ 01064 if ((p2 < i1) || (p2 < i2) || (p2 < e)) |
|
|
|
Definition at line 1647 of file dsp.c.
01652 { 01653 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01654 dsp->td.dtmf.current_digits = 0; 01655 /* Reinitialise the detector for the next block */ 01656 for (i = 0; i < 4; i++) { 01657 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01658 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01659 #ifdef OLD_DSP_ROUTINES 01660 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01661 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01662 #endif 01663 } 01664 #ifdef FAX_DETECT 01665 goertzel_reset (&dsp->td.dtmf.fax_tone); 01666 #endif 01667 #ifdef OLD_DSP_ROUTINES 01668 #ifdef FAX_DETECT 01669 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01670 #endif 01671 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01672 #else 01673 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0; 01674 #endif 01675 dsp->td.dtmf.energy = 0.0; 01676 dsp->td.dtmf.current_sample = 0; 01677 } 01678 } 01679 01680 void ast_dsp_reset(struct ast_dsp *dsp) 01681 { 01682 int x; 01683 dsp->totalsilence = 0; 01684 dsp->gsamps = 0; 01685 for (x=0;x<4;x++) 01686 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01687 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01688 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01689 01690 } 01691 01692 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode) 01693 { 01694 int new, old; |
|
Definition at line 1628 of file dsp.c. Referenced by ast_app_getvoice().
01632 { |
|
Definition at line 1086 of file dsp.c. References ast_dsp::td.
01089 { 01090 memcpy (buf, dsp->td.dtmf.digits, max); 01091 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01092 dsp->td.dtmf.current_digits -= max; 01093 } 01094 buf[max] = '\0'; 01095 return max; 01096 } 01097 } 01098 01099 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) 01100 { 01101 int x; 01102 int pass; 01103 int newstate = TONE_STATE_SILENCE; 01104 int res = 0; 01105 while(len) { 01106 /* Take the lesser of the number of samples we need and what we have */ 01107 pass = len; 01108 if (pass > GSAMP_SIZE - dsp->gsamps) 01109 pass = GSAMP_SIZE - dsp->gsamps; 01110 for (x=0;x<pass;x++) { 01111 goertzel_sample(&dsp->freqs[HZ_350], s[x]); 01112 goertzel_sample(&dsp->freqs[HZ_440], s[x]); 01113 goertzel_sample(&dsp->freqs[HZ_480], s[x]); |
|
Definition at line 1600 of file dsp.c. Referenced by ast_app_getvoice().
01608 { 01609 dsp->features = features; 01610 } 01611 01612 void ast_dsp_free(struct ast_dsp *dsp) 01613 { 01614 free(dsp); 01615 } 01616 01617 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold) 01618 { 01619 dsp->threshold = threshold; 01620 } 01621 |
|
Definition at line 1409 of file dsp.c. References AST_ALAW, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_VOICE, ast_log(), AST_MULAW, ast_frame::data, ast_frame::datalen, LOG_WARNING, and ast_frame::subclass.
01409 : \ 01410 for (x=0;x<len;x++) \ 01411 odata[x] = AST_LIN2MU(shortdata[x]); \ 01412 break; \ 01413 case AST_FORMAT_ALAW: \ 01414 for (x=0;x<len;x++) \ 01415 odata[x] = AST_LIN2A(shortdata[x]); \ 01416 break; \ 01417 } \ 01418 } \ 01419 } while(0) 01420 01421 if (!af) 01422 return NULL; 01423 if (af->frametype != AST_FRAME_VOICE) 01424 return af; 01425 odata = af->data; 01426 len = af->datalen; 01427 /* Make sure we have short data */ 01428 switch(af->subclass) { 01429 case AST_FORMAT_SLINEAR: 01430 shortdata = af->data; 01431 len = af->datalen / 2; 01432 break; 01433 case AST_FORMAT_ULAW: 01434 shortdata = alloca(af->datalen * 2); 01435 if (!shortdata) { 01436 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01437 return af; 01438 } 01439 for (x=0;x<len;x++) 01440 shortdata[x] = AST_MULAW(odata[x]); 01441 break; 01442 case AST_FORMAT_ALAW: 01443 shortdata = alloca(af->datalen * 2); 01444 if (!shortdata) { 01445 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01446 return af; 01447 } 01448 for (x=0;x<len;x++) 01449 shortdata[x] = AST_ALAW(odata[x]); 01450 break; 01451 default: 01452 ast_log(LOG_WARNING, "Unable to process inband DTMF on %d frames\n", af->subclass); 01453 return af; 01454 } 01455 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01456 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01457 memset(&dsp->f, 0, sizeof(dsp->f)); 01458 dsp->f.frametype = AST_FRAME_NULL; 01459 return &dsp->f; 01460 } 01461 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01462 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01463 memset(&dsp->f, 0, sizeof(dsp->f)); 01464 dsp->f.frametype = AST_FRAME_CONTROL; 01465 dsp->f.subclass = AST_CONTROL_BUSY; 01466 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01467 return &dsp->f; 01468 } 01469 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01470 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01471 #if 0 01472 if (digit) 01473 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01474 #endif 01475 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01476 if (!dsp->thinkdigit) { 01477 if (digit) { 01478 /* Looks like we might have something. Request a conference mute for the moment */ 01479 memset(&dsp->f, 0, sizeof(dsp->f)); 01480 dsp->f.frametype = AST_FRAME_DTMF; 01481 dsp->f.subclass = 'm'; 01482 dsp->thinkdigit = 'x'; 01483 FIX_INF(af); 01484 if (chan) 01485 ast_queue_frame(chan, af, needlock); 01486 ast_frfree(af); 01487 return &dsp->f; 01488 } 01489 } else { 01490 if (digit) { 01491 /* Thought we saw one last time. Pretty sure we really have now */ 01492 if (dsp->thinkdigit) { 01493 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01494 /* If we found a digit, and we're changing digits, go 01495 ahead and send this one, but DON'T stop confmute because 01496 we're detecting something else, too... */ 01497 memset(&dsp->f, 0, sizeof(dsp->f)); 01498 dsp->f.frametype = AST_FRAME_DTMF; 01499 dsp->f.subclass = dsp->thinkdigit; 01500 FIX_INF(af); 01501 if (chan) 01502 ast_queue_frame(chan, af, needlock); 01503 ast_frfree(af); 01504 } 01505 dsp->thinkdigit = digit; 01506 return &dsp->f; 01507 } 01508 dsp->thinkdigit = digit; 01509 } else { 01510 if (dsp->thinkdigit) { 01511 memset(&dsp->f, 0, sizeof(dsp->f)); 01512 if (dsp->thinkdigit != 'x') { 01513 /* If we found a digit, send it now */ 01514 dsp->f.frametype = AST_FRAME_DTMF; 01515 dsp->f.subclass = dsp->thinkdigit; 01516 dsp->thinkdigit = 0; 01517 } else { 01518 dsp->f.frametype = AST_FRAME_DTMF; 01519 dsp->f.subclass = 'u'; 01520 dsp->thinkdigit = 0; 01521 } 01522 FIX_INF(af); 01523 if (chan) 01524 ast_queue_frame(chan, af, needlock); 01525 ast_frfree(af); 01526 return &dsp->f; 01527 } 01528 } 01529 } 01530 } else if (!digit) { 01531 /* Only check when there is *not* a hit... */ 01532 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01533 if (dsp->td.mf.current_digits) { 01534 memset(&dsp->f, 0, sizeof(dsp->f)); 01535 dsp->f.frametype = AST_FRAME_DTMF; 01536 dsp->f.subclass = dsp->td.mf.digits[0]; 01537 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01538 dsp->td.mf.current_digits--; 01539 FIX_INF(af); 01540 if (chan) 01541 ast_queue_frame(chan, af, needlock); 01542 ast_frfree(af); 01543 return &dsp->f; 01544 } 01545 } else { 01546 if (dsp->td.dtmf.current_digits) { 01547 memset(&dsp->f, 0, sizeof(dsp->f)); 01548 dsp->f.frametype = AST_FRAME_DTMF; 01549 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01550 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01551 dsp->td.dtmf.current_digits--; 01552 FIX_INF(af); 01553 if (chan) 01554 ast_queue_frame(chan, af, needlock); 01555 ast_frfree(af); 01556 return &dsp->f; 01557 } 01558 } 01559 } 01560 } 01561 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01562 res = __ast_dsp_call_progress(dsp, shortdata, len); 01563 memset(&dsp->f, 0, sizeof(dsp->f)); 01564 dsp->f.frametype = AST_FRAME_CONTROL; 01565 if (res) { 01566 switch(res) { 01567 case AST_CONTROL_ANSWER: 01568 case AST_CONTROL_BUSY: 01569 case AST_CONTROL_RINGING: 01570 case AST_CONTROL_CONGESTION: 01571 dsp->f.subclass = res; 01572 if (chan) 01573 ast_queue_frame(chan, &dsp->f, needlock); 01574 break; 01575 default: 01576 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01577 } 01578 } 01579 } 01580 FIX_INF(af); 01581 return af; 01582 } 01583 01584 struct ast_dsp *ast_dsp_new(void) 01585 { 01586 struct ast_dsp *dsp; 01587 dsp = malloc(sizeof(struct ast_dsp)); 01588 if (dsp) { 01589 memset(dsp, 0, sizeof(struct ast_dsp)); 01590 dsp->threshold = DEFAULT_THRESHOLD; 01591 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01592 dsp->busycount = DSP_HISTORY; 01593 /* Initialize goertzels */ 01594 goertzel_init(&dsp->freqs[HZ_350], 350.0, GSAMP_SIZE); 01595 goertzel_init(&dsp->freqs[HZ_440], 440.0, GSAMP_SIZE); 01596 goertzel_init(&dsp->freqs[HZ_480], 480.0, GSAMP_SIZE); 01597 goertzel_init(&dsp->freqs[HZ_620], 620.0, GSAMP_SIZE); 01598 goertzel_init(&dsp->freqs[HZ_950], 950.0, GSAMP_SIZE); |
|
Definition at line 1696 of file dsp.c. References DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::td.
01697 { 01698 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01699 if (new & DSP_DIGITMODE_MF) 01700 ast_mf_detect_init(&dsp->td.mf); 01701 else 01702 ast_dtmf_detect_init(&dsp->td.dtmf); 01703 } 01704 dsp->digitmode = digitmode; 01705 return 0; 01706 } |
|
Definition at line 1638 of file dsp.c. References ast_dsp::td.
|
|
Definition at line 1623 of file dsp.c. References DSP_HISTORY.
01623 { 01624 if (cadences < 4) 01625 cadences = 4; 01626 if (cadences > DSP_HISTORY) |
|
Definition at line 1633 of file dsp.c. References DSP_DIGITMODE_MF, and ast_dsp::td.
|
|
Definition at line 1391 of file dsp.c. Referenced by ast_app_getvoice().
01394 { 01395 int silence; 01396 int res; 01397 int digit; 01398 int x; 01399 unsigned short *shortdata; 01400 unsigned char *odata; 01401 int len; 01402 int writeback = 0; 01403 01404 #define FIX_INF(inf) do { \ 01405 if (writeback) { \ 01406 switch(inf->subclass) { \ 01407 case AST_FORMAT_SLINEAR: \ |