FreeCalypso > hg > gsm-codec-lib
comparison libgsmhr1/dec_func.c @ 602:72cdae602d6e
libgsmhr1/dec_func.c: rm unused static functions
In the original code, sp_dec.c held two kinds of functions: those
needed only as part of the decoder, and those used by both decoder
and encoder engines. In this library, we have moved the latter
class of functions to dec_func.c module. Almost all static functions
from the original sp_dec.c, with the exception of aToRc(), are
needed only on sp_dec.c side of the new divide - remove them from
dec_func.c, where they became dead code.
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 04 Dec 2025 18:58:22 +0000 |
| parents | c7c03231002d |
| children | 27df1cef042c |
comparison
equal
deleted
inserted
replaced
| 601:c7c03231002d | 602:72cdae602d6e |
|---|---|
| 95 | | | 95 | | |
| 96 | Local Functions (scope is limited to this file) | | 96 | Local Functions (scope is limited to this file) | |
| 97 |_________________________________________________________________________| | 97 |_________________________________________________________________________| |
| 98 */ | 98 */ |
| 99 | 99 |
| 100 static void a_sst(Shortword swAshift, Shortword swAscale, | |
| 101 Shortword pswDirectFormCoefIn[], | |
| 102 Shortword pswDirectFormCoefOut[]); | |
| 103 | |
| 104 static short aToRc(Shortword swAshift, Shortword pswAin[], | 100 static short aToRc(Shortword swAshift, Shortword pswAin[], |
| 105 Shortword pswRc[]); | 101 Shortword pswRc[]); |
| 106 | |
| 107 static Shortword agcGain(Shortword pswStateCurr[], | |
| 108 struct NormSw snsInSigEnergy, | |
| 109 Shortword swEngyRShft); | |
| 110 | |
| 111 static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[]); | |
| 112 | |
| 113 static void pitchPreFilt(Shortword pswExcite[], | |
| 114 Shortword swRxGsp0, | |
| 115 Shortword swRxLag, | |
| 116 Shortword swUvCode, | |
| 117 Shortword swSemiBeta, | |
| 118 struct NormSw snsSqrtRs, | |
| 119 Shortword pswExciteOut[], | |
| 120 Shortword pswPPreState[]); | |
| 121 | 102 |
| 122 /*_________________________________________________________________________ | 103 /*_________________________________________________________________________ |
| 123 | | | 104 | | |
| 124 | Local Defines | | 105 | Local Defines | |
| 125 |_________________________________________________________________________| | 106 |_________________________________________________________________________| |
| 600 /*----------------------------------------------------*/ | 581 /*----------------------------------------------------*/ |
| 601 | 582 |
| 602 siUnstableFlt = siUnstableFlt | isSwLimit(pswRc[0]); | 583 siUnstableFlt = siUnstableFlt | isSwLimit(pswRc[0]); |
| 603 | 584 |
| 604 return (siUnstableFlt); | 585 return (siUnstableFlt); |
| 605 } | |
| 606 | |
| 607 /*************************************************************************** | |
| 608 * | |
| 609 * FUNCTION NAME: a_sst | |
| 610 * | |
| 611 * PURPOSE: | |
| 612 * | |
| 613 * The purpose of this function is to perform spectral smoothing of the | |
| 614 * direct form filter coefficients | |
| 615 * | |
| 616 * INPUTS: | |
| 617 * | |
| 618 * swAshift | |
| 619 * number of shift for coefficients | |
| 620 * | |
| 621 * swAscale | |
| 622 * scaling factor for coefficients | |
| 623 * | |
| 624 * pswDirectFormCoefIn[0:NP-1] | |
| 625 * | |
| 626 * array of input direct form coefficients | |
| 627 * | |
| 628 * OUTPUTS: | |
| 629 * | |
| 630 * pswDirectFormCoefOut[0:NP-1] | |
| 631 * | |
| 632 * array of output direct form coefficients | |
| 633 * | |
| 634 * RETURN VALUE: | |
| 635 * | |
| 636 * none | |
| 637 * | |
| 638 * DESCRIPTION: | |
| 639 * | |
| 640 * In a_sst() direct form coefficients are converted to | |
| 641 * autocorrelations, and smoothed in that domain. The function is | |
| 642 * used in the spectral postfilter. A description can be found in | |
| 643 * section 3.2.4 as well as in the reference by Y. Tohkura et al. | |
| 644 * "Spectral Smoothing Technique in PARCOR Speech | |
| 645 * Analysis-Synthesis", IEEE Trans. ASSP, vol. ASSP-26, pp. 591-596, | |
| 646 * Dec. 1978. | |
| 647 * | |
| 648 * After smoothing is performed conversion back to direct form | |
| 649 * coefficients is done by calling aFlatRc(), followed by rcToADp(). | |
| 650 * | |
| 651 * The spectral smoothing filter coefficients with bandwidth set to 300 | |
| 652 * and a sampling rate of 8000 be : | |
| 653 * static ShortwordRom psrSST[NP+1] = { 0x7FFF, | |
| 654 * 0x7F5C, 0x7D76, 0x7A5B, 0x7622, 0x70EC, | |
| 655 * 0x6ADD, 0x641F, 0x5CDD, 0x5546, 0x4D86 | |
| 656 * } | |
| 657 * | |
| 658 * REFERENCES: Sub_Clause 4.2.4 of GSM Recomendation 06.20 | |
| 659 * | |
| 660 * KEYWORDS: spectral smoothing, direct form coef, sst, atorc, atocor | |
| 661 * KEYWORDS: levinson | |
| 662 * | |
| 663 *************************************************************************/ | |
| 664 | |
| 665 static void a_sst(Shortword swAshift, Shortword swAscale, | |
| 666 Shortword pswDirectFormCoefIn[], | |
| 667 Shortword pswDirectFormCoefOut[]) | |
| 668 { | |
| 669 | |
| 670 /*_________________________________________________________________________ | |
| 671 | | | |
| 672 | Local Static Variables | | |
| 673 |_________________________________________________________________________| | |
| 674 */ | |
| 675 | |
| 676 static const ShortwordRom psrSST[NP + 1] = {0x7FFF, | |
| 677 0x7F5C, 0x7D76, 0x7A5B, 0x7622, 0x70EC, | |
| 678 0x6ADD, 0x641F, 0x5CDD, 0x5546, 0x4D86, | |
| 679 }; | |
| 680 | |
| 681 /*_________________________________________________________________________ | |
| 682 | | | |
| 683 | Automatic Variables | | |
| 684 |_________________________________________________________________________| | |
| 685 */ | |
| 686 | |
| 687 Longword pL_CorrTemp[NP + 1]; | |
| 688 | |
| 689 Shortword pswRCNum[NP], | |
| 690 pswRCDenom[NP]; | |
| 691 | |
| 692 short int siLoopCnt; | |
| 693 | |
| 694 /*_________________________________________________________________________ | |
| 695 | | | |
| 696 | Executable Code | | |
| 697 |_________________________________________________________________________| | |
| 698 */ | |
| 699 | |
| 700 /* convert direct form coefs to reflection coefs */ | |
| 701 /* --------------------------------------------- */ | |
| 702 | |
| 703 aToRc(swAshift, pswDirectFormCoefIn, pswRCDenom); | |
| 704 | |
| 705 /* convert to autocorrelation coefficients */ | |
| 706 /* --------------------------------------- */ | |
| 707 | |
| 708 rcToCorrDpL(swAshift, swAscale, pswRCDenom, pL_CorrTemp); | |
| 709 | |
| 710 /* do spectral smoothing technique */ | |
| 711 /* ------------------------------- */ | |
| 712 | |
| 713 for (siLoopCnt = 1; siLoopCnt <= NP; siLoopCnt++) | |
| 714 { | |
| 715 pL_CorrTemp[siLoopCnt] = L_mpy_ls(pL_CorrTemp[siLoopCnt], | |
| 716 psrSST[siLoopCnt]); | |
| 717 } | |
| 718 | |
| 719 /* Compute the reflection coefficients via AFLAT */ | |
| 720 /*-----------------------------------------------*/ | |
| 721 | |
| 722 aFlatRcDp(pL_CorrTemp, pswRCNum); | |
| 723 | |
| 724 | |
| 725 /* Convert reflection coefficients to direct form filter coefficients */ | |
| 726 /*-------------------------------------------------------------------*/ | |
| 727 | |
| 728 rcToADp(swAscale, pswRCNum, pswDirectFormCoefOut); | |
| 729 } | |
| 730 | |
| 731 /************************************************************************** | |
| 732 * | |
| 733 * FUNCTION NAME: agcGain | |
| 734 * | |
| 735 * PURPOSE: | |
| 736 * | |
| 737 * Figure out what the agc gain should be to make the energy in the | |
| 738 * output signal match that of the input signal. Used in the post | |
| 739 * filters. | |
| 740 * | |
| 741 * INPUT: | |
| 742 * | |
| 743 * pswStateCurr[0:39] | |
| 744 * Input signal into agc block whose energy is | |
| 745 * to be modified using the gain returned. Signal is not | |
| 746 * modified in this routine. | |
| 747 * | |
| 748 * snsInSigEnergy | |
| 749 * Normalized number with shift count - the energy in | |
| 750 * the input signal. | |
| 751 * | |
| 752 * swEngyRShft | |
| 753 * Number of right shifts to apply to the vectors energy | |
| 754 * to ensure that it remains less than 1.0 | |
| 755 * (swEngyRShft is always positive or zero) | |
| 756 * | |
| 757 * OUTPUT: | |
| 758 * | |
| 759 * none | |
| 760 * | |
| 761 * RETURN: | |
| 762 * | |
| 763 * the agc's gain/2 note DIVIDED by 2 | |
| 764 * | |
| 765 * | |
| 766 * REFERENCES: Sub_Clause 4.2.2 and 4.2.4 of GSM Recomendation 06.20 | |
| 767 * | |
| 768 * KEYWORDS: postfilter, agc, automaticgaincontrol, leveladjust | |
| 769 * | |
| 770 *************************************************************************/ | |
| 771 | |
| 772 static Shortword agcGain(Shortword pswStateCurr[], | |
| 773 struct NormSw snsInSigEnergy, Shortword swEngyRShft) | |
| 774 { | |
| 775 | |
| 776 /*_________________________________________________________________________ | |
| 777 | | | |
| 778 | Automatic Variables | | |
| 779 |_________________________________________________________________________| | |
| 780 */ | |
| 781 | |
| 782 Longword L_OutEnergy, | |
| 783 L_AgcGain; | |
| 784 | |
| 785 struct NormSw snsOutEnergy, | |
| 786 snsAgc; | |
| 787 | |
| 788 Shortword swAgcOut, | |
| 789 swAgcShftCnt; | |
| 790 | |
| 791 /*_________________________________________________________________________ | |
| 792 | | | |
| 793 | Executable Code | | |
| 794 |_________________________________________________________________________| | |
| 795 */ | |
| 796 | |
| 797 /* Calculate the energy in the output vector divided by 2 */ | |
| 798 /*--------------------------------------------------------*/ | |
| 799 | |
| 800 snsOutEnergy.sh = g_corr1s(pswStateCurr, swEngyRShft, &L_OutEnergy); | |
| 801 | |
| 802 /* reduce energy by a factor of 2 */ | |
| 803 snsOutEnergy.sh = add(snsOutEnergy.sh, 1); | |
| 804 | |
| 805 /* if waveform has nonzero energy, find AGC gain */ | |
| 806 /*-----------------------------------------------*/ | |
| 807 | |
| 808 if (L_OutEnergy == 0) | |
| 809 { | |
| 810 swAgcOut = 0; | |
| 811 } | |
| 812 else | |
| 813 { | |
| 814 | |
| 815 snsOutEnergy.man = round(L_OutEnergy); | |
| 816 | |
| 817 /* divide input energy by 2 */ | |
| 818 snsInSigEnergy.man = shr(snsInSigEnergy.man, 1); | |
| 819 | |
| 820 | |
| 821 /* Calculate AGC gain squared */ | |
| 822 /*----------------------------*/ | |
| 823 | |
| 824 snsAgc.man = divide_s(snsInSigEnergy.man, snsOutEnergy.man); | |
| 825 swAgcShftCnt = norm_s(snsAgc.man); | |
| 826 snsAgc.man = shl(snsAgc.man, swAgcShftCnt); | |
| 827 | |
| 828 /* find shift count for G^2 */ | |
| 829 /*--------------------------*/ | |
| 830 | |
| 831 snsAgc.sh = add(sub(snsInSigEnergy.sh, snsOutEnergy.sh), | |
| 832 swAgcShftCnt); | |
| 833 L_AgcGain = L_deposit_h(snsAgc.man); | |
| 834 | |
| 835 | |
| 836 /* Calculate AGC gain */ | |
| 837 /*--------------------*/ | |
| 838 | |
| 839 snsAgc.man = sqroot(L_AgcGain); | |
| 840 | |
| 841 | |
| 842 /* check if 1/2 sqrt(G^2) >= 1.0 */ | |
| 843 /* This is equivalent to checking if shiftCnt/2+1 < 0 */ | |
| 844 /*----------------------------------------------------*/ | |
| 845 | |
| 846 if (add(snsAgc.sh, 2) < 0) | |
| 847 { | |
| 848 swAgcOut = SW_MAX; | |
| 849 } | |
| 850 else | |
| 851 { | |
| 852 | |
| 853 if (0x1 & snsAgc.sh) | |
| 854 { | |
| 855 snsAgc.man = mult(snsAgc.man, SQRT_ONEHALF); | |
| 856 } | |
| 857 | |
| 858 snsAgc.sh = shr(snsAgc.sh, 1); /* shiftCnt/2 */ | |
| 859 snsAgc.sh = add(snsAgc.sh, 1); /* shiftCnt/2 + 1 */ | |
| 860 | |
| 861 if (snsAgc.sh > 0) | |
| 862 { | |
| 863 snsAgc.man = shr(snsAgc.man, snsAgc.sh); | |
| 864 } | |
| 865 swAgcOut = snsAgc.man; | |
| 866 } | |
| 867 } | |
| 868 | |
| 869 return (swAgcOut); | |
| 870 } | 586 } |
| 871 | 587 |
| 872 /*************************************************************************** | 588 /*************************************************************************** |
| 873 * | 589 * |
| 874 * FUNCTION NAME: b_con | 590 * FUNCTION NAME: b_con |
| 1818 return (siInterp_flg); | 1534 return (siInterp_flg); |
| 1819 } | 1535 } |
| 1820 | 1536 |
| 1821 /*************************************************************************** | 1537 /*************************************************************************** |
| 1822 * | 1538 * |
| 1823 * FUNCTION NAME: lookupVq | |
| 1824 * | |
| 1825 * PURPOSE: | |
| 1826 * | |
| 1827 * The purpose of this function is to recover the reflection coeffs from | |
| 1828 * the received LPC codewords. | |
| 1829 * | |
| 1830 * INPUTS: | |
| 1831 * | |
| 1832 * pswVqCodeWds[0:2] | |
| 1833 * | |
| 1834 * the codewords for each of the segments | |
| 1835 * | |
| 1836 * OUTPUTS: | |
| 1837 * | |
| 1838 * pswRCOut[0:NP-1] | |
| 1839 * | |
| 1840 * the decoded reflection coefficients | |
| 1841 * | |
| 1842 * RETURN VALUE: | |
| 1843 * | |
| 1844 * none. | |
| 1845 * | |
| 1846 * DESCRIPTION: | |
| 1847 * | |
| 1848 * For each segment do the following: | |
| 1849 * setup the retrieval pointers to the correct vector | |
| 1850 * get that vector | |
| 1851 * | |
| 1852 * REFERENCES: Sub-clause 4.2.3 of GSM Recomendation 06.20 | |
| 1853 * | |
| 1854 * KEYWORDS: vq, vectorquantizer, lpc | |
| 1855 * | |
| 1856 *************************************************************************/ | |
| 1857 | |
| 1858 static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[]) | |
| 1859 { | |
| 1860 /*_________________________________________________________________________ | |
| 1861 | | | |
| 1862 | Local Constants | | |
| 1863 |_________________________________________________________________________| | |
| 1864 */ | |
| 1865 | |
| 1866 #define LSP_MASK 0x00ff | |
| 1867 | |
| 1868 /*_________________________________________________________________________ | |
| 1869 | | | |
| 1870 | Automatic Variables | | |
| 1871 |_________________________________________________________________________| | |
| 1872 */ | |
| 1873 | |
| 1874 short int siSeg, | |
| 1875 siIndex, | |
| 1876 siVector, | |
| 1877 siVector1, | |
| 1878 siVector2, | |
| 1879 siWordPtr; | |
| 1880 | |
| 1881 const ShortwordRom *psrQTable; | |
| 1882 | |
| 1883 /*_________________________________________________________________________ | |
| 1884 | | | |
| 1885 | Executable Code | | |
| 1886 |_________________________________________________________________________| | |
| 1887 */ | |
| 1888 | |
| 1889 /* for each segment */ | |
| 1890 /* ---------------- */ | |
| 1891 | |
| 1892 for (siSeg = 0; siSeg < QUANT_NUM_OF_TABLES; siSeg++) | |
| 1893 { | |
| 1894 | |
| 1895 siVector = pswVqCodeWds[siSeg]; | |
| 1896 siIndex = psvqIndex[siSeg].l; | |
| 1897 | |
| 1898 if (sub(siSeg, 2) == 0) | |
| 1899 { /* segment 3 */ | |
| 1900 | |
| 1901 /* set table */ | |
| 1902 /* --------- */ | |
| 1903 | |
| 1904 psrQTable = psrQuant3; | |
| 1905 | |
| 1906 /* set offset into table */ | |
| 1907 /* ---------------------- */ | |
| 1908 | |
| 1909 siWordPtr = add(siVector, siVector); | |
| 1910 | |
| 1911 /* look up coeffs */ | |
| 1912 /* -------------- */ | |
| 1913 | |
| 1914 siVector1 = psrQTable[siWordPtr]; | |
| 1915 siVector2 = psrQTable[siWordPtr + 1]; | |
| 1916 | |
| 1917 pswRCOut[siIndex - 1] = psrSQuant[shr(siVector1, 8) & LSP_MASK]; | |
| 1918 pswRCOut[siIndex] = psrSQuant[siVector1 & LSP_MASK]; | |
| 1919 pswRCOut[siIndex + 1] = psrSQuant[shr(siVector2, 8) & LSP_MASK]; | |
| 1920 pswRCOut[siIndex + 2] = psrSQuant[siVector2 & LSP_MASK]; | |
| 1921 } | |
| 1922 else | |
| 1923 { /* segments 1 and 2 */ | |
| 1924 | |
| 1925 /* set tables */ | |
| 1926 /* ---------- */ | |
| 1927 | |
| 1928 if (siSeg == 0) | |
| 1929 { | |
| 1930 psrQTable = psrQuant1; | |
| 1931 } | |
| 1932 else | |
| 1933 { | |
| 1934 psrQTable = psrQuant2; | |
| 1935 | |
| 1936 } | |
| 1937 | |
| 1938 /* set offset into table */ | |
| 1939 /* --------------------- */ | |
| 1940 | |
| 1941 siWordPtr = add(siVector, siVector); | |
| 1942 siWordPtr = add(siWordPtr, siVector); | |
| 1943 siWordPtr = shr(siWordPtr, 1); | |
| 1944 | |
| 1945 /* look up coeffs */ | |
| 1946 /* -------------- */ | |
| 1947 | |
| 1948 siVector1 = psrQTable[siWordPtr]; | |
| 1949 siVector2 = psrQTable[siWordPtr + 1]; | |
| 1950 | |
| 1951 if ((siVector & 0x0001) == 0) | |
| 1952 { | |
| 1953 pswRCOut[siIndex - 1] = psrSQuant[shr(siVector1, 8) & LSP_MASK]; | |
| 1954 pswRCOut[siIndex] = psrSQuant[siVector1 & LSP_MASK]; | |
| 1955 pswRCOut[siIndex + 1] = psrSQuant[shr(siVector2, 8) & LSP_MASK]; | |
| 1956 } | |
| 1957 else | |
| 1958 { | |
| 1959 pswRCOut[siIndex - 1] = psrSQuant[siVector1 & LSP_MASK]; | |
| 1960 pswRCOut[siIndex] = psrSQuant[shr(siVector2, 8) & LSP_MASK]; | |
| 1961 pswRCOut[siIndex + 1] = psrSQuant[siVector2 & LSP_MASK]; | |
| 1962 } | |
| 1963 } | |
| 1964 } | |
| 1965 } | |
| 1966 | |
| 1967 /*************************************************************************** | |
| 1968 * | |
| 1969 * FUNCTION NAME: lpcFir | 1539 * FUNCTION NAME: lpcFir |
| 1970 * | 1540 * |
| 1971 * PURPOSE: | 1541 * PURPOSE: |
| 1972 * | 1542 * |
| 1973 * The purpose of this function is to perform direct form fir filtering | 1543 * The purpose of this function is to perform direct form fir filtering |
| 2913 | 2483 |
| 2914 pswCommonIO[siSmp] = extract_h(L_Sum); | 2484 pswCommonIO[siSmp] = extract_h(L_Sum); |
| 2915 } | 2485 } |
| 2916 } | 2486 } |
| 2917 | 2487 |
| 2918 /************************************************************************** | |
| 2919 * | |
| 2920 * FUNCTION NAME: pitchPreFilt | |
| 2921 * | |
| 2922 * PURPOSE: | |
| 2923 * | |
| 2924 * Performs pitch pre-filter on excitation in speech decoder. | |
| 2925 * | |
| 2926 * INPUTS: | |
| 2927 * | |
| 2928 * pswExcite[0:39] | |
| 2929 * | |
| 2930 * Synthetic residual signal to be filtered, a subframe- | |
| 2931 * length vector. | |
| 2932 * | |
| 2933 * ppsrPVecIntFilt[0:9][0:5] ([tap][phase]) | |
| 2934 * | |
| 2935 * Interpolation filter coefficients. | |
| 2936 * | |
| 2937 * ppsrSqtrP0[0:2][0:31] ([voicing level-1][gain code]) | |
| 2938 * | |
| 2939 * Sqrt(P0) look-up table, used to determine pitch | |
| 2940 * pre-filtering coefficient. | |
| 2941 * | |
| 2942 * swRxGsp0 | |
| 2943 * | |
| 2944 * Coded value from gain quantizer, used to look up | |
| 2945 * sqrt(P0). | |
| 2946 * | |
| 2947 * swRxLag | |
| 2948 * | |
| 2949 * Full-resolution lag value (fractional lag * | |
| 2950 * oversampling factor), used to index pitch pre-filter | |
| 2951 * state. | |
| 2952 * | |
| 2953 * swUvCode | |
| 2954 * | |
| 2955 * Coded voicing level, used to distinguish between | |
| 2956 * voiced and unvoiced conditions, and to look up | |
| 2957 * sqrt(P0). | |
| 2958 * | |
| 2959 * swSemiBeta | |
| 2960 * | |
| 2961 * The gain applied to the adaptive codebook excitation | |
| 2962 * (long-term predictor excitation) limited to a maximum | |
| 2963 * of 1.0, used to determine the pitch pre-filter | |
| 2964 * coefficient. | |
| 2965 * | |
| 2966 * snsSqrtRs | |
| 2967 * | |
| 2968 * The estimate of the energy in the residual, used only | |
| 2969 * for scaling. | |
| 2970 * | |
| 2971 * OUTPUTS: | |
| 2972 * | |
| 2973 * pswExciteOut[0:39] | |
| 2974 * | |
| 2975 * The output pitch pre-filtered excitation. | |
| 2976 * | |
| 2977 * pswPPreState[0:44] | |
| 2978 * | |
| 2979 * Contains the state of the pitch pre-filter | |
| 2980 * | |
| 2981 * RETURN VALUE: | |
| 2982 * | |
| 2983 * none | |
| 2984 * | |
| 2985 * DESCRIPTION: | |
| 2986 * | |
| 2987 * If the voicing mode for the frame is unvoiced, then the pitch pre- | |
| 2988 * filter state is updated with the input excitation, and the input | |
| 2989 * excitation is copied to the output. | |
| 2990 * | |
| 2991 * If voiced: first the energy in the input excitation is calculated. | |
| 2992 * Then, the coefficient of the pitch pre-filter is obtained: | |
| 2993 * | |
| 2994 * PpfCoef = POST_EPSILON * min(beta, sqrt(P0)). | |
| 2995 * | |
| 2996 * Then, the pitch pre-filter is performed: | |
| 2997 * | |
| 2998 * ex_p(n) = ex(n) + PpfCoef * ex_p(n-L) | |
| 2999 * | |
| 3000 * The ex_p(n-L) sample is interpolated from the surrounding samples, | |
| 3001 * even for integer values of L. | |
| 3002 * | |
| 3003 * Note: The coefficients of the interpolating filter are multiplied | |
| 3004 * by PpfCoef, rather multiplying ex_p(n_L) after interpolation. | |
| 3005 * | |
| 3006 * Finally, the energy in the output excitation is calculated, and | |
| 3007 * automatic gain control is applied to the output signal so that | |
| 3008 * its energy matches the original. | |
| 3009 * | |
| 3010 * The pitch pre-filter is described in section 4.2.2. | |
| 3011 * | |
| 3012 * REFERENCES: Sub-clause 4.2.2 of GSM Recomendation 06.20 | |
| 3013 * | |
| 3014 * KEYWORDS: prefilter, pitch, pitchprefilter, excitation, residual | |
| 3015 * | |
| 3016 *************************************************************************/ | |
| 3017 | |
| 3018 static void pitchPreFilt(Shortword pswExcite[], | |
| 3019 Shortword swRxGsp0, | |
| 3020 Shortword swRxLag, Shortword swUvCode, | |
| 3021 Shortword swSemiBeta, struct NormSw snsSqrtRs, | |
| 3022 Shortword pswExciteOut[], | |
| 3023 Shortword pswPPreState[]) | |
| 3024 { | |
| 3025 | |
| 3026 /*_________________________________________________________________________ | |
| 3027 | | | |
| 3028 | Local Constants | | |
| 3029 |_________________________________________________________________________| | |
| 3030 */ | |
| 3031 | |
| 3032 #define POST_EPSILON 0x2666 | |
| 3033 | |
| 3034 /*_________________________________________________________________________ | |
| 3035 | | | |
| 3036 | Local Static Variables | | |
| 3037 |_________________________________________________________________________| | |
| 3038 */ | |
| 3039 | |
| 3040 | |
| 3041 /*_________________________________________________________________________ | |
| 3042 | | | |
| 3043 | Automatic Variables | | |
| 3044 |_________________________________________________________________________| | |
| 3045 */ | |
| 3046 | |
| 3047 Longword L_1, | |
| 3048 L_OrigEnergy; | |
| 3049 | |
| 3050 Shortword swScale, | |
| 3051 swSqrtP0, | |
| 3052 swIntLag, | |
| 3053 swRemain, | |
| 3054 swEnergy, | |
| 3055 pswInterpCoefs[P_INT_MACS]; | |
| 3056 | |
| 3057 short int i, | |
| 3058 j; | |
| 3059 | |
| 3060 struct NormSw snsOrigEnergy; | |
| 3061 | |
| 3062 Shortword *pswPPreCurr = &pswPPreState[LTP_LEN]; | |
| 3063 | |
| 3064 /*_________________________________________________________________________ | |
| 3065 | | | |
| 3066 | Executable Code | | |
| 3067 |_________________________________________________________________________| | |
| 3068 */ | |
| 3069 | |
| 3070 /* Initialization */ | |
| 3071 /*----------------*/ | |
| 3072 | |
| 3073 swEnergy = 0; | |
| 3074 | |
| 3075 /* Check voicing level */ | |
| 3076 /*---------------------*/ | |
| 3077 | |
| 3078 if (swUvCode == 0) | |
| 3079 { | |
| 3080 | |
| 3081 /* Unvoiced: perform one subframe of delay on state, copy input to */ | |
| 3082 /* state, copy input to output (if not same) */ | |
| 3083 /*-----------------------------------------------------------------*/ | |
| 3084 | |
| 3085 for (i = 0; i < LTP_LEN - S_LEN; i++) | |
| 3086 pswPPreState[i] = pswPPreState[i + S_LEN]; | |
| 3087 | |
| 3088 for (i = 0; i < S_LEN; i++) | |
| 3089 pswPPreState[i + LTP_LEN - S_LEN] = pswExcite[i]; | |
| 3090 | |
| 3091 if (pswExciteOut != pswExcite) | |
| 3092 { | |
| 3093 | |
| 3094 for (i = 0; i < S_LEN; i++) | |
| 3095 pswExciteOut[i] = pswExcite[i]; | |
| 3096 } | |
| 3097 } | |
| 3098 else | |
| 3099 { | |
| 3100 | |
| 3101 /* Voiced: calculate energy in input, filter, calculate energy in */ | |
| 3102 /* output, scale */ | |
| 3103 /*----------------------------------------------------------------*/ | |
| 3104 | |
| 3105 /* Get energy in input excitation vector */ | |
| 3106 /*---------------------------------------*/ | |
| 3107 | |
| 3108 swEnergy = add(negate(shl(snsSqrtRs.sh, 1)), 3); | |
| 3109 | |
| 3110 if (swEnergy > 0) | |
| 3111 { | |
| 3112 | |
| 3113 /* High-energy residual: scale input vector during energy */ | |
| 3114 /* calculation. The shift count + 1 of the energy of the */ | |
| 3115 /* residual estimate is used as an estimate of the shift */ | |
| 3116 /* count needed for the excitation energy */ | |
| 3117 /*--------------------------------------------------------*/ | |
| 3118 | |
| 3119 | |
| 3120 snsOrigEnergy.sh = g_corr1s(pswExcite, swEnergy, &L_OrigEnergy); | |
| 3121 snsOrigEnergy.man = round(L_OrigEnergy); | |
| 3122 | |
| 3123 } | |
| 3124 else | |
| 3125 { | |
| 3126 | |
| 3127 /* set shift count to zero for AGC later */ | |
| 3128 /*---------------------------------------*/ | |
| 3129 | |
| 3130 swEnergy = 0; | |
| 3131 | |
| 3132 /* Lower-energy residual: no overflow protection needed */ | |
| 3133 /*------------------------------------------------------*/ | |
| 3134 | |
| 3135 L_OrigEnergy = 0; | |
| 3136 for (i = 0; i < S_LEN; i++) | |
| 3137 { | |
| 3138 | |
| 3139 L_OrigEnergy = L_mac(L_OrigEnergy, pswExcite[i], pswExcite[i]); | |
| 3140 } | |
| 3141 | |
| 3142 snsOrigEnergy.sh = norm_l(L_OrigEnergy); | |
| 3143 snsOrigEnergy.man = round(L_shl(L_OrigEnergy, snsOrigEnergy.sh)); | |
| 3144 } | |
| 3145 | |
| 3146 /* Determine pitch pre-filter coefficient, and scale the appropriate */ | |
| 3147 /* phase of the interpolating filter by it */ | |
| 3148 /*-------------------------------------------------------------------*/ | |
| 3149 | |
| 3150 swSqrtP0 = ppsrSqrtP0[swUvCode - 1][swRxGsp0]; | |
| 3151 | |
| 3152 if (sub(swSqrtP0, swSemiBeta) > 0) | |
| 3153 swScale = swSemiBeta; | |
| 3154 else | |
| 3155 swScale = swSqrtP0; | |
| 3156 | |
| 3157 swScale = mult_r(POST_EPSILON, swScale); | |
| 3158 | |
| 3159 get_ipjj(swRxLag, &swIntLag, &swRemain); | |
| 3160 | |
| 3161 for (i = 0; i < P_INT_MACS; i++) | |
| 3162 pswInterpCoefs[i] = mult_r(ppsrPVecIntFilt[i][swRemain], swScale); | |
| 3163 | |
| 3164 /* Perform filter */ | |
| 3165 /*----------------*/ | |
| 3166 | |
| 3167 for (i = 0; i < S_LEN; i++) | |
| 3168 { | |
| 3169 | |
| 3170 L_1 = L_deposit_h(pswExcite[i]); | |
| 3171 | |
| 3172 for (j = 0; j < P_INT_MACS - 1; j++) | |
| 3173 { | |
| 3174 | |
| 3175 L_1 = L_mac(L_1, pswPPreCurr[i - swIntLag - P_INT_MACS / 2 + j], | |
| 3176 pswInterpCoefs[j]); | |
| 3177 } | |
| 3178 | |
| 3179 pswPPreCurr[i] = mac_r(L_1, | |
| 3180 pswPPreCurr[i - swIntLag + P_INT_MACS / 2 - 1], | |
| 3181 pswInterpCoefs[P_INT_MACS - 1]); | |
| 3182 } | |
| 3183 | |
| 3184 /* Get energy in filtered vector, determine automatic-gain-control */ | |
| 3185 /* scale factor */ | |
| 3186 /*-----------------------------------------------------------------*/ | |
| 3187 | |
| 3188 swScale = agcGain(pswPPreCurr, snsOrigEnergy, swEnergy); | |
| 3189 | |
| 3190 /* Scale filtered vector by AGC, put out. NOTE: AGC scale returned */ | |
| 3191 /* by routine above is divided by two, hence the shift below */ | |
| 3192 /*------------------------------------------------------------------*/ | |
| 3193 | |
| 3194 for (i = 0; i < S_LEN; i++) | |
| 3195 { | |
| 3196 | |
| 3197 L_1 = L_mult(pswPPreCurr[i], swScale); | |
| 3198 L_1 = L_shl(L_1, 1); | |
| 3199 pswExciteOut[i] = round(L_1); | |
| 3200 } | |
| 3201 | |
| 3202 /* Update pitch pre-filter state */ | |
| 3203 /*-------------------------------*/ | |
| 3204 | |
| 3205 for (i = 0; i < LTP_LEN; i++) | |
| 3206 pswPPreState[i] = pswPPreState[i + S_LEN]; | |
| 3207 } | |
| 3208 } | |
| 3209 | |
| 3210 /*************************************************************************** | 2488 /*************************************************************************** |
| 3211 * | 2489 * |
| 3212 * FUNCTION NAME: r0BasedEnergyShft | 2490 * FUNCTION NAME: r0BasedEnergyShft |
| 3213 * | 2491 * |
| 3214 * PURPOSE: | 2492 * PURPOSE: |
