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_FEATURE_FAX_DETECT (1 << 4) |
| #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) |
| int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone) |
| ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf) |
| 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 23 of file dsp.h. Referenced by ast_dsp_digitmode(). |
|
|
Definition at line 24 of file dsp.h. Referenced by ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_getdigits(), and ast_dsp_process(). |
|
|
Definition at line 27 of file dsp.h. Referenced by ast_dsp_digitmode(), and ast_dsp_process(). |
|
|
Definition at line 28 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 1214 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. 01215 {
01216 if (inf->frametype != AST_FRAME_VOICE) {
01217 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01218 return 0;
01219 }
01220 if (inf->subclass != AST_FORMAT_SLINEAR) {
01221 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01222 return 0;
01223 }
01224 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01225 }
|
|
||||||||||||
|
Definition at line 1047 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. 01048 {
01049 short *s;
01050 int len;
01051 int ign=0;
01052 if (inf->frametype != AST_FRAME_VOICE) {
01053 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01054 return 0;
01055 }
01056 if (inf->subclass != AST_FORMAT_SLINEAR) {
01057 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01058 return 0;
01059 }
01060 s = inf->data;
01061 len = inf->datalen / 2;
01062 return __ast_dsp_digitdetect(dsp, s, len, &ign);
01063 }
|
|
||||||||||||
|
Definition at line 1718 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::td. 01719 {
01720 int new, old;
01721 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01722 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01723 if (old != new) {
01724 /* Must initialize structures if switching from MF to DTMF or vice-versa */
01725 if (new & DSP_DIGITMODE_MF)
01726 ast_mf_detect_init(&dsp->td.mf);
01727 else
01728 ast_dtmf_detect_init(&dsp->td.dtmf);
01729 }
01730 dsp->digitmode = digitmode;
01731 return 0;
01732 }
|
|
|
Definition at line 1657 of file dsp.c. References DSP_DIGITMODE_MF. 01658 {
01659 int i;
01660 dsp->thinkdigit = 0;
01661 if (dsp->digitmode & DSP_DIGITMODE_MF) {
01662 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01663 dsp->td.mf.current_digits = 0;
01664 /* Reinitialise the detector for the next block */
01665 for (i = 0; i < 6; i++) {
01666 goertzel_reset(&dsp->td.mf.tone_out[i]);
01667 #ifdef OLD_DSP_ROUTINES
01668 goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01669 #endif
01670 }
01671 #ifdef OLD_DSP_ROUTINES
01672 dsp->td.mf.energy = 0.0;
01673 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01674 #else
01675 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;
01676 #endif
01677 dsp->td.mf.current_sample = 0;
01678 } else {
01679 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01680 dsp->td.dtmf.current_digits = 0;
01681 /* Reinitialise the detector for the next block */
01682 for (i = 0; i < 4; i++) {
01683 goertzel_reset(&dsp->td.dtmf.row_out[i]);
01684 goertzel_reset(&dsp->td.dtmf.col_out[i]);
01685 #ifdef OLD_DSP_ROUTINES
01686 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01687 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01688 #endif
01689 }
01690 #ifdef FAX_DETECT
01691 goertzel_reset (&dsp->td.dtmf.fax_tone);
01692 #endif
01693 #ifdef OLD_DSP_ROUTINES
01694 #ifdef FAX_DETECT
01695 goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01696 #endif
01697 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01698 #else
01699 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0;
01700 #endif
01701 dsp->td.dtmf.energy = 0.0;
01702 dsp->td.dtmf.current_sample = 0;
01703 }
01704 }
|
|
|
Definition at line 1638 of file dsp.c. References free. Referenced by ast_app_getvoice(), and ast_play_and_record(). 01639 {
01640 free(dsp);
01641 }
|
|
||||||||||||||||
|
Definition at line 1085 of file dsp.c. References DSP_DIGITMODE_MF. 01088 {
01089 if (dsp->digitmode & DSP_DIGITMODE_MF) {
01090 if (max > dsp->td.mf.current_digits)
01091 max = dsp->td.mf.current_digits;
01092 if (max > 0)
01093 {
01094 memcpy (buf, dsp->td.mf.digits, max);
01095 memmove (dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01096 dsp->td.mf.current_digits -= max;
01097 }
01098 buf[max] = '\0';
01099 return max;
01100 } else {
01101 if (max > dsp->td.dtmf.current_digits)
01102 max = dsp->td.dtmf.current_digits;
01103 if (max > 0)
01104 {
01105 memcpy (buf, dsp->td.dtmf.digits, max);
01106 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01107 dsp->td.dtmf.current_digits -= max;
01108 }
01109 buf[max] = '\0';
01110 return max;
01111 }
01112 }
|
|
|
Definition at line 1616 of file dsp.c. References DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and malloc. Referenced by ast_app_getvoice(), ast_play_and_prepend(), and ast_play_and_record(). 01617 {
01618 struct ast_dsp *dsp;
01619 dsp = malloc(sizeof(struct ast_dsp));
01620 if (dsp) {
01621 memset(dsp, 0, sizeof(struct ast_dsp));
01622 dsp->threshold = DEFAULT_THRESHOLD;
01623 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01624 dsp->busycount = DSP_HISTORY;
01625 /* Initialize DTMF detector */
01626 ast_dtmf_detect_init(&dsp->td.dtmf);
01627 /* Initialize initial DSP progress detect parameters */
01628 ast_dsp_prog_reset(dsp);
01629 }
01630 return dsp;
01631 }
|
|
||||||||||||||||
|
Definition at line 1410 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_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_frame::data, ast_frame::datalen, 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, FIX_INF, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::name, and ast_frame::subclass. 01411 {
01412 int silence;
01413 int res;
01414 int digit;
01415 int x;
01416 unsigned short *shortdata;
01417 unsigned char *odata;
01418 int len;
01419 int writeback = 0;
01420
01421 #define FIX_INF(inf) do { \
01422 if (writeback) { \
01423 switch(inf->subclass) { \
01424 case AST_FORMAT_SLINEAR: \
01425 break; \
01426 case AST_FORMAT_ULAW: \
01427 for (x=0;x<len;x++) \
01428 odata[x] = AST_LIN2MU(shortdata[x]); \
01429 break; \
01430 case AST_FORMAT_ALAW: \
01431 for (x=0;x<len;x++) \
01432 odata[x] = AST_LIN2A(shortdata[x]); \
01433 break; \
01434 } \
01435 } \
01436 } while(0)
01437
01438 if (!af)
01439 return NULL;
01440 if (af->frametype != AST_FRAME_VOICE)
01441 return af;
01442 odata = af->data;
01443 len = af->datalen;
01444 /* Make sure we have short data */
01445 switch(af->subclass) {
01446 case AST_FORMAT_SLINEAR:
01447 shortdata = af->data;
01448 len = af->datalen / 2;
01449 break;
01450 case AST_FORMAT_ULAW:
01451 shortdata = alloca(af->datalen * 2);
01452 if (!shortdata) {
01453 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01454 return af;
01455 }
01456 for (x=0;x<len;x++)
01457 shortdata[x] = AST_MULAW(odata[x]);
01458 break;
01459 case AST_FORMAT_ALAW:
01460 shortdata = alloca(af->datalen * 2);
01461 if (!shortdata) {
01462 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
01463 return af;
01464 }
01465 for (x=0;x<len;x++)
01466 shortdata[x] = AST_ALAW(odata[x]);
01467 break;
01468 default:
01469 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01470 return af;
01471 }
01472 silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01473 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01474 memset(&dsp->f, 0, sizeof(dsp->f));
01475 dsp->f.frametype = AST_FRAME_NULL;
01476 return &dsp->f;
01477 }
01478 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01479 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01480 memset(&dsp->f, 0, sizeof(dsp->f));
01481 dsp->f.frametype = AST_FRAME_CONTROL;
01482 dsp->f.subclass = AST_CONTROL_BUSY;
01483 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01484 return &dsp->f;
01485 }
01486 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01487 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01488 #if 0
01489 if (digit)
01490 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01491 #endif
01492 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01493 if (!dsp->thinkdigit) {
01494 if (digit) {
01495 /* Looks like we might have something. Request a conference mute for the moment */
01496 memset(&dsp->f, 0, sizeof(dsp->f));
01497 dsp->f.frametype = AST_FRAME_DTMF;
01498 dsp->f.subclass = 'm';
01499 dsp->thinkdigit = 'x';
01500 FIX_INF(af);
01501 if (chan)
01502 ast_queue_frame(chan, af);
01503 ast_frfree(af);
01504 return &dsp->f;
01505 }
01506 } else {
01507 if (digit) {
01508 /* Thought we saw one last time. Pretty sure we really have now */
01509 if (dsp->thinkdigit) {
01510 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01511 /* If we found a digit, and we're changing digits, go
01512 ahead and send this one, but DON'T stop confmute because
01513 we're detecting something else, too... */
01514 memset(&dsp->f, 0, sizeof(dsp->f));
01515 dsp->f.frametype = AST_FRAME_DTMF;
01516 dsp->f.subclass = dsp->thinkdigit;
01517 FIX_INF(af);
01518 if (chan)
01519 ast_queue_frame(chan, af);
01520 ast_frfree(af);
01521 }
01522 dsp->thinkdigit = digit;
01523 return &dsp->f;
01524 }
01525 dsp->thinkdigit = digit;
01526 } else {
01527 if (dsp->thinkdigit) {
01528 memset(&dsp->f, 0, sizeof(dsp->f));
01529 if (dsp->thinkdigit != 'x') {
01530 /* If we found a digit, send it now */
01531 dsp->f.frametype = AST_FRAME_DTMF;
01532 dsp->f.subclass = dsp->thinkdigit;
01533 dsp->thinkdigit = 0;
01534 } else {
01535 dsp->f.frametype = AST_FRAME_DTMF;
01536 dsp->f.subclass = 'u';
01537 dsp->thinkdigit = 0;
01538 }
01539 FIX_INF(af);
01540 if (chan)
01541 ast_queue_frame(chan, af);
01542 ast_frfree(af);
01543 return &dsp->f;
01544 }
01545 }
01546 }
01547 } else if (!digit) {
01548 /* Only check when there is *not* a hit... */
01549 if (dsp->digitmode & DSP_DIGITMODE_MF) {
01550 if (dsp->td.mf.current_digits) {
01551 memset(&dsp->f, 0, sizeof(dsp->f));
01552 dsp->f.frametype = AST_FRAME_DTMF;
01553 dsp->f.subclass = dsp->td.mf.digits[0];
01554 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01555 dsp->td.mf.current_digits--;
01556 FIX_INF(af);
01557 if (chan)
01558 ast_queue_frame(chan, af);
01559 ast_frfree(af);
01560 return &dsp->f;
01561 }
01562 } else {
01563 if (dsp->td.dtmf.current_digits) {
01564 memset(&dsp->f, 0, sizeof(dsp->f));
01565 dsp->f.frametype = AST_FRAME_DTMF;
01566 dsp->f.subclass = dsp->td.dtmf.digits[0];
01567 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01568 dsp->td.dtmf.current_digits--;
01569 FIX_INF(af);
01570 if (chan)
01571 ast_queue_frame(chan, af);
01572 ast_frfree(af);
01573 return &dsp->f;
01574 }
01575 }
01576 }
01577 }
01578 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01579 res = __ast_dsp_call_progress(dsp, shortdata, len);
01580 memset(&dsp->f, 0, sizeof(dsp->f));
01581 dsp->f.frametype = AST_FRAME_CONTROL;
01582 if (res) {
01583 switch(res) {
01584 case AST_CONTROL_ANSWER:
01585 case AST_CONTROL_BUSY:
01586 case AST_CONTROL_RINGING:
01587 case AST_CONTROL_CONGESTION:
01588 dsp->f.subclass = res;
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 1706 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. 01707 {
01708 int x;
01709 dsp->totalsilence = 0;
01710 dsp->gsamps = 0;
01711 for (x=0;x<4;x++)
01712 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01713 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01714 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01715
01716 }
|
|
||||||||||||
|
Definition at line 1648 of file dsp.c. References ast_dsp::busycount, and DSP_HISTORY. 01649 {
01650 if (cadences < 4)
01651 cadences = 4;
01652 if (cadences > DSP_HISTORY)
01653 cadences = DSP_HISTORY;
01654 dsp->busycount = cadences;
01655 }
|
|
||||||||||||
|
Definition at line 1734 of file dsp.c. References ast_dsp::progmode. 01735 {
01736 int x;
01737 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01738 if (!strcasecmp(aliases[x].name, zone)) {
01739 dsp->progmode = aliases[x].mode;
01740 ast_dsp_prog_reset(dsp);
01741 return 0;
01742 }
01743 }
01744 return -1;
01745 }
|
|
||||||||||||
|
Definition at line 1633 of file dsp.c. References ast_dsp::features.
|
|
||||||||||||
|
Definition at line 1643 of file dsp.c. References ast_dsp::threshold. Referenced by ast_play_and_prepend(), and ast_play_and_record().
|
|
||||||||||||||||
|
Definition at line 1392 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(), ast_play_and_prepend(), and ast_play_and_record(). 01393 {
01394 short *s;
01395 int len;
01396
01397 if (f->frametype != AST_FRAME_VOICE) {
01398 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01399 return 0;
01400 }
01401 if (f->subclass != AST_FORMAT_SLINEAR) {
01402 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01403 return 0;
01404 }
01405 s = f->data;
01406 len = f->datalen/2;
01407 return __ast_dsp_silence(dsp, s, len, totalsilence);
01408 }
|
1.4.2