| r3029 | r3164 | |
| 50 | 50 | /* Number of goertzels for progress detect */ |
| 51 | 51 | #define GSAMP_SIZE_NA 183 /* North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ |
| 52 | 52 | #define GSAMP_SIZE_CR 188 /* Costa Rica, Brazil - Only care about 425 Hz */ |
| 53 | | #define GSAMP_SIZE_UK 160 /* UK disconnect goertzel feed - should trigger 400hz */ |
| 53 | #define GSAMP_SIZE_UK 160 /* UK disconnect goertzel feed - should trigger 400Hz */ |
| 54 | 54 | |
| 55 | 55 | #define PROG_MODE_NA 0 |
| 56 | 56 | #define PROG_MODE_CR 1 |
| --- | --- | |
| 122 | 122 | int totalsilence; |
| 123 | 123 | int totalnoise; |
| 124 | 124 | int features; |
| 125 | | int busymaybe; |
| 125 | int busy_maybe; |
| 126 | 126 | int busycount; |
| 127 | 127 | int busy_tonelength; |
| 128 | 128 | int busy_quietlength; |
| --- | --- | |
| 140 | 140 | int mute_lag; |
| 141 | 141 | float genergy; |
| 142 | 142 | dtmf_rx_state_t dtmf_rx; |
| 143 | modem_connect_tones_rx_state_t fax_ced_rx; |
| 143 | 144 | modem_connect_tones_rx_state_t fax_cng_rx; |
| 144 | 145 | bell_mf_rx_state_t bell_mf_rx; |
| 145 | 146 | }; |
| --- | --- | |
| 164 | 165 | return 1; |
| 165 | 166 | } |
| 166 | 167 | |
| 167 | | static int __opbx_dsp_call_progress(struct opbx_dsp *dsp, short *s, int len) |
| 168 | static int __opbx_dsp_call_progress(struct opbx_dsp *dsp, int16_t *s, int len) |
| 168 | 169 | { |
| 169 | 170 | int x; |
| 170 | 171 | int y; |
| --- | --- | |
| 235 | 236 | newstate = DSP_TONE_STATE_TALKING; |
| 236 | 237 | } |
| 237 | 238 | else |
| 239 | { |
| 238 | 240 | newstate = DSP_TONE_STATE_SILENCE; |
| 241 | } |
| 239 | 242 | break; |
| 240 | 243 | case PROG_MODE_CR: |
| 241 | 244 | if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) |
| --- | --- | |
| 324 | 327 | return __opbx_dsp_call_progress(dsp, inf->data, inf->datalen / 2); |
| 325 | 328 | } |
| 326 | 329 | |
| 327 | | static int __opbx_dsp_silence(struct opbx_dsp *dsp, short *s, int len, int *totalsilence) |
| 330 | static int __opbx_dsp_silence(struct opbx_dsp *dsp, int16_t amp[], int len, int *totalsilence) |
| 328 | 331 | { |
| 329 | 332 | int accum; |
| 330 | 333 | int x; |
| 331 | | int res = 0; |
| 334 | int res; |
| 332 | 335 | |
| 333 | 336 | if (!len) |
| 334 | 337 | return 0; |
| 335 | 338 | accum = 0; |
| 336 | 339 | for (x = 0; x < len; x++) |
| 337 | | accum += abs(s[x]); |
| 340 | accum += abs(amp[x]); |
| 338 | 341 | accum /= len; |
| 339 | 342 | if (accum < dsp->threshold) |
| 340 | 343 | { |
| --- | --- | |
| 345 | 348 | /* Move and save history */ |
| 346 | 349 | memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0])); |
| 347 | 350 | dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise; |
| 348 | | /* we don't want to check for busydetect that frequently */ |
| 351 | /* We don't want to check for busydetect that frequently */ |
| 349 | 352 | } |
| 350 | 353 | dsp->totalnoise = 0; |
| 351 | | res = 1; |
| 354 | res = TRUE; |
| 352 | 355 | } |
| 353 | 356 | else |
| 354 | 357 | { |
| --- | --- | |
| 363 | 366 | dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence; |
| 364 | 367 | /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ |
| 365 | 368 | if (silence1 < silence2) |
| 366 | | { |
| 367 | | if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) |
| 368 | | dsp->busymaybe = 1; |
| 369 | | else |
| 370 | | dsp->busymaybe = 0; |
| 371 | | } |
| 369 | dsp->busy_maybe = (silence1 + silence1*BUSY_PERCENT/100 >= silence2); |
| 372 | 370 | else |
| 373 | | { |
| 374 | | if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) |
| 375 | | dsp->busymaybe = 1; |
| 376 | | else |
| 377 | | dsp->busymaybe = 0; |
| 378 | | } |
| 371 | dsp->busy_maybe = (silence1 - silence1*BUSY_PERCENT/100 <= silence2); |
| 379 | 372 | } |
| 380 | 373 | dsp->totalsilence = 0; |
| 374 | res = FALSE; |
| 381 | 375 | } |
| 382 | 376 | if (totalsilence) |
| 383 | 377 | *totalsilence = dsp->totalsilence; |
| --- | --- | |
| 396 | 390 | int avgtone = 0; |
| 397 | 391 | int hittone = 0; |
| 398 | 392 | |
| 399 | | if (!dsp->busymaybe) |
| 393 | if (!dsp->busy_maybe) |
| 400 | 394 | return res; |
| 401 | 395 | for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) |
| 402 | 396 | { |
| --- | --- | |
| 494 | 488 | int min; |
| 495 | 489 | |
| 496 | 490 | res = 0; |
| 497 | | if (dsp->busymaybe) |
| 491 | if (dsp->busy_maybe) |
| 498 | 492 | { |
| 499 | | dsp->busymaybe = 0; |
| 493 | dsp->busy_maybe = FALSE; |
| 500 | 494 | min = 9999; |
| 501 | 495 | max = 0; |
| 502 | 496 | for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) |
| --- | --- | |
| 519 | 513 | |
| 520 | 514 | int opbx_dsp_silence(struct opbx_dsp *dsp, struct opbx_frame *f, int *totalsilence) |
| 521 | 515 | { |
| 522 | | short *s; |
| 516 | int16_t *amp; |
| 517 | uint8_t *data; |
| 523 | 518 | int len; |
| 524 | | |
| 519 | int x; |
| 520 | |
| 525 | 521 | if (f->frametype != OPBX_FRAME_VOICE) |
| 526 | 522 | { |
| 527 | 523 | opbx_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); |
| 528 | 524 | return 0; |
| 529 | 525 | } |
| 530 | | if (f->subclass != OPBX_FORMAT_SLINEAR) |
| 526 | data = f->data; |
| 527 | switch (f->subclass) |
| 531 | 528 | { |
| 532 | | opbx_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); |
| 529 | case OPBX_FORMAT_SLINEAR: |
| 530 | amp = f->data; |
| 531 | len = f->datalen/2; |
| 532 | break; |
| 533 | case OPBX_FORMAT_ULAW: |
| 534 | amp = alloca(f->datalen*sizeof(int16_t)); |
| 535 | for (x = 0; x < len; x++) |
| 536 | amp[x] = OPBX_MULAW(data[x]); |
| 537 | break; |
| 538 | case OPBX_FORMAT_ALAW: |
| 539 | amp = alloca(f->datalen*sizeof(int16_t)); |
| 540 | for (x = 0; x < len; x++) |
| 541 | amp[x] = OPBX_ALAW(data[x]); |
| 542 | break; |
| 543 | default: |
| 544 | opbx_log(LOG_WARNING, "Silence detection is not supported on codec %s. Use RFC2833\n", opbx_getformatname(f->subclass)); |
| 533 | 545 | return 0; |
| 534 | 546 | } |
| 535 | | s = f->data; |
| 536 | | len = f->datalen/2; |
| 537 | | return __opbx_dsp_silence(dsp, s, len, totalsilence); |
| 547 | return __opbx_dsp_silence(dsp, amp, len, totalsilence); |
| 538 | 548 | } |
| 539 | 549 | |
| 540 | 550 | #define FIX_INF(inf) \ |
| --- | --- | |
| 544 | 554 | { \ |
| 545 | 555 | switch(inf->subclass) \ |
| 546 | 556 | { \ |
| 547 | | case OPBX_FORMAT_SLINEAR: \ |
| 548 | | break; \ |
| 549 | 557 | case OPBX_FORMAT_ULAW: \ |
| 550 | 558 | for (x = 0; x < len; x++) \ |
| 551 | | odata[x] = OPBX_LIN2MU((int16_t) amp[x]); \ |
| 559 | odata[x] = OPBX_LIN2MU(amp[x]); \ |
| 552 | 560 | break; \ |
| 553 | 561 | case OPBX_FORMAT_ALAW: \ |
| 554 | 562 | for (x = 0; x < len; x++) \ |
| 555 | | odata[x] = OPBX_LIN2A((int16_t) amp[x]); \ |
| 563 | odata[x] = OPBX_LIN2A(amp[x]); \ |
| 556 | 564 | break; \ |
| 557 | 565 | } \ |
| 558 | 566 | } \ |
| --- | --- | |
| 582 | 590 | { |
| 583 | 591 | case OPBX_FORMAT_SLINEAR: |
| 584 | 592 | amp = af->data; |
| 585 | | len = af->datalen / 2; |
| 593 | len = af->datalen/2; |
| 586 | 594 | break; |
| 587 | 595 | case OPBX_FORMAT_ULAW: |
| 588 | 596 | amp = alloca(af->datalen*sizeof(int16_t)); |
| --- | --- | |
| 595 | 603 | amp[x] = OPBX_ALAW(odata[x]); |
| 596 | 604 | break; |
| 597 | 605 | default: |
| 598 | | opbx_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", opbx_getformatname(af->subclass)); |
| 606 | opbx_log(LOG_WARNING, "Tone detection is not supported on codec %s. Use RFC2833\n", opbx_getformatname(af->subclass)); |
| 599 | 607 | return af; |
| 600 | 608 | } |
| 601 | 609 | silence = __opbx_dsp_silence(dsp, amp, len, NULL); |
| 602 | | if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) |
| 610 | if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) |
| 603 | 611 | { |
| 604 | 612 | opbx_fr_init(&dsp->f); |
| 605 | 613 | dsp->f.frametype = OPBX_FRAME_NULL; |
| --- | --- | |
| 645 | 653 | if (dsp->dtmf_rx.last_hit) |
| 646 | 654 | { |
| 647 | 655 | /* Looks like we might have something. |
| 648 | | * Request a conference mute for the moment */ |
| 656 | Request a conference mute for the moment */ |
| 649 | 657 | dsp->thinkdigit = 'x'; |
| 650 | 658 | opbx_fr_init_ex(&dsp->f, OPBX_FRAME_DTMF, 'm', NULL); |
| 651 | 659 | FIX_INF(af); |
| --- | --- | |
| 659 | 667 | { |
| 660 | 668 | if (dsp->dtmf_rx.in_digit) |
| 661 | 669 | { |
| 662 | | /* Thought we saw one last time. Pretty sure we really have now */ |
| 670 | /* Thought we saw one last time. It is now confirmed. */ |
| 663 | 671 | if (dsp->thinkdigit) |
| 664 | 672 | { |
| 665 | 673 | if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != dsp->dtmf_rx.in_digit)) |
| --- | --- | |
| 716 | 724 | } |
| 717 | 725 | } |
| 718 | 726 | } |
| 719 | | if ((dsp->features & DSP_FEATURE_FAX_DETECT)) |
| 727 | if ((dsp->features & DSP_FEATURE_FAX_CNG_DETECT)) |
| 720 | 728 | { |
| 721 | 729 | modem_connect_tones_rx(&dsp->fax_cng_rx, amp, len); |
| 722 | 730 | if (modem_connect_tones_rx_get(&dsp->fax_cng_rx)) |
| --- | --- | |
| 729 | 737 | return &dsp->f; |
| 730 | 738 | } |
| 731 | 739 | } |
| 740 | if ((dsp->features & DSP_FEATURE_FAX_CED_DETECT)) |
| 741 | { |
| 742 | modem_connect_tones_rx(&dsp->fax_ced_rx, amp, len); |
| 743 | if (modem_connect_tones_rx_get(&dsp->fax_ced_rx)) |
| 744 | { |
| 745 | opbx_fr_init_ex(&dsp->f, OPBX_FRAME_DTMF, 'F', NULL); |
| 746 | FIX_INF(af); |
| 747 | if (chan) |
| 748 | opbx_queue_frame(chan, af); |
| 749 | opbx_fr_free(af); |
| 750 | return &dsp->f; |
| 751 | } |
| 752 | } |
| 732 | 753 | if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) |
| 733 | 754 | { |
| 734 | | res = __opbx_dsp_call_progress(dsp, amp, len); |
| 735 | | if (res) |
| 755 | if ((res = __opbx_dsp_call_progress(dsp, amp, len))) |
| 736 | 756 | { |
| 737 | 757 | switch (res) |
| 738 | 758 | { |
| --- | --- | |
| 793 | 813 | MODEM_CONNECT_TONES_FAX_CNG, |
| 794 | 814 | NULL, |
| 795 | 815 | NULL); |
| 816 | modem_connect_tones_rx_init(&dsp->fax_ced_rx, |
| 817 | MODEM_CONNECT_TONES_FAX_CED, |
| 818 | NULL, |
| 819 | NULL); |
| 796 | 820 | |
| 797 | 821 | /* Initialize initial DSP progress detect parameters */ |
| 798 | 822 | opbx_dsp_prog_reset(dsp); |
| --- | --- | |
| 843 | 867 | MODEM_CONNECT_TONES_FAX_CNG, |
| 844 | 868 | NULL, |
| 845 | 869 | NULL); |
| 870 | modem_connect_tones_rx_init(&dsp->fax_ced_rx, |
| 871 | MODEM_CONNECT_TONES_FAX_CED, |
| 872 | NULL, |
| 873 | NULL); |
| 846 | 874 | } |
| 847 | 875 | |
| 848 | 876 | void opbx_dsp_reset(struct opbx_dsp *dsp) |
| --- | --- | |
| 859 | 887 | |
| 860 | 888 | int opbx_dsp_digitmode(struct opbx_dsp *dsp, int digitmode) |
| 861 | 889 | { |
| 862 | | int new; |
| 863 | | int old; |
| 890 | int new_mode; |
| 891 | int old_mode; |
| 864 | 892 | |
| 865 | | old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); |
| 866 | | new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); |
| 867 | | if (old != new) |
| 893 | old_mode = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); |
| 894 | new_mode = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); |
| 895 | if (old_mode != new_mode) |
| 868 | 896 | { |
| 869 | 897 | /* Must initialize structures if switching from MF to DTMF or vice-versa */ |
| 870 | | if ((new & DSP_DIGITMODE_MF)) |
| 898 | if ((new_mode & DSP_DIGITMODE_MF)) |
| 871 | 899 | bell_mf_rx_init(&dsp->bell_mf_rx, NULL, NULL); |
| 872 | 900 | else |
| 873 | 901 | dtmf_rx_init(&dsp->dtmf_rx, NULL, NULL); |
| --- | --- | |
| 876 | 904 | MODEM_CONNECT_TONES_FAX_CNG, |
| 877 | 905 | NULL, |
| 878 | 906 | NULL); |
| 907 | modem_connect_tones_rx_init(&dsp->fax_ced_rx, |
| 908 | MODEM_CONNECT_TONES_FAX_CED, |
| 909 | NULL, |
| 910 | NULL); |
| 879 | 911 | } |
| 880 | 912 | if ((digitmode & DSP_DIGITMODE_RELAXDTMF)) |
| 881 | 913 | dtmf_rx_parms(&dsp->dtmf_rx, FALSE, 8, 8); |