LCOV - code coverage report
Current view: top level - lib_com - pvq_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 319 321 99.4 %
Date: 2025-05-03 01:55:50 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : #include <stdint.h>
       5             : #include "options.h" /* Compilation switches                   */
       6             : #include "prot_fx.h" /* Function prototypes                    */
       7             : #include "cnst.h"    /* Common constants                       */
       8             : #include "rom_com.h" /* Static table prototypes                */
       9             : 
      10             : /*! r: Approximate integer division for positive input using lookup table */
      11      810127 : UWord32 intLimCDivPos_fx(
      12             :     UWord32 NUM, /* Qx */
      13             :     Word16 DEN   /* Q0 */
      14             : )
      15             : {
      16             :     UWord32 UL_ru, UL_rl;
      17      810127 :     Mpy_32_32_uu( UL_lshl( NUM, 1 ), intLimCDivInvDQ31[DEN], &UL_ru, &UL_rl ); /* Qx */
      18      810127 :     return UL_ru;
      19             : }
      20             : 
      21             : /*! r: Approximate integer division for signed input using lookup table */
      22      565328 : static Word32 intLimCDivSigned_fx(
      23             :     Word32 NUM, /* Qx */
      24             :     Word16 DEN  /* Q0 */
      25             : )
      26             : {
      27             :     Word32 L_tmp;
      28             : 
      29      565328 :     L_tmp = intLimCDivPos_fx( L_abs( NUM ), DEN ); /* Qx */
      30      565328 :     if ( NUM < 0 )
      31             :     {
      32       75756 :         L_tmp = L_negate( L_tmp ); /* one op */
      33             :     }
      34      565328 :     return L_tmp;
      35             : }
      36             : 
      37             : /*! r: Approximate integer division for negative input */
      38      624530 : Word16 shrtCDivSignedApprox(
      39             :     const Word16 num, /* Q0 */
      40             :     const Word16 den  /* Q0 */
      41             : )
      42             : {
      43             :     Word16 pool_part;
      44             : 
      45      624530 :     pool_part = extract_h( L_mult( negate( abs_s( num ) ), lim_neg_inv_tbl_fx[den] ) ); /* Q0 */
      46             :     /* neg_in always, positive out always, so that positive truncation(rounding) is used */
      47      624530 :     if ( num < 0 )
      48             :     {
      49       12518 :         pool_part = negate( pool_part ); /* make negative,  one op */
      50             :     }
      51      624530 :     return pool_part;
      52             : }
      53             : 
      54      122264 : static void nearProjQ15_fx(
      55             :     const Word16 x, /* i  : input coefficient   Q15*/
      56             :     Word16 *result  /* o  : projection                  Q15*/
      57             : )
      58             : {
      59             :     const Word16 a[4] = { 14967, -25518, 3415, 32351 }; /* Q15 */
      60      122264 :     move16();
      61      122264 :     move16();
      62      122264 :     move16();
      63      122264 :     move16();
      64             :     Word32 b;
      65             :     UWord16 lsb;
      66             : 
      67      122264 :     b = L_deposit_l( a[0] );
      68      122264 :     b = L_shl( L_deposit_l( add( a[1], extract_h( L_mult0( extract_l( b ), x ) ) ) ), 1 ); /* Q15 */
      69      122264 :     Mpy_32_16_ss( b, x, &b, &lsb );                                                        /* Q15 */
      70      122264 :     b = L_add( L_deposit_l( a[2] ), b );                                                   /* Q15 */
      71      122264 :     Mpy_32_16_ss( b, x, &b, &lsb );                                                        /* Q15 */
      72      122264 :     b = L_add( L_deposit_l( a[3] ), b );                                                   /* Q15 */
      73      122264 :     *result = extract_l( b );                                                              /* Q15 */
      74      122264 :     move16();
      75      122264 :     return;
      76             : }
      77             : 
      78             : /*-------------------------------------------------------------------*
      79             :  * obtainEnergyQuantizerDensity_fx()
      80             :  *
      81             :  *
      82             :  *-------------------------------------------------------------------*/
      83       61853 : void obtainEnergyQuantizerDensity_fx(
      84             :     const Word16 L, /* i  : left vector energy          Q0*/
      85             :     const Word16 R, /* i  : right vector energy         Q0*/
      86             :     Word16 *Density /* o  : quantizer density           Q0*/
      87             : )
      88             : {
      89             :     Word16 Rnrg, den, n;
      90             : 
      91       61853 :     den = sub( shl( L, 1 ), 1 );
      92       61853 :     IF( LE_16( den, 67 ) )
      93             :     {
      94       60191 :         Rnrg = extract_l( intLimCDivPos_fx( L_deposit_l( R ), den ) ); /* Q0 */
      95             :     }
      96             :     ELSE
      97             :     {
      98        1662 :         n = norm_s( den );
      99        1662 :         move16();
     100        1662 :         Rnrg = shr( div_s( R, shl( den, n ) ), sub( 15, n ) ); /* n */
     101             :     }
     102       61853 :     Rnrg = add( Rnrg, 28 ); /* Q0 */
     103             : 
     104       61853 :     Rnrg = s_min( Rnrg, 56 );           /* Q0 */
     105       61853 :     Rnrg = s_min( Rnrg, sub( R, 96 ) ); /* Q0 */
     106             : 
     107       61853 :     Rnrg = s_max( Rnrg, 3 );
     108       61853 :     *Density = obtainEnergyQuantizerDensity_f[Rnrg]; /* Q0 */
     109       61853 :     move16();
     110       61853 :     return;
     111             : }
     112             : 
     113             : 
     114             : /*-------------------------------------------------------------------*
     115             :  * dsDirac2Dirac_fx()
     116             :  *
     117             :  *
     118             :  *-------------------------------------------------------------------*/
     119      624530 : void dsDirac2Dirac_fx(
     120             :     const Word16 dsDiracIndex, /* i  : input index                      Q0*/
     121             :     Word16 *diracs             /* o  : number of diracs         Q0*/
     122             : )
     123             : {
     124      624530 :     *diracs = dsDiracsTab[dsDiracIndex]; /* Q0 */
     125      624530 :     move16();
     126      624530 :     return;
     127             : }
     128             : 
     129      686343 : void dsDiracPerQuanta_fx(
     130             :     const Word16 td,                      /* i  : Length of vector segment              Q0*/
     131             :     const Word16 t_quanta,                /* i  : Assigned number of quanta             Q0*/
     132             :     const Word16 dsm,                     /* i  : Conservative rounding flag    Q0*/
     133             :     const unsigned char *const *frQuanta, /* i  : Quanta lookup table                     */
     134             :     Word16 *DsIdx                         /* o  : Lookup table index                    Q0*/
     135             : )
     136             : {
     137             :     const unsigned char *sv;
     138             :     Word16 nsv;
     139             :     Word16 t_quanta_o;
     140             :     Word16 dsIndex;
     141             :     Word16 i;
     142             : 
     143      686343 :     sv = frQuanta[td]; /* Q0 */
     144      686343 :     nsv = sv[0];
     145      686343 :     move16();
     146      686343 :     t_quanta_o = sub( t_quanta, QUANTAQ3OFFSET ); /* Q0 */
     147             : 
     148      686343 :     IF( GE_16( t_quanta_o, sv[nsv] ) )
     149             :     {
     150       36822 :         *DsIdx = nsv; /* Q0 */
     151       36822 :         move16();
     152       36822 :         return;
     153             :     }
     154             : 
     155      649521 :     IF( LE_16( t_quanta_o, sv[1] ) )
     156             :     {
     157       85484 :         *DsIdx = 1; /* Q0 */
     158       85484 :         move16();
     159       85484 :         return;
     160             :     }
     161             : 
     162             : 
     163      564037 :     dsIndex = shl( 1, frQuanta[0][td] ); /* Q0 */
     164      564037 :     IF( GT_16( t_quanta_o, sv[nsv >> 1] ) )
     165             :     {
     166      186640 :         dsIndex = sub( nsv, dsIndex ); /* Q0 */
     167             :     }
     168     2012273 :     FOR( i = frQuanta[0][td] - 1; i >= 0; i-- )
     169             :     {
     170     1448236 :         dsIndex = add( dsIndex, shl( sub( shl( lshr( sub( sv[dsIndex], t_quanta_o ), 15 ), 1 ), 1 ), i ) ); /* Q0 */
     171             :     }
     172             : 
     173      564037 :     dsIndex = add( dsIndex, lshr( sub( sv[dsIndex], t_quanta_o ), 15 ) ); /* Q0 */
     174      564037 :     dsIndex = sub( dsIndex, lshr( sub( 1, dsIndex ), 15 ) );              /* Q0 */
     175             : 
     176      564037 :     if ( EQ_16( dsm, PVQ_CONS ) )
     177             :     {
     178      222789 :         *DsIdx = dsIndex; /* Q0 */
     179      222789 :         move16();
     180      222789 :         return;
     181             :     }
     182      341248 :     *DsIdx = add( dsIndex, lshr( sub( add( sv[dsIndex + 1], sv[dsIndex] ), shl( t_quanta_o, 1 ) ), 15 ) ); /* Q0 */
     183      341248 :     move16();
     184      341248 :     return;
     185             : }
     186             : 
     187       63453 : void QuantaPerDsDirac_fx(
     188             :     const Word16 td,                         /* i  : Length of vector segment   Q0*/
     189             :     const Word16 dsDiracIndex,               /* i  : Quanta table index         Q0*/
     190             :     const unsigned char *const *dimFrQuanta, /* i  : Quanta lookup table          */
     191             :     Word16 *Quanta                           /* i  : Quanta                     Q0*/
     192             : )
     193             : {
     194       63453 :     *Quanta = dimFrQuanta[td][dsDiracIndex];
     195       63453 :     move16();
     196       63453 :     if ( dsDiracIndex == 0 )
     197             :     {
     198           0 :         *Quanta = -1; /* single op */
     199           0 :         move16();
     200             :     }
     201       63453 :     *Quanta = add( *Quanta, QUANTAQ3OFFSET ); /* Q0 */
     202       63453 :     move16();
     203       63453 :     return;
     204             : }
     205             : 
     206      624530 : void conservativeL1Norm_fx(
     207             :     const Word16 L,       /* i  : Length of vector segment      Q0*/
     208             :     const Word16 Qvec,    /* i  : Assigned number of quanta     Q0*/
     209             :     const Word16 Fcons,   /* i  : Conservative rounding flag    Q0*/
     210             :     const Word16 Qavail,  /* i  : Input quanta remaining        Q0*/
     211             :     const Word16 Qreserv, /* i  : Input quanta in reservoir     Q0*/
     212             :     const Word16 Dspec,   /* i  : assigned diracs from bitalloc Q0*/
     213             :     Word16 *Dvec,         /* o  : actual number of diracs       Q0*/
     214             :     Word16 *Qspare,       /* o  : Output quanta remaining       Q0*/
     215             :     Word16 *Qreservplus,  /* o  : Output quanta in reservoir    Q0*/
     216             :     Word16 *Dspecplus     /* o  : Output number of diracs       Q0*/
     217             : )
     218             : {
     219             : 
     220             :     Word16 Minit, Mprime;
     221             :     Word16 Qtestminus;
     222             :     const unsigned char *frQuantaL;
     223             : 
     224      624530 :     frQuantaL = hBitsN[L];
     225             : 
     226      624530 :     *Qreservplus = add( Qreserv, sub( Qvec, QUANTAQ3OFFSET ) ); /* Q0 */
     227      624530 :     move16();
     228      624530 :     dsDiracPerQuanta_fx( L, Qvec, Fcons, hBitsN, &Minit );
     229             : 
     230      624530 :     Mprime = Minit;
     231      624530 :     move16();
     232             :     DO
     233             :     {
     234      687491 :         Qtestminus = (Word16) frQuantaL[Mprime];
     235      687491 :         move16();
     236      687491 :         *Qspare = sub( Qavail, Qtestminus ); /* Q0 */
     237      687491 :         move16();
     238      687491 :         Mprime = sub( Mprime, 1 ); /* Q0 */
     239             :     }
     240      687491 :     WHILE( ( Mprime >= 0 ) && LT_16( *Qspare, QUANTAQ3OFFSET ) );
     241             : 
     242      624530 :     if ( Mprime < 0 )
     243             :     {
     244       57172 :         *Qspare = add( Qavail, QUANTAQ3OFFSET ); /* single op   Q0*/
     245       57172 :         move16();
     246             :     }
     247      624530 :     dsDirac2Dirac_fx( add( Mprime, 1 ), Dvec );
     248             : 
     249      624530 :     *Dspecplus = add( Dspec, *Dvec ); /* Q0 */
     250      624530 :     move16();
     251      624530 :     *Qreservplus = sub( *Qreservplus, (Word16) frQuantaL[Minit] ); /* Q0 */
     252      624530 :     move16();
     253      624530 :     *Qspare = sub( *Qspare, QUANTAQ3OFFSET ); /* Q0 */
     254      624530 :     move16();
     255             : 
     256      624530 :     return;
     257             : }
     258             : 
     259             : 
     260      562677 : void bandBitsAdjustment_fx(
     261             :     const Word16 Brc,     /* i  : Current number of read quanta in range coder    Q0*/
     262             :     const UWord32 INTrc,  /* i  : Range coder state                               Q0*/
     263             :     const Word16 Bavail,  /* i  : Available number of quanta                      Q3*/
     264             :     const Word16 Nbands,  /* i  : Number of bands                                 Q0*/
     265             :     const Word16 D,       /* i  : Remaining number of bands to encode             Q0*/
     266             :     const Word16 L,       /* i  : Size of current band                            Q0*/
     267             :     const Word16 Bband,   /* i  : Quanta allocation for current band              Q0*/
     268             :     const Word16 Breserv, /* i  : Quanta reservoir                                Q0*/
     269             :     Word16 *Bband_adj,    /* o  : Actual used number of quanta                    Q0*/
     270             :     Word16 *Brem,         /* o  : Quanta remaining                                Q0*/
     271             :     Word16 *Breservplus   /* o  : Quanta pool size                                Q0*/
     272             : )
     273             : {
     274             :     Word16 Btemp;
     275             :     Word16 Bff;
     276             :     Word32 L_tmp;
     277             : 
     278      562677 :     rangeCoderFinalizationFBits_fx( Brc, INTrc, &Bff );
     279             : 
     280      562677 :     IF( LT_16( D, Nbands ) )
     281             :     {
     282      503515 :         L_tmp = L_deposit_l( sub( Breserv, Bff ) );                       /* Q0 */
     283      503515 :         Btemp = extract_l( intLimCDivSigned_fx( L_tmp, s_min( D, 3 ) ) ); /* result always fits in Word16       Q0*/
     284      503515 :         *Breservplus = add( Bband, Breserv );                             /* Q0 */
     285      503515 :         move16();
     286             :     }
     287             :     ELSE
     288             :     {
     289       59162 :         Btemp = 0;
     290       59162 :         move16();
     291       59162 :         *Breservplus = add( Bband, Bff ); /* Q0 */
     292       59162 :         move16();
     293             :     }
     294      562677 :     *Bband_adj = s_min( extract_l( L_mult( L, 40 ) ), Bband ); /* Q3 */
     295      562677 :     move16();
     296      562677 :     *Brem = sub( Bavail, Bff ); /* Q0 */
     297      562677 :     move16();
     298      562677 :     *Bband_adj = s_min( *Brem, add( *Bband_adj, Btemp ) ); /* Q0 */
     299      562677 :     move16();
     300      562677 :     *Bband_adj = s_max( 0, *Bband_adj ); /* Q0 */
     301      562677 :     move16();
     302      562677 :     return;
     303             : }
     304             : 
     305             : 
     306       61132 : static Word16 Ratio_base2Q11_fx(                   /* o :   Q11 */
     307             :                                  const Word16 opp, /* i  : opposite Q15 */
     308             :                                  const Word16 near /* i  : near     Q15 */
     309             : )
     310             : {
     311             :     Word16 mc, nc, ms, ns, d, z;
     312             :     Word16 result;
     313             :     Word32 acc;
     314             : 
     315       61132 :     ns = norm_s( opp );  /* exponent */
     316       61132 :     nc = norm_s( near ); /* exponent */
     317             : 
     318       61132 :     ms = shl( opp, ns );  /* mantissa */
     319       61132 :     mc = shl( near, nc ); /* mantissa */
     320             : 
     321       61132 :     acc = L_mac( 538500224L, mc, -2776 ); /* a0*mc + a1, acc(Q27), a0(Q11), a1(Q27) */
     322       61132 :     z = mac_r( acc, ms, -2776 );          /* z in Q11, a0 in Q11 */
     323       61132 :     d = sub( ms, mc );                    /* d in Q15 */
     324       61132 :     z = mult_r( z, d );                   /* z in Q11 */
     325             : 
     326       61132 :     result = add( z, shl( sub( nc, ns ), 11 ) ); /* Q11 */
     327             : 
     328       61132 :     return result;
     329             : }
     330             : 
     331       61132 : static void Ratio_rQ3_fx(
     332             :     Word16 opp,    /* i  : opposite             Q15*/
     333             :     Word16 near,   /* i  : near                 Q15*/
     334             :     Word16 *result /* o  : ratio                Q3*/
     335             : )
     336             : {
     337             :     Word16 tmp;
     338             : 
     339       61132 :     tmp = add( 1 << 7, Ratio_base2Q11_fx( opp, near ) ); /* Q11 */
     340       61132 :     *result = shr( tmp, 8 );                             /* Q3 */
     341       61132 :     move16();
     342       61132 :     return;
     343             : }
     344             : 
     345             : 
     346       61853 : void densityAngle2RmsProjDec_fx(
     347             :     const Word16 D,        /* i  : density                                              Q0*/
     348             :     const Word16 indexphi, /* i  : decoded index from AR dec    Q0*/
     349             :     Word16 *oppQ15,        /* o  : opposite                                             Q15*/
     350             :     Word16 *nearQ15,       /* o  : near                                                 Q15*/
     351             :     Word16 *oppRatioQ3     /* o  : ratio                                                Q3*/
     352             : )
     353             : {
     354             :     Word16 phiQ14q;
     355             :     Word16 oppTail, nearTail;
     356             : 
     357       61853 :     phiQ14q = (Word16) intLimCDivPos_fx( (UWord32) L_shl( L_deposit_l( indexphi ), 13 ), shr( D, 1 ) ); /* Q14 */
     358       61853 :     move16();
     359       61853 :     if ( indexphi < 0 )
     360             :     {
     361         337 :         phiQ14q = 1 << 13; /* one op */
     362         337 :         move16();
     363             :     }
     364             : 
     365       61853 :     oppTail = shr( sub( 16320, phiQ14q ), 15 );
     366       61853 :     nearTail = shr( sub( phiQ14q, 64 ), 15 );
     367             : 
     368       61853 :     IF( s_or( oppTail, nearTail ) < 0 )
     369             :     {
     370         721 :         *oppQ15 = s_and( oppTail, ( 1 << 15 ) - 1 ); /* Q15 */
     371         721 :         move16();
     372         721 :         *nearQ15 = s_and( nearTail, ( 1 << 15 ) - 1 ); /* Q15 */
     373         721 :         move16();
     374         721 :         *oppRatioQ3 = shl( add( 1, shl( nearTail, 1 ) ), 14 ); /* Q3 */
     375         721 :         move16();
     376             :     }
     377             :     ELSE
     378             :     {
     379       61132 :         nearProjQ15_fx( shl( sub( 1 << 14, phiQ14q ), 1 ), oppQ15 );
     380       61132 :         nearProjQ15_fx( shl( phiQ14q, 1 ), nearQ15 );
     381       61132 :         Ratio_rQ3_fx( *oppQ15, *nearQ15, oppRatioQ3 );
     382             :     }
     383             : 
     384       61853 :     return;
     385             : }
     386             : 
     387       31568 : void densityAngle2RmsProjEnc_fx(
     388             :     const Word16 D,        /* i  : density              Q0*/
     389             :     const Word16 phiQ14uq, /* i  : angle                Q14*/
     390             :     Word16 *indexphi,      /* o  : index                Q0*/
     391             :     Word16 *oppQ15,        /* o  : opposite             Q15*/
     392             :     Word16 *nearQ15,       /* o  : near                 Q15*/
     393             :     Word16 *oppRatioQ3     /* o  : ratio                Q3*/
     394             : )
     395             : {
     396       31568 :     *indexphi = mult_r( shl( D, 1 ), phiQ14uq ); /* Q0 */
     397       31568 :     move16();
     398       31568 :     if ( s_and( D, 1 ) > 0 )
     399             :     {
     400         180 :         *indexphi = -1; /* one op */
     401         180 :         move16();
     402             :     }
     403       31568 :     densityAngle2RmsProjDec_fx( D, *indexphi, oppQ15, nearQ15, oppRatioQ3 );
     404             : 
     405       31568 :     return;
     406             : }
     407             : 
     408       61853 : void NearOppSplitAdjustment_fx(
     409             :     const Word16 qband,    /* i  : quanta for current band         Q0*/
     410             :     const Word16 qzero,    /* i  : range coder finalization quanta Q0*/
     411             :     const Word16 Qac,      /* i  : range coder current quanta      Q0*/
     412             :     const UWord32 INTac,   /* i  : range coder state               Q0*/
     413             :     const Word16 qglobal,  /* i  : quanta input                    Q0*/
     414             :     const Word16 FlagCons, /* i  : conservative rounding flag      Q0*/
     415             :     const Word16 Np,       /* i  : number of parts                 Q0*/
     416             :     const Word16 Nhead,    /* i  : first part                      Q0*/
     417             :     const Word16 Ntail,    /* i  : remaining parts                 Q0*/
     418             :     const Word16 Nnear,    /* i  : length of near component        Q0*/
     419             :     const Word16 Nopp,     /* i  : length of opposite component    Q0*/
     420             :     Word16 oppRQ3,         /* i  : ratio                           Q0*/
     421             :     Word16 *qnear,         /* o  : quantized near                  Q0*/
     422             :     Word16 *qopp,          /* o  : quantized opposite              Q0*/
     423             :     Word16 *qglobalupd     /* o  : quanta remaining                Q0*/
     424             : )
     425             : {
     426             : 
     427             :     Word16 qac, qboth, qskew, qavg, qmin, Midx;
     428             :     Word32 L_QIb, L_qnum;
     429             :     Word16 QIb, QIa;
     430             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     431       61853 :     Flag Overflow = 0;
     432       61853 :     move32();
     433             : #endif
     434             : 
     435       61853 :     rangeCoderFinalizationFBits_fx( Qac, INTac, &qac );
     436       61853 :     qboth = sub( qband, sub( qac, qzero ) ); /* Q0 */
     437             :     /* skew calc code  */
     438       61853 :     qskew = 0;
     439       61853 :     move16();
     440       61853 :     IF( GT_16( Nhead, 1 ) )
     441             :     {
     442       61813 :         qavg = extract_h( L_shl( intLimCDivSigned_fx( L_deposit_l( qboth ), Np ), 16 ) ); /* qboth may be negative      Q0*/
     443       61813 :         dsDiracPerQuanta_fx( Ntail, qavg, FlagCons, hBitsN, &Midx );
     444       61813 :         QuantaPerDsDirac_fx( Nhead, Midx, hBitsN, &qmin );
     445       61813 :         qskew = sub( qavg, qmin ); /* Q0 */
     446       61813 :         qskew = s_max( 0, qskew ); /* Q0 */
     447             :     }                              /* end of skew calc code*/
     448             : 
     449       61853 :     QIa = add( extract_l( intLimCDivPos_fx( (UWord32) L_deposit_l( Nopp ), Nnear ) ), 1 );                   /* always positive Word16 out      Q0*/
     450       61853 :     L_qnum = L_sub( L_deposit_l( sub( sub( add( qband, qzero ), qac ), qskew ) ), L_mult0( Nopp, oppRQ3 ) ); /* Q0 */
     451             : 
     452       61853 :     L_QIb = L_deposit_l( 0 );
     453       61853 :     IF( L_qnum > 0 )
     454             :     {
     455       60879 :         L_QIb = (Word32) intLimCDivPos_fx( L_qnum, QIa ); /* Q0 */
     456             :     }
     457       61853 :     *qnear = qboth; /* Q3 */
     458       61853 :     move16();
     459       61853 :     QIb = extract_h( L_shl_o( L_QIb, 16, &Overflow ) ); /* may saturate             Q0*/
     460       61853 :     if ( LE_16( QIb, qboth ) )
     461             :     {
     462       61006 :         *qnear = QIb; /* Q0 */
     463       61006 :         move16();
     464             :     }
     465       61853 :     *qopp = sub( qboth, *qnear ); /* Q0 */
     466       61853 :     move16();
     467       61853 :     *qglobalupd = sub( qglobal, sub( qac, qzero ) ); /* Q0 */
     468       61853 :     move16();
     469             : 
     470       61853 :     return;
     471             : }
     472             : 
     473             : 
     474             : /*--------------------------------------------------------------------------*
     475             :  * apply_gain()
     476             :  *
     477             :  * Apply gain
     478             :  *--------------------------------------------------------------------------*/
     479             : 
     480       57713 : void apply_gain_fx(
     481             :     const Word16 *ord,        /* i  : Indices for energy order               Q0      */
     482             :     const Word16 *band_start, /* i  : Sub band start indices                 Q0      */
     483             :     const Word16 *band_end,   /* i  : Sub band end indices                   Q0      */
     484             :     const Word16 num_sfm,     /* i  : Number of bands                        Q0      */
     485             :     const Word16 *gains,      /* i  : Band gain vector                       Qx     */
     486             :     Word16 *xq                /* i/o: Float synthesis / Gain adjusted synth  Q15/Qx */
     487             : )
     488             : {
     489             :     Word16 band, i;
     490             :     Word16 g; /* Q12 */
     491             : 
     492      901946 :     FOR( band = 0; band < num_sfm; band++ )
     493             :     {
     494      844233 :         g = gains[ord[band]];
     495      844233 :         move16();
     496    15530897 :         FOR( i = band_start[band]; i < band_end[band]; i++ )
     497             :         {
     498             :             /*xq[i] *= g; */
     499    14686664 :             xq[i] = mult_r( g, xq[i] );
     500    14686664 :             move16(); /*12+15+1-16=12 */
     501             :         }
     502             :     }
     503             : 
     504       57713 :     return;
     505             : }
     506             : 
     507             : /*--------------------------------------------------------------------------*
     508             :  * fine_gain_quant_fx()
     509             :  *
     510             :  * Fine gain quantization
     511             :  *--------------------------------------------------------------------------*/
     512       29425 : void fine_gain_quant_fx(
     513             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle                                     */
     514             :     const Word16 *ord,       /* i  : Indices for energy order                 Q0  */
     515             :     const Word16 num_sfm,    /* i  : Number of bands                          Q0  */
     516             :     const Word16 *gain_bits, /* i  : Gain adjustment bits per sub band        Q0  */
     517             :     Word16 *fg_pred,         /* i/o: Predicted gains / Corrected gains        Q12 */
     518             :     const Word16 *gopt       /* i  : Optimal gains                            Q12 */
     519             : )
     520             : {
     521             :     Word16 band;
     522             :     Word16 gbits;
     523             :     Word16 idx;
     524             :     Word16 gain_db, gain_dbq;
     525             :     Word16 err;
     526             : 
     527             :     Word16 tmp1, tmp2, exp1, exp2;
     528             :     Word32 L_tmp;
     529             :     UWord16 lsb;
     530             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     531       29425 :     Flag Overflow = 0;
     532       29425 :     move32();
     533             : #endif
     534             : 
     535      464086 :     FOR( band = 0; band < num_sfm; band++ )
     536             :     {
     537      434661 :         gbits = gain_bits[ord[band]]; /* Q0 */
     538      434661 :         move16();
     539      434661 :         test();
     540      434661 :         IF( fg_pred[band] != 0 && gbits > 0 )
     541             :         {
     542       34836 :             exp1 = norm_s( gopt[band] );
     543       34836 :             exp1 = sub( exp1, 1 );
     544       34836 :             tmp1 = shl( gopt[band], exp1 );
     545       34836 :             exp2 = norm_s( fg_pred[band] );
     546       34836 :             tmp2 = shl( fg_pred[band], exp2 ); /* Q12 + exp2 */
     547       34836 :             exp1 = add( 15, sub( exp1, exp2 ) );
     548       34836 :             err = div_s( tmp1, tmp2 ); /* Q15 */
     549       34836 :             tmp1 = norm_s( err );
     550       34836 :             exp2 = Log2_norm_lc( L_deposit_h( shl( err, tmp1 ) ) );
     551       34836 :             tmp1 = sub( 14, tmp1 );
     552       34836 :             tmp1 = sub( tmp1, exp1 );
     553       34836 :             L_tmp = L_Comp( tmp1, exp2 );
     554       34836 :             Mpy_32_16_ss( L_tmp, 24660, &L_tmp, &lsb ); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */
     555       34836 :             gain_db = round_fx_sat( L_shl_o( L_tmp, 17, &Overflow ) );
     556             : 
     557       34836 :             idx = squant_fx( gain_db, &gain_dbq, finegain_fx[gbits - 1], gain_cb_size[gbits - 1] );
     558       34836 :             push_indice( hBstr, IND_PVQ_FINE_GAIN, idx, gbits );
     559             : 
     560       34836 :             L_tmp = L_mult0( gain_dbq, 21771 ); /* 21771=0.05*log2(10) */ /* 14+17=31 */
     561       34836 :             L_tmp = L_shr( L_tmp, 15 );                                   /* Q16 */
     562       34836 :             tmp1 = L_Extract_lc( L_tmp, &exp1 );
     563       34836 :             tmp1 = abs_s( tmp1 );
     564       34836 :             tmp1 = extract_l( Pow2( 14, tmp1 ) );
     565       34836 :             exp1 = sub( 14, exp1 );
     566             : 
     567       34836 :             L_tmp = L_mult0( fg_pred[band], tmp1 );                              /*12+exp1 */
     568       34836 :             fg_pred[band] = round_fx_sat( L_shl_sat( L_tmp, sub( 16, exp1 ) ) ); /*12+exp1+16-exp1-16=12 */
     569       34836 :             move16();
     570             :         }
     571             :     }
     572             : 
     573       29425 :     return;
     574             : }
     575             : 
     576             : /*-------------------------------------------------------------------*
     577             :  * srt_vec_ind()
     578             :  *
     579             :  *  sort vector and save  sorting indeces
     580             :  *-------------------------------------------------------------------*/
     581             : 
     582      605940 : void srt_vec_ind16_fx(
     583             :     const Word16 *linear, /* linear input                               Q3*/
     584             :     Word16 *srt,          /* sorted output                              Q3*/
     585             :     Word16 *I,            /* index for sorted output    Q0*/
     586             :     Word16 length         /* Q0 */
     587             : )
     588             : {
     589             :     Word16 pos, npos;
     590             :     Word16 idxMem;
     591             :     Word16 valMem;
     592             : 
     593             :     /*initilize */
     594     1540151 :     FOR( pos = 0; pos < length; pos++ )
     595             :     {
     596      934211 :         I[pos] = pos; /* Q0 */
     597      934211 :         move16();
     598             :     }
     599             : 
     600      605940 :     Copy( linear, srt, length ); /* Q3 */
     601             : 
     602             :     /* now iterate */
     603      934211 :     FOR( pos = 0; pos < ( length - 1 ); pos++ )
     604             :     {
     605     1442244 :         FOR( npos = ( pos + 1 ); npos < length; npos++ )
     606             :         {
     607     1113973 :             IF( LT_16( srt[npos], srt[pos] ) )
     608             :             {
     609      517806 :                 idxMem = I[pos]; /* Q0 */
     610      517806 :                 move16();
     611      517806 :                 I[pos] = I[npos]; /* Q0 */
     612      517806 :                 move16();
     613      517806 :                 I[npos] = idxMem; /* Q0 */
     614      517806 :                 move16();
     615             : 
     616      517806 :                 valMem = srt[pos]; /* Q0 */
     617      517806 :                 move16();
     618      517806 :                 srt[pos] = srt[npos]; /* Q0 */
     619      517806 :                 move16();
     620      517806 :                 srt[npos] = valMem; /* Q0 */
     621      517806 :                 move16();
     622             :             }
     623             :         }
     624             :     }
     625             : 
     626      605940 :     return;
     627             : }
     628             : 
     629             : /*-----------------------------------------------------------------------------
     630             :  * atan2_fx():
     631             :  *
     632             :  * Approximates arctan piecewise with various 4th to 5th order least square fit
     633             :  * polynomials for input in 5 segments:
     634             :  *   - 0.0 to 1.0
     635             :  *   - 1.0 to 2.0
     636             :  *   - 2.0 to 4.0
     637             :  *   - 4.0 to 8.0
     638             :  *   - 8.0 to infinity
     639             :  *---------------------------------------------------------------------------*/
     640     6839398 : Word16 atan2_fx(                 /* o: Angle between 0 and PI/2 radian (Q14) */
     641             :                  const Word32 y, /* i  : near side (Argument must be positive) (Q15) */
     642             :                  const Word32 x  /* i  : opposite side (Q15)                         */
     643             : )
     644             : {
     645             :     Word32 acc, arg;
     646             :     Word16 man, expo, reciprocal;
     647             :     Word16 angle, w, z;
     648             : 
     649     6839398 :     IF( x == 0 )
     650             :     {
     651       54813 :         return 25736; /* PI/2 in Q14 */
     652             :     }
     653     6784585 :     man = ratio( y, x, &expo );      /* man in Q14 */
     654     6784585 :     expo = sub( expo, ( 15 - 14 ) ); /* Now, man is considered in Q15 */
     655     6784585 :     arg = L_shr( (Word32) man, expo );
     656             : 
     657     6784585 :     IF( L_shr( arg, 3 + 15 ) != 0 )
     658             :     /*===============================*
     659             :      *      8.0 <= x < infinity      *
     660             :      *===============================*/
     661             :     {
     662             :         /* atan(x) = PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ...
     663             :          *         ~ PI/2 - 1/x, for x >= 8.
     664             :          */
     665      401885 :         expo = norm_l( arg );
     666      401885 :         man = extract_h( L_shl( arg, expo ) );
     667      401885 :         reciprocal = div_s( 0x3fff, man );
     668      401885 :         expo = sub( 15 + 1, expo );
     669      401885 :         reciprocal = shr( reciprocal, expo ); /* Q14 */
     670      401885 :         angle = sub( 25736, reciprocal );     /* Q14   (PI/2 - 1/x) */
     671             : 
     672             :         /* For 8.0 <= x < 10.0, 1/(5x^5) is not completely negligible.
     673             :          * For more accurate result, add very small correction term.
     674             :          */
     675      401885 :         if ( LT_32( L_shr( arg, 15 ), 10L ) )
     676             :         {
     677       84006 :             angle = add( angle, 8 ); /* Add tiny correction term. */
     678             :         }
     679             :     }
     680     6382700 :     ELSE IF( L_shr( arg, 2 + 15 ) != 0 )
     681             :     /*==========================*
     682             :      *      4.0 <= x < 8.0      *
     683             :      *==========================*/
     684             :     {
     685             :         /* interval: [3.999, 8.001]
     686             :          * atan(x) ~ (((a0*x     +   a1)*x   + a2)*x   + a3)*x   + a4
     687             :          *         = (((a0*8*y   +   a1)*8*y + a2)*8*y + a3)*8*y + a4   Substitute 8*y -> x
     688             :          *         = (((a0*8^3*y + a1*8^2)*y + a2*8)*y + a3)*8*y + a4
     689             :          *         = (((    c0*y +     c1)*y +   c2)*y + c3)*8*y + c4,
     690             :          *  where y = x/8
     691             :          *   and a0 = -1.28820869667651e-04, a1 = 3.88263533346295e-03,
     692             :          *       a2 = -4.64216306484597e-02, a3 = 2.75986060068931e-01,
     693             :          *       a4 = 7.49208077809799e-01.
     694             :          */
     695      261521 :         w = extract_l( L_shr( arg, 3 ) );               /* Q15  y = x/8 */
     696      261521 :         acc = L_add( 533625337L, 0 );                   /* Q31  c1 = a1*8^2 */
     697      261521 :         z = mac_r( acc, w, -2161 );                     /* Q15  c0 = a0*8^3 */
     698      261521 :         acc = L_add( -797517542L, 0 );                  /* Q31  c2 = a2*8 */
     699      261521 :         z = mac_r( acc, w, z );                         /* Q15 */
     700      261521 :         acc = L_add( 592675551L, 0 );                   /* Q31  c3 = a3 */
     701      261521 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q12) */
     702      261521 :         acc = L_add( 201114012L, 0 );                   /* Q28  c4 = a4 */
     703      261521 :         acc = L_mac( acc, w, z );                       /* Q28 */
     704      261521 :         angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14 result of atan(x), where 4 <= x < 8 */
     705             :     }
     706     6121179 :     ELSE IF( L_shr( arg, 1 + 15 ) != 0 )
     707             :     /*==========================*
     708             :      *      2.0 <= x < 4.0      *
     709             :      *==========================*/
     710             :     {
     711             :         /* interval: [1.999, 4.001]
     712             :          * atan(x) ~ (((a0*x    + a1)*x   +   a2)*x   + a3)*x   + a4
     713             :          *         = (((a0*4*y  + a1)*4*y +   a2)*4*y + a3)*4*y + a4   Substitute 4*y -> x
     714             :          *         = (((a0*16*y + a1*4)*y +   a2)*4*y + a3)*4*y + a4
     715             :          *         = (((a0*32*y + a1*8)*y + a2*2)*2*y + a3)*4*y + a4
     716             :          *         = (((   c0*y +   c1)*y +   c2)*2*y + c3)*4*y + c4,
     717             :          *  where y = x/4
     718             :          *   and a0 = -0.00262378195660943, a1 = 0.04089687039888652,
     719             :          *       a2 = -0.25631148958325911, a3 = 0.81685854627399479,
     720             :          *       a4 = 0.21358070563097167
     721             :          * */
     722      413088 :         w = extract_l( L_shr( arg, 2 ) );               /* Q15  y = x/4 */
     723      413088 :         acc = L_add( 702602883L, 0 );                   /* Q31  c1 = a1*8 */
     724      413088 :         z = mac_r( acc, w, -2751 );                     /* Q15  c0 = a0*32 */
     725      413088 :         acc = L_add( -1100849465L, 0 );                 /* Q31  c2 = a2*2 */
     726      413088 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q14) */
     727      413088 :         acc = L_add( 877095185L, 0 );                   /* Q30  c3 = a3 */
     728      413088 :         z = mac_r( acc, w, z );                         /* z (in:Q14, out:Q12) */
     729      413088 :         acc = L_add( 57332634L, 0 );                    /* Q28  c4 = a4 */
     730      413088 :         acc = L_mac( acc, w, z );                       /* Q28 */
     731      413088 :         angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14  result of atan(x) where 2 <= x < 4 */
     732             :     }
     733     5708091 :     ELSE IF( L_shr( arg, 15 ) != 0 )
     734             :     /*==========================*
     735             :      *      1.0 <= x < 2.0      *
     736             :      *==========================*/
     737             :     {
     738             :         /* interval: [0.999, 2.001]
     739             :          * atan(x) ~ (((a0*x   +  1)*x   + a2)*x   +   a3)*x   + a4
     740             :          *         = (((a0*2*y + a1)*2*y + a2)*2*y +   a3)*2*y + a4    Substitute 2*y -> x
     741             :          *         = (((a0*4*y + a1*2)*y + a2)*2*y +   a3)*2*y + a4
     742             :          *         = (((a0*4*y + a1*2)*y + a2)*y   + a3/2)*4*y + a4
     743             :          *         = (((  c0*y +   c1)*y + c2)*y   +   c3)*4*y + c4,
     744             :          *  where y = x/2
     745             :          *   and a0 = -0.0160706457245251, a1 = 0.1527106504065224,
     746             :          *       a2 = -0.6123208404800871, a3 = 1.3307896976322915,
     747             :          *       a4 = -0.0697089375247448
     748             :          */
     749     1063623 :         w = extract_l( L_shr( arg, 1 ) ); /* Q15  y= x/2 */
     750     1063623 :         acc = L_add( 655887249L, 0 );     /* Q31  c1 = a1*2 */
     751     1063623 :         z = mac_r( acc, w, -2106 );       /* Q15  c0 = a0*4 */
     752     1063623 :         acc = L_add( -1314948992L, 0 );   /* Q31  c2 = a2 */
     753     1063623 :         z = mac_r( acc, w, z );
     754     1063623 :         acc = L_add( 1428924557L, 0 );                  /* Q31  c3 = a3/2 */
     755     1063623 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q13) */
     756     1063623 :         acc = L_add( -37424701L, 0 );                   /* Q29  c4 = a4 */
     757     1063623 :         acc = L_mac( acc, w, z );                       /* Q29 */
     758     1063623 :         angle = extract_l( L_shr( acc, ( 29 - 14 ) ) ); /* Q14  result of atan(x) where 1 <= x < 2 */
     759             :     }
     760             :     ELSE
     761             :     /*==========================*
     762             :      *      0.0 <= x < 1.0      *
     763             :      *==========================*/
     764             :     {
     765             :         /* interval: [-0.001, 1.001]
     766             :          * atan(x) ~ ((((a0*x   +   a1)*x   + a2)*x + a3)*x + a4)*x + a5
     767             :          *         = ((((a0*2*x + a1*2)*x/2 + a2)*x + a3)*x + a4)*x + a5
     768             :          *         = ((((  c0*x +   c1)*x/2 + c2)*x + c3)*x + c4)*x + c5
     769             :          *  where
     770             :          *    a0 = -5.41182677118661e-02, a1 = 2.76690449232515e-01,
     771             :          *    a2 = -4.63358392562492e-01, a3 = 2.87188466598566e-02,
     772             :          *    a4 =  9.97438122814383e-01, a5 = 5.36158556179092e-05.
     773             :          */
     774     4644468 :         w = extract_l( arg );                 /* Q15 */
     775     4644468 :         acc = L_add( 1188376431L, 0 );        /* Q31  c1 = a1*2 */
     776     4644468 :         z = mac_r( acc, w, -3547 );           /* Q15  c0 = a0*2 */
     777     4644468 :         acc = L_add( -995054571L, 0 );        /* Q31  c2 = a2 */
     778     4644468 :         z = extract_h( L_mac0( acc, w, z ) ); /* Q15  non-fractional mode multiply */
     779     4644468 :         acc = L_add( 61673254L, 0 );          /* Q31  c3 = a3 */
     780     4644468 :         z = mac_r( acc, w, z );
     781     4644468 :         acc = L_add( 2141982059L, 0 ); /* Q31  c4 = a4 */
     782     4644468 :         z = mac_r( acc, w, z );
     783     4644468 :         acc = L_add( 115139L, 0 );                  /* Q31  c5 = a5 */
     784     4644468 :         acc = L_mac( acc, w, z );                   /* Q31 */
     785     4644468 :         angle = extract_l( L_shr( acc, 31 - 14 ) ); /* Q14  result of atan(x), where 0 <= x < 1 */
     786             :     }
     787             : 
     788     6784585 :     return angle; /* Q14 between 0 and PI/2 radian. */
     789             : }

Generated by: LCOV version 1.14