LCOV - code coverage report
Current view: top level - lib_com - lsp_conv_poly_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ a17e51f9ff5a27406f0609d97377f4ae607c6718 Lines: 212 287 73.9 %
Date: 2025-11-06 02:08:20 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h"
       7             : #include "cnst.h"
       8             : #include "rom_com.h"
       9             : #include "prot_fx.h"
      10             : #include "wmc_auto.h"
      11             : 
      12             : /*-------------------------------------------------------------------*
      13             :  * Local constants
      14             :  *-------------------------------------------------------------------*/
      15             : 
      16             : /* The conversion modes. */
      17             : #define DOWNCONV 0
      18             : #define UPCONV   1
      19             : /* The cap of the inverse power spectrum. */
      20             : #define MAXPOWERSPECT 1e-5f
      21             : #define N50           GRID50_POINTS
      22             : #define N40           GRID40_POINTS
      23             : 
      24             : /*-------------------------------------------------------------------*
      25             :  * Local function prototypes
      26             :  *-------------------------------------------------------------------*/
      27             : static void powerspect_fx( const Word16 x[], Word16 N, Word32 R[], Word32 S[], Word32 G[], Word16 mode );
      28             : static void spectautocorr_fx( const Word16 x[], const Word16 N, const Word32 G[], Word16 rh[], Word16 rl[] );
      29             : static Word32 b_inv_sq( const Word32 in32, const Word16 exp_in );
      30             : static Word32 inv_pow( const Word32 re, const Word32 se, const Word16 x );
      31             : static void zeros2poly_fx( Word16 x[], Word32 R[], Word32 S[] );
      32             : static void polydecomp_fx( Word16 A[], Word32 P[], Word32 Q[] );
      33             : static void cheb2poly_fx( Word32 L_P[] );
      34             : 
      35             : /*---------------------------------------------------------------------*
      36             :  *  lsp_convert_poly()
      37             :  *
      38             :  *  Converts the LP filter estimated at 16.0 kHz sampling rate down
      39             :  *  12.8 kHz frequency scale or alternatively from 12.8 kHz up to
      40             :  *  16.0 kHz.  The former is called down conversation and latter up
      41             :  *  conversion.  The resulting LP filter is characterized with its
      42             :  *  line spectrum pairs.  The original Lp filter can be either in
      43             :  *  its immittance, used for the AMR-WB IO mode, or line spectrum
      44             :  *  pair representation.
      45             :  *
      46             :  *  The conversion is based the autocorrelation computed from the
      47             :  *  power spectrum of the LP filter that is truncated or extrapolated
      48             :  *  to the desired frequency scale.
      49             :  *---------------------------------------------------------------------*/
      50             : 
      51      103344 : Word16 lsp_convert_poly_fx(
      52             :     Word16 w[],            /* i/o: LSP or ISP parameters          */
      53             :     const Word16 L_frame,  /* i  : flag for up or down conversion */
      54             :     const Word16 Opt_AMRWB /* i  : flag for the AMR-WB IO mode    */
      55             : )
      56             : {
      57             :     Word16 flag;
      58             : 
      59             :     Word32 G[GRID50_POINTS];
      60             :     Word16 i;
      61             :     Word16 A[M + 1];
      62             :     Word32 R[NC + 1], S[NC + 1];
      63             :     Word32 epsP[M + 1];
      64             :     Word16 rh[M + 1], rl[M + 1];
      65             :     Word16 oldA[M + 3];
      66             : 
      67             :     /*---------------------------------------------------------------------*
      68             :      * Because AMR-WB IO mode uses immittance spectrum frequency representation
      69             :      * instead of line spectrum frequency representation, the input
      70             :      * parameters do not give the zeros of the polynomials R(x) and S(x).
      71             :      * Hence R(x) and S(x) are formed via the polynomial A(z) of the linear
      72             :      * prediction filter.
      73             :      *---------------------------------------------------------------------*/
      74             : 
      75      103344 :     IF( Opt_AMRWB )
      76             :     {
      77           0 :         E_LPC_f_isp_a_conversion( w, oldA, M );
      78             : 
      79           0 :         polydecomp_fx( oldA, R, S );
      80             :     }
      81             : 
      82             :     /*---------------------------------------------------------------------*
      83             :      * Form the polynomials R(x) and S(x) from their zeros that are the
      84             :      * line spectrum pairs of A(z).  The polynomial coefficients can be
      85             :      * scaled for convenience, because scaling will not affect the
      86             :      * resulting LP coefficients.  Scaling by 128 gives the correct offset
      87             :      * to the power spectrum for n = 16.
      88             :      *---------------------------------------------------------------------*/
      89             : 
      90             :     ELSE
      91             :     {
      92      103344 :         E_LPC_f_lsp_a_conversion( w, oldA, M );
      93             : 
      94      103344 :         zeros2poly_fx( w, R, S );
      95             :     }
      96             : 
      97             :     /*---------------------------------------------------------------------*
      98             :      * Conversion from 16.0 kHz down to 12.8 kHz.  The power spectrum
      99             :      * needs to be computed only up to 6.4 kHz, because the upper band
     100             :      * is omitted.
     101             :      *---------------------------------------------------------------------*/
     102             : 
     103      103344 :     IF( EQ_16( L_frame, L_FRAME ) )
     104             :     {
     105        5226 :         powerspect_fx( grid50_fx, N50, R, S, G, DOWNCONV );
     106        5226 :         spectautocorr_fx( grid40_fx, N40, G, rh, rl );
     107             :     }
     108             :     /*---------------------------------------------------------------------*
     109             :      * Conversion from 12.8 kHz up to 16.0 kHz.
     110             :      * Compute the power spectrum of the LP filter, extrapolate the
     111             :      * power spectrum from 6.4 kHz to 8.0 kHz, and compute auto-
     112             :      * correlation on this power spectrum.
     113             :      *---------------------------------------------------------------------*/
     114             : 
     115             :     ELSE
     116             :     {
     117       98118 :         powerspect_fx( grid40_fx, N40, R, S, G, UPCONV );
     118             : 
     119     1079298 :         FOR( i = N40; i < N50; i++ )
     120             :         {
     121      981180 :             G[i] = G[N40 - 1];
     122      981180 :             move32();
     123             :         }
     124             : 
     125       98118 :         spectautocorr_fx( grid50_fx, N50, G, rh, rl );
     126             :     }
     127             : 
     128             : 
     129             :     /*---------------------------------------------------------------------*
     130             :      * Compute the linear prediction coefficients from the autocorrelation
     131             :      * and convert to line spectrum pairs.
     132             :      *---------------------------------------------------------------------*/
     133      103344 :     flag = E_LPC_lev_dur( rh, rl, A, epsP, M, oldA );
     134      103344 :     E_LPC_a_lsp_conversion( A, w, stable_LSP_fx, M );
     135             : 
     136             : 
     137      103344 :     return ( flag );
     138             : }
     139             : 
     140             : /*---------------------------------------------------------------------*
     141             :  *  powerspect()
     142             :  *
     143             :  *  Computes the power spectrum G(w) = 1/|A(w)|^2 at N points on
     144             :  *  the real axis x = cos w by utilizing the line spectrum frequency
     145             :  *  decomposition
     146             :  *
     147             :  *     A(z) = (P(z) + Q(z))/2,
     148             :  *
     149             :  *  where assuming A(z) of an even degree n,
     150             :  *
     151             :  *     P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
     152             :  *     Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1).
     153             :  *
     154             :  *  The zeros of these polynomials give the line spectrum frequencies
     155             :  *  of A(z).  It can be shown that for an even n,
     156             :  *
     157             :  *     |A(x)|^2 = 2 (1 + x) R(x)^2 + 2 (1 - x) S(x)^2,
     158             :  *
     159             :  *  where x = cos w, and R(x) and S(x) are the direct polynomials
     160             :  *  resulting from the Chebyshev series representation of P(z)
     161             :  *  and Q(z).
     162             :  *
     163             :  *  This routine assumes the grid X = 1, x[0], x[1], .., x[m-1],
     164             :  *  -, ..., -x[1], -x[0], -1 such that x[i] = cos((i+1)*pi/N) for
     165             :  *  evaluating the power spectrum.  Only m = (N-1)/2 - 1 grid points
     166             :  *  need to be stored, because cos(0) and cos(pi/2) are trivial,
     167             :  *  and the points above pi/2 are obtained readily using the symmetry
     168             :  *  of cosine.
     169             :  *
     170             :  *  The power spectrum can be scaled as a*G[], where a is chosen
     171             :  *  for convenience. This is because the scaling has no impact on
     172             :  *  the LP coefficients to be determined based on the power spectrum.
     173             :  *---------------------------------------------------------------------*/
     174             : 
     175      103344 : void powerspect_fx(
     176             :     const Word16 x[], /* i: Q15 Grid points x[0:m-1]             */
     177             :     Word16 N,         /* i: Number of grid points                */
     178             :     Word32 R[],       /* i: Q20 Coefficients of R(x) in R[0:NC]  */
     179             :     Word32 S[],       /* i: Q20 Coefficients of S(x) in S[0:NC]  */
     180             :     Word32 G[],       /* o: Q15 Power spectrum G[0:N]            */
     181             :     Word16 mode       /* i: Flag for up or down conversion       */
     182             : )
     183             : {
     184             :     Word32 s0, se, so, r0, re, ro;
     185             :     Word16 i, j;
     186             :     Word16 iuni, imid;
     187             :     Word32 L_tmp;
     188             :     Word16 x2;
     189             :     Word32 mh;
     190             :     UWord16 ml;
     191             : 
     192             :     /*---------------------------------------------------------------------*
     193             :      * Down conversion yields iuni unique grid points that do not have
     194             :      * symmetric counterparts above x = cos(pi/2) = 0.
     195             :      * Set the mid point of the frequency grid.
     196             :      *---------------------------------------------------------------------*/
     197             : 
     198      103344 :     IF( mode == DOWNCONV )
     199             :     {
     200        5226 :         iuni = ( GRID50_POINTS - 1 ) / 5 - 1;
     201        5226 :         move16();
     202        5226 :         imid = ( GRID50_POINTS - 1 ) / 2;
     203        5226 :         move16();
     204             :     }
     205             : 
     206             :     /*---------------------------------------------------------------------*
     207             :      * Power spectrum x = cos(pi) = -1 that is not needed in down
     208             :      * conversion. Set the mid point of the frequency grid.
     209             :      *---------------------------------------------------------------------*/
     210             : 
     211             :     ELSE
     212             :     {
     213       98118 :         iuni = 0;
     214       98118 :         move16();
     215       98118 :         imid = ( GRID40_POINTS - 1 ) / 2;
     216       98118 :         move16();
     217             : 
     218       98118 :         G[N - 1] = S[0];
     219       98118 :         move32();
     220             : 
     221      883062 :         FOR( j = 1; j <= NC; j++ )
     222             :         {
     223      784944 :             G[N - 1] = L_sub( S[j], G[N - 1] );
     224      784944 :             move32();
     225             :         }
     226       98118 :         G[N - 1] = b_inv_sq( G[N - 1], 19 );
     227       98118 :         move32();
     228             :     }
     229             : 
     230             :     /*---------------------------------------------------------------------*
     231             :      * Power spectrum x = cos(0) = 1.
     232             :      *---------------------------------------------------------------------*/
     233             : 
     234      103344 :     G[0] = R[0];
     235      103344 :     move32();
     236      930096 :     FOR( j = 1; j <= NC; j++ )
     237             :     {
     238      826752 :         G[0] = L_add( R[j], G[0] );
     239      826752 :         move32();
     240             :     }
     241             : 
     242      103344 :     G[0] = b_inv_sq( L_max( G[0], 1 ), 19 );
     243      103344 :     move32();
     244             : 
     245             :     /*---------------------------------------------------------------------*
     246             :      * Power spectrum at x = cos(pi/2) = 0.
     247             :      *---------------------------------------------------------------------*/
     248      103344 :     G[imid] = inv_pow( R[NC], S[NC], 0 );
     249      103344 :     move32();
     250             : 
     251             :     /*---------------------------------------------------------------------*
     252             :      * Power spectrum at unique points that do not have symmetric
     253             :      * counterparts at x > cos(pi/2) = 0.
     254             :      *---------------------------------------------------------------------*/
     255             : 
     256      150378 :     FOR( i = 1; i <= iuni; i++ )
     257             :     {
     258       47034 :         Mpy_32_16_ss( R[0], x[i - 1], &mh, &ml );
     259       47034 :         r0 = L_add( R[1], mh );
     260       47034 :         Mpy_32_16_ss( S[0], x[i - 1], &mh, &ml );
     261       47034 :         s0 = L_add( S[1], mh );
     262             : 
     263             : 
     264      376272 :         FOR( j = 2; j <= NC; j++ )
     265             :         {
     266      329238 :             Mpy_32_16_ss( r0, x[i - 1], &mh, &ml );
     267      329238 :             r0 = L_add( R[j], mh );
     268             : 
     269      329238 :             Mpy_32_16_ss( s0, x[i - 1], &mh, &ml );
     270      329238 :             s0 = L_add( S[j], mh );
     271             :         }
     272             : 
     273       47034 :         G[i] = inv_pow( r0, s0, x[i - 1] );
     274       47034 :         move32();
     275             :     }
     276             : 
     277             :     /*---------------------------------------------------------------------*
     278             :      * Power spectrum at points other than x = -1, 0, and 1 and unique
     279             :      * points is computed using the anti-symmetry of the grid relative
     280             :      * to the midpoint x = 0 in order to reduce looping.
     281             :      *---------------------------------------------------------------------*/
     282             : 
     283     2045976 :     FOR( ; i < imid; i++ )
     284             :     {
     285     1942632 :         x2 = mult_r( x[i - 1], x[i - 1] );
     286             : 
     287     1942632 :         Mpy_32_16_ss( R[0], x2, &mh, &ml );
     288     1942632 :         re = L_add( R[2], mh );
     289     1942632 :         Mpy_32_16_ss( R[1], x2, &mh, &ml );
     290     1942632 :         ro = L_add( R[3], mh );
     291             : 
     292     1942632 :         Mpy_32_16_ss( S[0], x2, &mh, &ml );
     293     1942632 :         se = L_add( S[2], mh );
     294     1942632 :         Mpy_32_16_ss( S[1], x2, &mh, &ml );
     295     1942632 :         so = L_add( S[3], mh );
     296             : 
     297     5827896 :         FOR( j = 4; j < NC; j += 2 )
     298             :         {
     299     3885264 :             Mpy_32_16_ss( re, x2, &mh, &ml );
     300     3885264 :             re = L_add( R[j], mh );
     301     3885264 :             Mpy_32_16_ss( ro, x2, &mh, &ml );
     302     3885264 :             ro = L_add( R[j + 1], mh );
     303     3885264 :             Mpy_32_16_ss( se, x2, &mh, &ml );
     304     3885264 :             se = L_add( S[j], mh );
     305     3885264 :             Mpy_32_16_ss( so, x2, &mh, &ml );
     306     3885264 :             so = L_add( S[j + 1], mh );
     307             :         }
     308             : 
     309     1942632 :         Mpy_32_16_ss( re, x2, &mh, &ml );
     310     1942632 :         L_tmp = L_add( R[j], mh );
     311     1942632 :         Mpy_32_16_ss( ro, x[i - 1], &mh, &ml );
     312     1942632 :         re = L_add( L_tmp, mh );
     313     1942632 :         ro = L_sub( L_tmp, mh );
     314             : 
     315     1942632 :         Mpy_32_16_ss( se, x2, &mh, &ml );
     316     1942632 :         L_tmp = L_add( S[j], mh );
     317     1942632 :         Mpy_32_16_ss( so, x[i - 1], &mh, &ml );
     318     1942632 :         se = L_add( L_tmp, mh );
     319     1942632 :         so = L_sub( L_tmp, mh );
     320             : 
     321     1942632 :         G[i] = inv_pow( re, se, x[i - 1] );
     322     1942632 :         move32();
     323     1942632 :         G[N - i - 1] = inv_pow( so, ro, x[i - 1] );
     324     1942632 :         move32();
     325             :     }
     326             : 
     327      103344 :     return;
     328             : }
     329             : 
     330      201462 : static Word32 b_inv_sq(
     331             :     const Word32 in32,  /* i  : Input not normalized to inverse */
     332             :     const Word16 exp_in /* i  : input current exponent          */
     333             : )
     334             : {
     335             :     Word16 m_den, exp_den;
     336             :     Word16 div_out;
     337             :     Word32 Ltmp;
     338             : 
     339      201462 :     exp_den = norm_l( in32 );
     340      201462 :     m_den = extract_h( L_shl( in32, exp_den ) );
     341      201462 :     exp_den = add( sub( 30, exp_den ), sub( 16, exp_in ) );
     342             : 
     343      201462 :     m_den = mult_r( m_den, m_den );
     344      201462 :     exp_den = shl( exp_den, 1 );
     345             : 
     346      201462 :     div_out = div_s( 8192, m_den );
     347      201462 :     Ltmp = L_shl_sat( div_out, add( sub( 30 - 13, exp_den ), 15 ) ); /*Q15*/
     348             : 
     349      201462 :     return Ltmp;
     350             : }
     351             : 
     352     4035642 : static Word32 inv_pow(
     353             :     const Word32 re,
     354             :     const Word32 se,
     355             :     const Word16 x )
     356             : {
     357             :     Word16 exp1, exp2;
     358             :     Word16 tmp;
     359             :     Word32 L_tmp;
     360             :     Word32 mh;
     361             :     UWord16 ml;
     362             :     Word32 r0, s0;
     363             : 
     364     4035642 :     IF( re == 0 )
     365             :     {
     366          52 :         exp1 = 30;
     367          52 :         move16();
     368          52 :         r0 = L_deposit_l( 0 );
     369             :     }
     370             :     ELSE
     371             :     {
     372     4035590 :         exp1 = norm_l( re );
     373     4035590 :         tmp = extract_h( L_shl( re, exp1 ) );
     374     4035590 :         L_tmp = L_shr( L_mult_sat( tmp, tmp ), 1 );
     375     4035590 :         Mpy_32_16_ss( L_tmp, x, &mh, &ml );
     376     4035590 :         r0 = L_add( L_tmp, mh );
     377             :     }
     378             : 
     379     4035642 :     IF( se == 0 )
     380             :     {
     381          12 :         exp2 = 30;
     382          12 :         move16();
     383          12 :         s0 = L_deposit_l( 0 );
     384             :     }
     385             :     ELSE
     386             :     {
     387     4035630 :         exp2 = norm_l( se );
     388     4035630 :         tmp = extract_h( L_shl( se, exp2 ) );
     389     4035630 :         L_tmp = L_shr( L_mult_sat( tmp, tmp ), 1 );
     390     4035630 :         Mpy_32_16_ss( L_tmp, x, &mh, &ml );
     391     4035630 :         s0 = L_sub( L_tmp, mh );
     392             :     }
     393             : 
     394     4035642 :     IF( exp1 > exp2 )
     395             :     {
     396     2699730 :         exp1 = shl( sub( exp1, exp2 ), 1 );
     397     2699730 :         r0 = L_shr( r0, exp1 );
     398             : 
     399     2699730 :         exp2 = add( add( exp2, exp2 ), 8 );
     400             :     }
     401             :     ELSE
     402             :     {
     403     1335912 :         exp2 = shl( sub( exp2, exp1 ), 1 );
     404     1335912 :         s0 = L_shr( s0, exp2 );
     405             : 
     406     1335912 :         exp2 = add( add( exp1, exp1 ), 8 );
     407             :     }
     408             : 
     409     4035642 :     r0 = L_add( r0, s0 );
     410     4035642 :     exp1 = norm_l( r0 );
     411     4035642 :     L_tmp = L_shl( r0, exp1 );
     412     4035642 :     tmp = extract_h( L_tmp );
     413     4035642 :     IF( tmp == 0 )
     414             :     {
     415           0 :         return MAX_32;
     416             :     }
     417     4035642 :     tmp = div_s( (Word16) ( ( 1 << 14 ) - 1 ), tmp );
     418     4035642 :     exp1 = add( exp1, exp2 );
     419     4035642 :     L_tmp = L_shr_sat( tmp, sub( 31, exp1 ) ); /* result in Q15 */
     420             : 
     421     4035642 :     return ( L_tmp );
     422             : }
     423             : 
     424             : 
     425             : /*---------------------------------------------------------------------*
     426             :  *  spectautocorr()
     427             :  *
     428             :  *  Computes the autocorrelation r[j] for j = 0, 1, ..., M from
     429             :  *  the power spectrum P(w) by using rectangle rule to approximate
     430             :  *  the integral
     431             :  *
     432             :  *             1     pi
     433             :  *     r[j] = ---    I  P(w) cos(j*w) dw.
     434             :  *            2*pi -pi
     435             :  *
     436             :  *  It is sufficient to evaluate the integrand only from w = 0 to
     437             :  *  w = pi due to the symmetry P(-w) = P(w).  We can further
     438             :  *  employ the relation
     439             :  *
     440             :  *      cos(j*(pi - w)) = (-1)^j cos(j*w)
     441             :  *
     442             :  *  to use symmetries relative to w = pi/2.
     443             :  *
     444             :  *  When applying the rectangle rule, it is useful to separate w = 0,
     445             :  *  w = pi/2, and w = pi.  By using a frequency grid of N points, we
     446             :  *  can express the rectangle rule as
     447             :  *
     448             :  *     r[j] = G[0] + 2*a*G[(N-1)/2] + b*G[N-1]
     449             :  *
     450             :  *                      M
     451             :  *                 + 2 sum (G[i] - G[N-i-1]) cos(j*x[i])
     452             :  *                     i=1
     453             :  *
     454             :  *  where G[i] is the power spectrum at the grid point cos(i*pi/N)
     455             :  *  and M = (N-1)/2 - 1 is the number of the grid points in the
     456             :  *  interval(0, pi/2).
     457             :  *
     458             :  *  The coefficients
     459             :  *
     460             :  *     b = (-1)^j
     461             :  *     a = (1 + (-1)^(j+1))(-1)^floor(j/2)
     462             :  *
     463             :  *  follow from the properties of cosine.  The computation further
     464             :  *  uses the recursion
     465             :  *
     466             :  *     cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w)
     467             :  *
     468             :  *  Note that the autocorrelation can be scaled for convenience,
     469             :  *  because this scaling has no impact on the LP coefficients to be
     470             :  *  calculated from the autocorrelation. The expression of r[j] thus
     471             :  *  omits the division by N.
     472             :  *
     473             :  *  See the powerspect function on the definition of the grid.
     474             :  *
     475             :  *  References
     476             :  *  J. Makhoul, "Spectral linear prediction: properties and
     477             :  *  applications," IEEE Trans. on Acoustics, Speech and Signal
     478             :  *  Processing, Vol. 23, No. 3, pp.283-296, June 1975
     479             :  *---------------------------------------------------------------------*/
     480             : 
     481      103344 : static void spectautocorr_fx(
     482             :     const Word16 x[], /* i: Grid points x[0:m-1]             */
     483             :     const Word16 N,   /* i: Number of grid points            */
     484             :     const Word32 G[], /* i: Power spectrum G[0:N-1]          */
     485             :     Word16 rh[],      /* o: Autocorrelation r[0:M]           */
     486             :     Word16 rl[]       /* o: Autocorrelation r[0:M]           */
     487             : )
     488             : {
     489             :     Word16 c[M + 1]; /* c[j] = cos(j*w) */
     490             :     Word32 gp, gn;
     491             :     Word16 i, j;
     492             :     Word16 imid;
     493             :     Word32 mh;
     494             :     UWord16 ml;
     495             :     Word32 r[M + 1];
     496             :     Word16 exp0;
     497             : 
     498             :     /*---------------------------------------------------------------------*
     499             :      * The mid point of the cosine table x of m entries assuming an odd m.
     500             :      * Only the entries x[0] = cos(pi/m), x[1] = cos(2*pi/m), ...,
     501             :      * x[imid-1] = cos((imid-1)*pi/m) need to be stored due to trivial
     502             :      * cos(0), cos(pi/2), cos(pi), and symmetry relative to pi/2.
     503             :      * Here m = 51.
     504             :      *---------------------------------------------------------------------*/
     505             : 
     506      103344 :     imid = shr( sub( N, 1 ), 1 );
     507      103344 :     move16();
     508             : 
     509             :     /*---------------------------------------------------------------------*
     510             :      * Autocorrelation r[j] at zero lag j = 0 for the upper half of the
     511             :      * unit circle, but excluding the points x = cos(0) and x = cos(pi).
     512             :      *---------------------------------------------------------------------*/
     513             : 
     514      103344 :     r[0] = G[1];
     515      103344 :     move32();
     516     5011596 :     FOR( i = 2; i < N - 1; i++ )
     517             :     {
     518     4908252 :         r[0] = L_add_sat( r[0], G[i] );
     519     4908252 :         move32();
     520             :     }
     521             : 
     522             :     /*---------------------------------------------------------------------*
     523             :      * Initialize the autocorrelation r[j] at lags greater than zero
     524             :      * by adding the midpoint x = cos(pi/2) = 0.
     525             :      *---------------------------------------------------------------------*/
     526             : 
     527      103344 :     r[1] = L_deposit_l( 0 );
     528      103344 :     move32();
     529             : 
     530      103344 :     r[2] = -G[imid];
     531      103344 :     move32();
     532             : 
     533      826752 :     FOR( i = 3; i < M; i += 2 )
     534             :     {
     535      723408 :         r[i] = L_deposit_l( 0 );
     536      723408 :         r[i + 1] = L_negate( r[i - 1] );
     537      723408 :         move32();
     538      723408 :         move32();
     539             :     }
     540             : 
     541             :     /*---------------------------------------------------------------------*
     542             :      * Autocorrelation r[j] at lags j = 1, 2, ..., M.  The computation
     543             :      * employes the relation cos(j*(pi - w)) = (-1)^j cos(j*w) and
     544             :      * cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w) for obtaining
     545             :      * the cosine c[j] = cos(j*w).
     546             :      *---------------------------------------------------------------------*/
     547             : 
     548      103344 :     c[0] = (Word16) 32767;
     549      103344 :     move16(); /* 1.0 in Q15 */
     550     2557470 :     FOR( i = 1; i < imid; i++ )
     551             :     {
     552     2454126 :         gp = L_add_sat( G[i], G[N - i - 1] );
     553     2454126 :         gn = L_sub( G[i], G[N - i - 1] );
     554             : 
     555             :         /*r[1] = L_mac(r[1], x[i-1], gn);*/
     556     2454126 :         Mpy_32_16_ss( gn, x[i - 1], &mh, &ml );
     557     2454126 :         r[1] = L_add_sat( r[1], mh );
     558     2454126 :         move32();
     559     2454126 :         c[1] = x[i - 1];
     560     2454126 :         move16();
     561             : 
     562    19633008 :         FOR( j = 2; j < M; j += 2 )
     563             :         {
     564    17178882 :             c[j] = mult_r( c[j - 1], x[i - 1] );
     565    17178882 :             move16();
     566    17178882 :             c[j] = add_sat( c[j], sub_sat( c[j], c[j - 2] ) );
     567    17178882 :             move16();
     568             : 
     569             :             /*r[j] = L_mac(r[j], c[j], gp);*/
     570    17178882 :             Mpy_32_16_ss( gp, c[j], &mh, &ml );
     571    17178882 :             r[j] = L_add_sat( r[j], mh );
     572    17178882 :             move32();
     573             : 
     574    17178882 :             c[j + 1] = mult_r( c[j], x[i - 1] );
     575    17178882 :             move16();
     576    17178882 :             c[j + 1] = add_sat( c[j + 1], sub_sat( c[j + 1], c[j - 1] ) );
     577    17178882 :             move16();
     578             : 
     579             :             /*r[j+1] = L_mac(r[j+1], c[j+1], gn);*/
     580    17178882 :             Mpy_32_16_ss( gn, c[j + 1], &mh, &ml );
     581    17178882 :             r[j + 1] = L_add_sat( r[j + 1], mh );
     582    17178882 :             move32();
     583             :         }
     584     2454126 :         c[j] = mult_r( c[j - 1], x[i - 1] );
     585     2454126 :         move16();
     586     2454126 :         c[j] = add_sat( c[j], sub_sat( c[j], c[j - 2] ) );
     587     2454126 :         move16();
     588             : 
     589     2454126 :         Mpy_32_16_ss( gp, c[j], &mh, &ml );
     590     2454126 :         r[j] = L_add_sat( r[j], mh );
     591     2454126 :         move32();
     592             :     }
     593             : 
     594             :     /*---------------------------------------------------------------------*
     595             :      * Add the endpoints x = cos(0) = 1 and x = cos(pi) = -1 as
     596             :      * well as the lower half of the unit circle.
     597             :      *---------------------------------------------------------------------*/
     598             : 
     599      103344 :     gp = L_shr( L_add_sat( G[0], G[N - 1] ), 1 );
     600      103344 :     gn = L_shr( L_sub( G[0], G[N - 1] ), 1 );
     601             : 
     602      103344 :     r[0] = L_add_sat( r[0], gp );
     603      103344 :     move32();
     604      103344 :     exp0 = norm_l( r[0] );
     605      103344 :     L_Extract( L_shl( r[0], exp0 ), &rh[0], &rl[0] );
     606             : 
     607      930096 :     FOR( j = 1; j < M; j += 2 )
     608             :     {
     609      826752 :         L_Extract( L_shl( L_add_sat( r[j], gn ), exp0 ), &rh[j], &rl[j] );
     610      826752 :         L_Extract( L_shl( L_add_sat( r[j + 1], gp ), exp0 ), &rh[j + 1], &rl[j + 1] );
     611             :     }
     612             : 
     613      103344 :     return;
     614             : }
     615             : 
     616             : /*---------------------------------------------------------------------*
     617             :  *  zeros2poly()
     618             :  *
     619             :  *  Computes the coefficients of the polynomials
     620             :  *
     621             :  *      R(x) =   prod  (x - x[i]),
     622             :  *             i = 0,2,4,...
     623             :  *
     624             :  *      S(x) =   prod  (x - x[i]),
     625             :  *             i = 1,3,5,...
     626             :  *
     627             :  *  when their zeros x[i] are given for i = 0, 1, ..., n-1. The
     628             :  *  routine assumes n = 1 or even n greater than or equal to 4.
     629             :  *
     630             :  *  The polynomial coefficients are returned in R[0:n/2-1] and
     631             :  *  S[0:n/2-1]. The leading coefficients are in R[0] and S[0].
     632             :  *---------------------------------------------------------------------*/
     633      103344 : static void zeros2poly_fx(
     634             :     Word16 x[], /* i: Q15  Zeros of R(x) and S(x)      */
     635             :     Word32 R[], /* o: Q22  Coefficients of R(x)        */
     636             :     Word32 S[]  /* o: Q22  Coefficients of S(x)        */
     637             : )
     638             : {
     639             :     Word16 xr, xs;
     640             :     Word16 i, j;
     641             :     Word32 mh;
     642             :     UWord16 ml;
     643             : 
     644      103344 :     R[0] = ( 1 << 27 ) - 1;
     645      103344 :     move32();
     646      103344 :     S[0] = ( 1 << 27 ) - 1;
     647      103344 :     move32();
     648      103344 :     R[1] = L_msu( 0, x[0], 1 << 11 );
     649      103344 :     move32();
     650      103344 :     S[1] = L_msu( 0, x[1], 1 << 11 );
     651      103344 :     move32();
     652             : 
     653      826752 :     FOR( i = 2; i <= NC; i++ )
     654             :     {
     655      723408 :         xr = negate( x[2 * i - 2] );
     656      723408 :         xs = negate( x[2 * i - 1] );
     657             : 
     658      723408 :         Mpy_32_16_ss( R[i - 1], xr, &R[i], &ml );
     659      723408 :         Mpy_32_16_ss( S[i - 1], xs, &S[i], &ml );
     660     3617040 :         FOR( j = i - 1; j > 0; j-- )
     661             :         {
     662     2893632 :             Mpy_32_16_ss( R[j - 1], xr, &mh, &ml );
     663     2893632 :             R[j] = L_add( R[j], mh );
     664     2893632 :             move32();
     665     2893632 :             Mpy_32_16_ss( S[j - 1], xs, &mh, &ml );
     666     2893632 :             S[j] = L_add( S[j], mh );
     667     2893632 :             move32();
     668             :         }
     669             :     }
     670             : 
     671      103344 :     return;
     672             : }
     673             : 
     674             : /*---------------------------------------------------------------------*
     675             :  *  polydecomp()
     676             :  *
     677             :  *  Computes the coefficients of the symmetric and antisymmetric
     678             :  *  polynomials P(z) and Q(z) that define the line spectrum pair
     679             :  *  decomposition of a given polynomial A(z) of order n. For even n,
     680             :  *
     681             :  *      P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
     682             :  *      Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1),
     683             :  *
     684             :  *  These polynomials are then expressed in their direct form,
     685             :  *  respectively, R(x) and S(x), on the real axis x = cos w using
     686             :  *  explicit Chebyshev polynomials of the first kind.
     687             :  *
     688             :  *  The coefficients of the polynomials R(x) and S(x) are returned
     689             :  *  in R[0:n/2] and S[0:n/2] for the given linear prediction
     690             :  *  coefficients A[0:n/2]. Note that R(x) and S(x) are formed in
     691             :  *  place such that P(z) is stored in the same array than R(x),
     692             :  *  and Q(z) is stored in the same array than S(x).
     693             :  *
     694             :  *  The routines assumes n = 16.
     695             :  *---------------------------------------------------------------------*/
     696             : 
     697           0 : static void polydecomp_fx(
     698             :     Word16 A[], /* i: Q12 linear prediction coefficients */
     699             :     Word32 R[], /* o: Q20 coefficients of R(x)           */
     700             :     Word32 S[]  /* o: Q20 coefficients of S(x)           */
     701             : )
     702             : {
     703             :     Word16 scale;
     704             :     Word16 i;
     705             :     Word32 Ltmp1, Ltmp2;
     706             : 
     707           0 :     scale = shl( ( 1 << 5 ), norm_s( A[0] ) );
     708             : 
     709           0 :     R[0] = ( 1 << 20 ) - 1;
     710           0 :     move32(); /* Q20 */
     711           0 :     S[0] = ( 1 << 20 ) - 1;
     712           0 :     move32();
     713             : 
     714           0 :     FOR( i = 0; i < NC; i++ )
     715             :     {
     716           0 :         Ltmp1 = L_mult( A[i + 1], scale );
     717             : 
     718           0 :         Ltmp2 = L_msu( Ltmp1, A[M - i], scale );
     719           0 :         Ltmp1 = L_mac( Ltmp1, A[M - i], scale );
     720             : 
     721           0 :         R[i + 1] = L_sub( Ltmp1, R[i] );
     722           0 :         move32();
     723           0 :         S[i + 1] = L_add( Ltmp2, S[i] );
     724           0 :         move32();
     725             :     }
     726             : 
     727           0 :     cheb2poly_fx( R );
     728           0 :     cheb2poly_fx( S );
     729             : 
     730           0 :     return;
     731             : }
     732             : 
     733             : /*---------------------------------------------------------------------*
     734             :  *  cheb2poly_fx()
     735             :  *
     736             :  *  Computes the coefficients of the explicit Chebyshev polynomial
     737             :  *  P(x) = P[0]*x^n + P[1]*x^(n-1) + ... + P[n] given the coefficients
     738             :  *  of the series
     739             :  *
     740             :  *     C(x) = C[0]*T_n(x) + C[1]*T_n-1(x) + ... + C[n]*T_0(x)
     741             :  *
     742             :  *  where T_n(x) is the nth Chebyshev polynomial of the first kind.
     743             :  *  This implementation assumes C[0] = 1. Only value n = 8 is
     744             :  *  supported.
     745             :  *
     746             :  *  The conversion from C(x) to P(x) is done in place such that the
     747             :  *  coefficients of C(x) are given in P[0:8] and those of P(x) are
     748             :  *  returned in the same array.
     749             :  *---------------------------------------------------------------------*/
     750             : 
     751           0 : static void cheb2poly_fx(
     752             :     Word32 L_P[] /* i/o Q20: The coefficients of C(x) and P(x) */
     753             : )
     754             : {
     755             :     Word32 L_C[NC + 1], L_tmp;
     756             :     Word16 i;
     757             : 
     758           0 :     FOR( i = 1; i <= NC; i++ )
     759             :     {
     760           0 :         L_C[i] = L_P[i];
     761           0 :         move32();
     762             :     }
     763             : 
     764           0 :     L_P[0] = ( 1 << 27 ) - 1;
     765           0 :     move32();
     766             : 
     767           0 :     L_P[1] = L_shl( L_C[1], 6 );
     768           0 :     move32(); /*  64.0*C[1] */
     769           0 :     L_P[8] = L_shl( L_C[1], 3 );
     770           0 :     move32(); /*   8.0*C[1] */
     771             : 
     772           0 :     L_P[5] = L_sub( L_P[1], L_P[8] );
     773           0 :     move32(); /*  56.0*C[1] */
     774             : 
     775           0 :     L_P[2] = L_shl( L_C[3], 2 );
     776           0 :     move32();
     777           0 :     L_tmp = L_add( L_C[3], L_P[2] ); /*   5.0*C[3] */
     778           0 :     L_P[7] = L_sub( L_tmp, L_sub( L_P[8], L_C[1] ) );
     779           0 :     move32(); /*  -7.0*C[1] */
     780             : 
     781           0 :     L_P[8] = L_shl( L_C[3], 4 );
     782           0 :     move32(); /*  16.0*C[3] */
     783           0 :     L_P[3] = L_sub( L_P[8], L_shl( L_P[5], 1 ) );
     784           0 :     move32(); /*-112.0*C[1] */
     785             : 
     786           0 :     L_P[5] = L_sub( L_P[5], L_add( L_P[8], L_P[2] ) );
     787           0 :     move32(); /* -20.0*C[3] */
     788             : 
     789           0 :     L_P[2] = L_shl( L_C[5], 2 );
     790           0 :     move32();
     791           0 :     L_P[5] = L_add( L_P[5], L_P[2] );
     792           0 :     move32(); /*   4.0*C[5] */
     793             : 
     794           0 :     L_tmp = L_sub( L_P[7], L_sub( L_P[2], L_C[5] ) ); /*  -3.0*C[5] */
     795           0 :     L_P[7] = L_add( L_tmp, L_C[7] );
     796           0 :     move32(); /*       C[7] */
     797             : 
     798           0 :     L_P[6] = L_shl( L_C[2], 4 );
     799           0 :     move32();
     800           0 :     L_tmp = L_sub( ( 160 << 20 ), L_P[6] );
     801           0 :     L_P[4] = L_sub( L_tmp, L_shl( L_C[2], 5 ) );
     802           0 :     move32(); /* -48.0*C[2] */
     803             : 
     804           0 :     L_tmp = L_add( L_P[6], L_shl( L_C[2], 1 ) ); /*  18.0*C[2] */
     805           0 :     L_P[6] = L_sub( L_tmp, ( 32 << 20 ) );
     806           0 :     move32();
     807             : 
     808           0 :     L_P[8] = L_shl( L_C[4], 3 );
     809           0 :     move32();
     810           0 :     L_P[4] = L_add( L_P[4], L_P[8] );
     811           0 :     move32(); /*   8.0*C[4] */
     812             : 
     813           0 :     L_tmp = L_sub( L_P[6], L_P[8] ); /*  -8.0*C[4] */
     814           0 :     L_P[6] = L_add( L_tmp, L_shl( L_C[6], 1 ) );
     815           0 :     move32(); /*   2.0*C[6] */
     816             : 
     817           0 :     L_tmp = L_shl( L_C[2], 5 ); /*  32.0*C[2] */
     818           0 :     L_P[2] = L_sub( L_tmp, ( 256 << 20 ) );
     819           0 :     move32();
     820             : 
     821           0 :     L_tmp = L_add( ( 1 << 21 ) + 1, L_C[8] );
     822           0 :     L_tmp = L_shr( L_tmp, 1 ); /* 1+0.5*C[8] */
     823           0 :     L_tmp = L_sub( L_tmp, L_C[2] );
     824           0 :     L_tmp = L_add( L_tmp, L_C[4] );
     825           0 :     L_P[8] = L_sub( L_tmp, L_C[6] );
     826           0 :     move32();
     827             : 
     828           0 :     return;
     829             : }

Generated by: LCOV version 1.14