LCOV - code coverage report
Current view: top level - lib_com - pvq_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 275 317 86.8 %
Date: 2025-08-23 01:22:27 Functions: 17 19 89.5 %

          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      394760 : UWord32 intLimCDivPos_fx(
      12             :     UWord32 NUM, /* Qx */
      13             :     Word16 DEN   /* Q0 */
      14             : )
      15             : {
      16             :     UWord32 UL_ru, UL_rl;
      17      394760 :     Mpy_32_32_uu( UL_lshl( NUM, 1 ), intLimCDivInvDQ31[DEN], &UL_ru, &UL_rl ); /* Qx */
      18      394760 :     return UL_ru;
      19             : }
      20             : 
      21             : /*! r: Approximate integer division for signed input using lookup table */
      22      274661 : static Word32 intLimCDivSigned_fx(
      23             :     Word32 NUM, /* Qx */
      24             :     Word16 DEN  /* Q0 */
      25             : )
      26             : {
      27             :     Word32 L_tmp;
      28             : 
      29      274661 :     L_tmp = intLimCDivPos_fx( L_abs( NUM ), DEN ); /* Qx */
      30      274661 :     if ( NUM < 0 )
      31             :     {
      32       36466 :         L_tmp = L_negate( L_tmp ); /* one op */
      33             :     }
      34      274661 :     return L_tmp;
      35             : }
      36             : 
      37             : /*! r: Approximate integer division for negative input */
      38      303123 : Word16 shrtCDivSignedApprox(
      39             :     const Word16 num, /* Q0 */
      40             :     const Word16 den  /* Q0 */
      41             : )
      42             : {
      43             :     Word16 pool_part;
      44             : 
      45      303123 :     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      303123 :     if ( num < 0 )
      48             :     {
      49        6178 :         pool_part = negate( pool_part ); /* make negative,  one op */
      50             :     }
      51      303123 :     return pool_part;
      52             : }
      53             : 
      54       59996 : 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       59996 :     move16();
      61       59996 :     move16();
      62       59996 :     move16();
      63       59996 :     move16();
      64             :     Word32 b;
      65             :     UWord16 lsb;
      66             : 
      67       59996 :     b = L_deposit_l( a[0] );
      68       59996 :     b = L_shl( L_deposit_l( add( a[1], extract_h( L_mult0( extract_l( b ), x ) ) ) ), 1 ); /* Q15 */
      69       59996 :     Mpy_32_16_ss( b, x, &b, &lsb );                                                        /* Q15 */
      70       59996 :     b = L_add( L_deposit_l( a[2] ), b );                                                   /* Q15 */
      71       59996 :     Mpy_32_16_ss( b, x, &b, &lsb );                                                        /* Q15 */
      72       59996 :     b = L_add( L_deposit_l( a[3] ), b );                                                   /* Q15 */
      73       59996 :     *result = extract_l( b );                                                              /* Q15 */
      74       59996 :     move16();
      75       59996 :     return;
      76             : }
      77             : 
      78             : /*-------------------------------------------------------------------*
      79             :  * obtainEnergyQuantizerDensity_fx()
      80             :  *
      81             :  *
      82             :  *-------------------------------------------------------------------*/
      83       30342 : 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       30342 :     den = sub( shl( L, 1 ), 1 );
      92       30342 :     IF( LE_16( den, 67 ) )
      93             :     {
      94       29544 :         Rnrg = extract_l( intLimCDivPos_fx( L_deposit_l( R ), den ) ); /* Q0 */
      95             :     }
      96             :     ELSE
      97             :     {
      98         798 :         n = norm_s( den );
      99         798 :         move16();
     100         798 :         Rnrg = shr( div_s( R, shl( den, n ) ), sub( 15, n ) ); /* n */
     101             :     }
     102       30342 :     Rnrg = add( Rnrg, 28 ); /* Q0 */
     103             : 
     104       30342 :     Rnrg = s_min( Rnrg, 56 );           /* Q0 */
     105       30342 :     Rnrg = s_min( Rnrg, sub( R, 96 ) ); /* Q0 */
     106             : 
     107       30342 :     Rnrg = s_max( Rnrg, 3 );
     108       30342 :     *Density = obtainEnergyQuantizerDensity_f[Rnrg]; /* Q0 */
     109       30342 :     move16();
     110       30342 :     return;
     111             : }
     112             : 
     113             : 
     114             : /*-------------------------------------------------------------------*
     115             :  * dsDirac2Dirac_fx()
     116             :  *
     117             :  *
     118             :  *-------------------------------------------------------------------*/
     119      303123 : void dsDirac2Dirac_fx(
     120             :     const Word16 dsDiracIndex, /* i  : input index                      Q0*/
     121             :     Word16 *diracs             /* o  : number of diracs         Q0*/
     122             : )
     123             : {
     124      303123 :     *diracs = dsDiracsTab[dsDiracIndex]; /* Q0 */
     125      303123 :     move16();
     126      303123 :     return;
     127             : }
     128             : 
     129      333425 : 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      333425 :     sv = frQuanta[td]; /* Q0 */
     144      333425 :     nsv = sv[0];
     145      333425 :     move16();
     146      333425 :     t_quanta_o = sub( t_quanta, QUANTAQ3OFFSET ); /* Q0 */
     147             : 
     148      333425 :     IF( GE_16( t_quanta_o, sv[nsv] ) )
     149             :     {
     150       17797 :         *DsIdx = nsv; /* Q0 */
     151       17797 :         move16();
     152       17797 :         return;
     153             :     }
     154             : 
     155      315628 :     IF( LE_16( t_quanta_o, sv[1] ) )
     156             :     {
     157       40129 :         *DsIdx = 1; /* Q0 */
     158       40129 :         move16();
     159       40129 :         return;
     160             :     }
     161             : 
     162             : 
     163      275499 :     dsIndex = shl( 1, frQuanta[0][td] ); /* Q0 */
     164      275499 :     IF( GT_16( t_quanta_o, sv[nsv >> 1] ) )
     165             :     {
     166       91149 :         dsIndex = sub( nsv, dsIndex ); /* Q0 */
     167             :     }
     168      984782 :     FOR( i = frQuanta[0][td] - 1; i >= 0; i-- )
     169             :     {
     170      709283 :         dsIndex = add( dsIndex, shl( sub( shl( lshr( sub( sv[dsIndex], t_quanta_o ), 15 ), 1 ), 1 ), i ) ); /* Q0 */
     171             :     }
     172             : 
     173      275499 :     dsIndex = add( dsIndex, lshr( sub( sv[dsIndex], t_quanta_o ), 15 ) ); /* Q0 */
     174      275499 :     dsIndex = sub( dsIndex, lshr( sub( 1, dsIndex ), 15 ) );              /* Q0 */
     175             : 
     176      275499 :     if ( EQ_16( dsm, PVQ_CONS ) )
     177             :     {
     178      106839 :         *DsIdx = dsIndex; /* Q0 */
     179      106839 :         move16();
     180      106839 :         return;
     181             :     }
     182      168660 :     *DsIdx = add( dsIndex, lshr( sub( add( sv[dsIndex + 1], sv[dsIndex] ), shl( t_quanta_o, 1 ) ), 15 ) ); /* Q0 */
     183      168660 :     move16();
     184      168660 :     return;
     185             : }
     186             : 
     187       31054 : 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       31054 :     *Quanta = dimFrQuanta[td][dsDiracIndex];
     195       31054 :     move16();
     196       31054 :     if ( dsDiracIndex == 0 )
     197             :     {
     198           0 :         *Quanta = -1; /* single op */
     199           0 :         move16();
     200             :     }
     201       31054 :     *Quanta = add( *Quanta, QUANTAQ3OFFSET ); /* Q0 */
     202       31054 :     move16();
     203       31054 :     return;
     204             : }
     205             : 
     206      303123 : 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      303123 :     frQuantaL = hBitsN[L];
     225             : 
     226      303123 :     *Qreservplus = add( Qreserv, sub( Qvec, QUANTAQ3OFFSET ) ); /* Q0 */
     227      303123 :     move16();
     228      303123 :     dsDiracPerQuanta_fx( L, Qvec, Fcons, hBitsN, &Minit );
     229             : 
     230      303123 :     Mprime = Minit;
     231      303123 :     move16();
     232             :     DO
     233             :     {
     234      332911 :         Qtestminus = (Word16) frQuantaL[Mprime];
     235      332911 :         move16();
     236      332911 :         *Qspare = sub( Qavail, Qtestminus ); /* Q0 */
     237      332911 :         move16();
     238      332911 :         Mprime = sub( Mprime, 1 ); /* Q0 */
     239             :     }
     240      332911 :     WHILE( ( Mprime >= 0 ) && LT_16( *Qspare, QUANTAQ3OFFSET ) );
     241             : 
     242      303123 :     if ( Mprime < 0 )
     243             :     {
     244       26963 :         *Qspare = add( Qavail, QUANTAQ3OFFSET ); /* single op   Q0*/
     245       26963 :         move16();
     246             :     }
     247      303123 :     dsDirac2Dirac_fx( add( Mprime, 1 ), Dvec );
     248             : 
     249      303123 :     *Dspecplus = add( Dspec, *Dvec ); /* Q0 */
     250      303123 :     move16();
     251      303123 :     *Qreservplus = sub( *Qreservplus, (Word16) frQuantaL[Minit] ); /* Q0 */
     252      303123 :     move16();
     253      303123 :     *Qspare = sub( *Qspare, QUANTAQ3OFFSET ); /* Q0 */
     254      303123 :     move16();
     255             : 
     256      303123 :     return;
     257             : }
     258             : 
     259             : 
     260      272781 : 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      272781 :     rangeCoderFinalizationFBits_fx( Brc, INTrc, &Bff );
     279             : 
     280      272781 :     IF( LT_16( D, Nbands ) )
     281             :     {
     282      244359 :         L_tmp = L_deposit_l( sub( Breserv, Bff ) );                       /* Q0 */
     283      244359 :         Btemp = extract_l( intLimCDivSigned_fx( L_tmp, s_min( D, 3 ) ) ); /* result always fits in Word16       Q0*/
     284      244359 :         *Breservplus = add( Bband, Breserv );                             /* Q0 */
     285      244359 :         move16();
     286             :     }
     287             :     ELSE
     288             :     {
     289       28422 :         Btemp = 0;
     290       28422 :         move16();
     291       28422 :         *Breservplus = add( Bband, Bff ); /* Q0 */
     292       28422 :         move16();
     293             :     }
     294      272781 :     *Bband_adj = s_min( extract_l( L_mult( L, 40 ) ), Bband ); /* Q3 */
     295      272781 :     move16();
     296      272781 :     *Brem = sub( Bavail, Bff ); /* Q0 */
     297      272781 :     move16();
     298      272781 :     *Bband_adj = s_min( *Brem, add( *Bband_adj, Btemp ) ); /* Q0 */
     299      272781 :     move16();
     300      272781 :     *Bband_adj = s_max( 0, *Bband_adj ); /* Q0 */
     301      272781 :     move16();
     302      272781 :     return;
     303             : }
     304             : 
     305             : 
     306       29998 : 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       29998 :     ns = norm_s( opp );  /* exponent */
     316       29998 :     nc = norm_s( near ); /* exponent */
     317             : 
     318       29998 :     ms = shl( opp, ns );  /* mantissa */
     319       29998 :     mc = shl( near, nc ); /* mantissa */
     320             : 
     321       29998 :     acc = L_mac( 538500224L, mc, -2776 ); /* a0*mc + a1, acc(Q27), a0(Q11), a1(Q27) */
     322       29998 :     z = mac_r( acc, ms, -2776 );          /* z in Q11, a0 in Q11 */
     323       29998 :     d = sub( ms, mc );                    /* d in Q15 */
     324       29998 :     z = mult_r( z, d );                   /* z in Q11 */
     325             : 
     326       29998 :     result = add( z, shl( sub( nc, ns ), 11 ) ); /* Q11 */
     327             : 
     328       29998 :     return result;
     329             : }
     330             : 
     331       29998 : 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       29998 :     tmp = add( 1 << 7, Ratio_base2Q11_fx( opp, near ) ); /* Q11 */
     340       29998 :     *result = shr( tmp, 8 );                             /* Q3 */
     341       29998 :     move16();
     342       29998 :     return;
     343             : }
     344             : 
     345             : 
     346       30342 : 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       30342 :     phiQ14q = (Word16) intLimCDivPos_fx( (UWord32) L_shl( L_deposit_l( indexphi ), 13 ), shr( D, 1 ) ); /* Q14 */
     358       30342 :     move16();
     359       30342 :     if ( indexphi < 0 )
     360             :     {
     361         157 :         phiQ14q = 1 << 13; /* one op */
     362         157 :         move16();
     363             :     }
     364             : 
     365       30342 :     oppTail = shr( sub( 16320, phiQ14q ), 15 );
     366       30342 :     nearTail = shr( sub( phiQ14q, 64 ), 15 );
     367             : 
     368       30342 :     IF( s_or( oppTail, nearTail ) < 0 )
     369             :     {
     370         344 :         *oppQ15 = s_and( oppTail, ( 1 << 15 ) - 1 ); /* Q15 */
     371         344 :         move16();
     372         344 :         *nearQ15 = s_and( nearTail, ( 1 << 15 ) - 1 ); /* Q15 */
     373         344 :         move16();
     374         344 :         *oppRatioQ3 = shl( add( 1, shl( nearTail, 1 ) ), 14 ); /* Q3 */
     375         344 :         move16();
     376             :     }
     377             :     ELSE
     378             :     {
     379       29998 :         nearProjQ15_fx( shl( sub( 1 << 14, phiQ14q ), 1 ), oppQ15 );
     380       29998 :         nearProjQ15_fx( shl( phiQ14q, 1 ), nearQ15 );
     381       29998 :         Ratio_rQ3_fx( *oppQ15, *nearQ15, oppRatioQ3 );
     382             :     }
     383             : 
     384       30342 :     return;
     385             : }
     386             : 
     387           0 : 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           0 :     *indexphi = mult_r( shl( D, 1 ), phiQ14uq ); /* Q0 */
     397           0 :     move16();
     398           0 :     if ( s_and( D, 1 ) > 0 )
     399             :     {
     400           0 :         *indexphi = -1; /* one op */
     401           0 :         move16();
     402             :     }
     403           0 :     densityAngle2RmsProjDec_fx( D, *indexphi, oppQ15, nearQ15, oppRatioQ3 );
     404             : 
     405           0 :     return;
     406             : }
     407             : 
     408       30342 : 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             : #ifndef ISSUE_1836_replace_overflow_libcom
     431             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     432             :     Flag Overflow = 0;
     433             :     move32();
     434             : #endif
     435             : #endif
     436             : 
     437       30342 :     rangeCoderFinalizationFBits_fx( Qac, INTac, &qac );
     438       30342 :     qboth = sub( qband, sub( qac, qzero ) ); /* Q0 */
     439             :     /* skew calc code  */
     440       30342 :     qskew = 0;
     441       30342 :     move16();
     442       30342 :     IF( GT_16( Nhead, 1 ) )
     443             :     {
     444       30302 :         qavg = extract_h( L_shl( intLimCDivSigned_fx( L_deposit_l( qboth ), Np ), 16 ) ); /* qboth may be negative      Q0*/
     445       30302 :         dsDiracPerQuanta_fx( Ntail, qavg, FlagCons, hBitsN, &Midx );
     446       30302 :         QuantaPerDsDirac_fx( Nhead, Midx, hBitsN, &qmin );
     447       30302 :         qskew = sub( qavg, qmin ); /* Q0 */
     448       30302 :         qskew = s_max( 0, qskew ); /* Q0 */
     449             :     }                              /* end of skew calc code*/
     450             : 
     451       30342 :     QIa = add( extract_l( intLimCDivPos_fx( (UWord32) L_deposit_l( Nopp ), Nnear ) ), 1 );                   /* always positive Word16 out      Q0*/
     452       30342 :     L_qnum = L_sub( L_deposit_l( sub( sub( add( qband, qzero ), qac ), qskew ) ), L_mult0( Nopp, oppRQ3 ) ); /* Q0 */
     453             : 
     454       30342 :     L_QIb = L_deposit_l( 0 );
     455       30342 :     IF( L_qnum > 0 )
     456             :     {
     457       29871 :         L_QIb = (Word32) intLimCDivPos_fx( L_qnum, QIa ); /* Q0 */
     458             :     }
     459       30342 :     *qnear = qboth; /* Q3 */
     460       30342 :     move16();
     461             : #ifdef ISSUE_1836_replace_overflow_libcom
     462       30342 :     QIb = extract_h( L_shl_sat( L_QIb, 16 ) ); /* may saturate          Q0*/
     463             : #else
     464             :     QIb = extract_h( L_shl_o( L_QIb, 16, &Overflow ) ); /* may saturate             Q0*/
     465             : #endif
     466       30342 :     if ( LE_16( QIb, qboth ) )
     467             :     {
     468       29936 :         *qnear = QIb; /* Q0 */
     469       29936 :         move16();
     470             :     }
     471       30342 :     *qopp = sub( qboth, *qnear ); /* Q0 */
     472       30342 :     move16();
     473       30342 :     *qglobalupd = sub( qglobal, sub( qac, qzero ) ); /* Q0 */
     474       30342 :     move16();
     475             : 
     476       30342 :     return;
     477             : }
     478             : 
     479             : 
     480             : /*--------------------------------------------------------------------------*
     481             :  * apply_gain()
     482             :  *
     483             :  * Apply gain
     484             :  *--------------------------------------------------------------------------*/
     485             : 
     486       28429 : void apply_gain_fx(
     487             :     const Word16 *ord,        /* i  : Indices for energy order               Q0      */
     488             :     const Word16 *band_start, /* i  : Sub band start indices                 Q0      */
     489             :     const Word16 *band_end,   /* i  : Sub band end indices                   Q0      */
     490             :     const Word16 num_sfm,     /* i  : Number of bands                        Q0      */
     491             :     const Word16 *gains,      /* i  : Band gain vector                       Qx     */
     492             :     Word16 *xq                /* i/o: Float synthesis / Gain adjusted synth  Q15/Qx */
     493             : )
     494             : {
     495             :     Word16 band, i;
     496             :     Word16 g; /* Q12 */
     497             : 
     498      442506 :     FOR( band = 0; band < num_sfm; band++ )
     499             :     {
     500      414077 :         g = gains[ord[band]];
     501      414077 :         move16();
     502     7618677 :         FOR( i = band_start[band]; i < band_end[band]; i++ )
     503             :         {
     504             :             /*xq[i] *= g; */
     505     7204600 :             xq[i] = mult_r( g, xq[i] );
     506     7204600 :             move16(); /*12+15+1-16=12 */
     507             :         }
     508             :     }
     509             : 
     510       28429 :     return;
     511             : }
     512             : 
     513             : /*--------------------------------------------------------------------------*
     514             :  * fine_gain_quant_fx()
     515             :  *
     516             :  * Fine gain quantization
     517             :  *--------------------------------------------------------------------------*/
     518           0 : void fine_gain_quant_fx(
     519             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle                                     */
     520             :     const Word16 *ord,       /* i  : Indices for energy order                 Q0  */
     521             :     const Word16 num_sfm,    /* i  : Number of bands                          Q0  */
     522             :     const Word16 *gain_bits, /* i  : Gain adjustment bits per sub band        Q0  */
     523             :     Word16 *fg_pred,         /* i/o: Predicted gains / Corrected gains        Q12 */
     524             :     const Word16 *gopt       /* i  : Optimal gains                            Q12 */
     525             : )
     526             : {
     527             :     Word16 band;
     528             :     Word16 gbits;
     529             :     Word16 idx;
     530             :     Word16 gain_db, gain_dbq;
     531             :     Word16 err;
     532             : 
     533             :     Word16 tmp1, tmp2, exp1, exp2;
     534             :     Word32 L_tmp;
     535             :     UWord16 lsb;
     536             : #ifndef ISSUE_1836_replace_overflow_libcom
     537             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     538             :     Flag Overflow = 0;
     539             :     move32();
     540             : #endif
     541             : #endif
     542             : 
     543           0 :     FOR( band = 0; band < num_sfm; band++ )
     544             :     {
     545           0 :         gbits = gain_bits[ord[band]]; /* Q0 */
     546           0 :         move16();
     547           0 :         test();
     548           0 :         IF( fg_pred[band] != 0 && gbits > 0 )
     549             :         {
     550           0 :             exp1 = norm_s( gopt[band] );
     551           0 :             exp1 = sub( exp1, 1 );
     552           0 :             tmp1 = shl( gopt[band], exp1 );
     553           0 :             exp2 = norm_s( fg_pred[band] );
     554           0 :             tmp2 = shl( fg_pred[band], exp2 ); /* Q12 + exp2 */
     555           0 :             exp1 = add( 15, sub( exp1, exp2 ) );
     556           0 :             err = div_s( tmp1, tmp2 ); /* Q15 */
     557           0 :             tmp1 = norm_s( err );
     558           0 :             exp2 = Log2_norm_lc( L_deposit_h( shl( err, tmp1 ) ) );
     559           0 :             tmp1 = sub( 14, tmp1 );
     560           0 :             tmp1 = sub( tmp1, exp1 );
     561           0 :             L_tmp = L_Comp( tmp1, exp2 );
     562           0 :             Mpy_32_16_ss( L_tmp, 24660, &L_tmp, &lsb ); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */
     563             : #ifdef ISSUE_1836_replace_overflow_libcom
     564           0 :             gain_db = round_fx_sat( L_shl_sat( L_tmp, 17 ) );
     565             : #else
     566             :             gain_db = round_fx_sat( L_shl_o( L_tmp, 17, &Overflow ) );
     567             : #endif
     568             : 
     569           0 :             idx = squant_fx( gain_db, &gain_dbq, finegain_fx[gbits - 1], gain_cb_size[gbits - 1] );
     570           0 :             push_indice( hBstr, IND_PVQ_FINE_GAIN, idx, gbits );
     571             : 
     572           0 :             L_tmp = L_mult0( gain_dbq, 21771 ); /* 21771=0.05*log2(10) */ /* 14+17=31 */
     573           0 :             L_tmp = L_shr( L_tmp, 15 );                                   /* Q16 */
     574           0 :             tmp1 = L_Extract_lc( L_tmp, &exp1 );
     575           0 :             tmp1 = abs_s( tmp1 );
     576           0 :             tmp1 = extract_l( Pow2( 14, tmp1 ) );
     577           0 :             exp1 = sub( 14, exp1 );
     578             : 
     579           0 :             L_tmp = L_mult0( fg_pred[band], tmp1 );                              /*12+exp1 */
     580           0 :             fg_pred[band] = round_fx_sat( L_shl_sat( L_tmp, sub( 16, exp1 ) ) ); /*12+exp1+16-exp1-16=12 */
     581           0 :             move16();
     582             :         }
     583             :     }
     584             : 
     585           0 :     return;
     586             : }
     587             : 
     588             : /*-------------------------------------------------------------------*
     589             :  * srt_vec_ind()
     590             :  *
     591             :  *  sort vector and save  sorting indeces
     592             :  *-------------------------------------------------------------------*/
     593             : 
     594      293372 : void srt_vec_ind16_fx(
     595             :     const Word16 *linear, /* linear input                               Q3*/
     596             :     Word16 *srt,          /* sorted output                              Q3*/
     597             :     Word16 *I,            /* index for sorted output    Q0*/
     598             :     Word16 length         /* Q0 */
     599             : )
     600             : {
     601             :     Word16 pos, npos;
     602             :     Word16 idxMem;
     603             :     Word16 valMem;
     604             : 
     605             :     /*initilize */
     606      743480 :     FOR( pos = 0; pos < length; pos++ )
     607             :     {
     608      450108 :         I[pos] = pos; /* Q0 */
     609      450108 :         move16();
     610             :     }
     611             : 
     612      293372 :     Copy( linear, srt, length ); /* Q3 */
     613             : 
     614             :     /* now iterate */
     615      450108 :     FOR( pos = 0; pos < ( length - 1 ); pos++ )
     616             :     {
     617      684695 :         FOR( npos = ( pos + 1 ); npos < length; npos++ )
     618             :         {
     619      527959 :             IF( LT_16( srt[npos], srt[pos] ) )
     620             :             {
     621      246848 :                 idxMem = I[pos]; /* Q0 */
     622      246848 :                 move16();
     623      246848 :                 I[pos] = I[npos]; /* Q0 */
     624      246848 :                 move16();
     625      246848 :                 I[npos] = idxMem; /* Q0 */
     626      246848 :                 move16();
     627             : 
     628      246848 :                 valMem = srt[pos]; /* Q0 */
     629      246848 :                 move16();
     630      246848 :                 srt[pos] = srt[npos]; /* Q0 */
     631      246848 :                 move16();
     632      246848 :                 srt[npos] = valMem; /* Q0 */
     633      246848 :                 move16();
     634             :             }
     635             :         }
     636             :     }
     637             : 
     638      293372 :     return;
     639             : }
     640             : 
     641             : /*-----------------------------------------------------------------------------
     642             :  * atan2_fx():
     643             :  *
     644             :  * Approximates arctan piecewise with various 4th to 5th order least square fit
     645             :  * polynomials for input in 5 segments:
     646             :  *   - 0.0 to 1.0
     647             :  *   - 1.0 to 2.0
     648             :  *   - 2.0 to 4.0
     649             :  *   - 4.0 to 8.0
     650             :  *   - 8.0 to infinity
     651             :  *---------------------------------------------------------------------------*/
     652     6873793 : Word16 atan2_fx(                 /* o: Angle between 0 and PI/2 radian (Q14) */
     653             :                  const Word32 y, /* i  : near side (Argument must be positive) (Q15) */
     654             :                  const Word32 x  /* i  : opposite side (Q15)                         */
     655             : )
     656             : {
     657             :     Word32 acc, arg;
     658             :     Word16 man, expo, reciprocal;
     659             :     Word16 angle, w, z;
     660             : 
     661     6873793 :     IF( x == 0 )
     662             :     {
     663       54599 :         return 25736; /* PI/2 in Q14 */
     664             :     }
     665     6819194 :     man = ratio( y, x, &expo );      /* man in Q14 */
     666     6819194 :     expo = sub( expo, ( 15 - 14 ) ); /* Now, man is considered in Q15 */
     667     6819194 :     arg = L_shr( (Word32) man, expo );
     668             : 
     669     6819194 :     IF( L_shr( arg, 3 + 15 ) != 0 )
     670             :     /*===============================*
     671             :      *      8.0 <= x < infinity      *
     672             :      *===============================*/
     673             :     {
     674             :         /* atan(x) = PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ...
     675             :          *         ~ PI/2 - 1/x, for x >= 8.
     676             :          */
     677      405084 :         expo = norm_l( arg );
     678      405084 :         man = extract_h( L_shl( arg, expo ) );
     679      405084 :         reciprocal = div_s( 0x3fff, man );
     680      405084 :         expo = sub( 15 + 1, expo );
     681      405084 :         reciprocal = shr( reciprocal, expo ); /* Q14 */
     682      405084 :         angle = sub( 25736, reciprocal );     /* Q14   (PI/2 - 1/x) */
     683             : 
     684             :         /* For 8.0 <= x < 10.0, 1/(5x^5) is not completely negligible.
     685             :          * For more accurate result, add very small correction term.
     686             :          */
     687      405084 :         if ( LT_32( L_shr( arg, 15 ), 10L ) )
     688             :         {
     689       84962 :             angle = add( angle, 8 ); /* Add tiny correction term. */
     690             :         }
     691             :     }
     692     6414110 :     ELSE IF( L_shr( arg, 2 + 15 ) != 0 )
     693             :     /*==========================*
     694             :      *      4.0 <= x < 8.0      *
     695             :      *==========================*/
     696             :     {
     697             :         /* interval: [3.999, 8.001]
     698             :          * atan(x) ~ (((a0*x     +   a1)*x   + a2)*x   + a3)*x   + a4
     699             :          *         = (((a0*8*y   +   a1)*8*y + a2)*8*y + a3)*8*y + a4   Substitute 8*y -> x
     700             :          *         = (((a0*8^3*y + a1*8^2)*y + a2*8)*y + a3)*8*y + a4
     701             :          *         = (((    c0*y +     c1)*y +   c2)*y + c3)*8*y + c4,
     702             :          *  where y = x/8
     703             :          *   and a0 = -1.28820869667651e-04, a1 = 3.88263533346295e-03,
     704             :          *       a2 = -4.64216306484597e-02, a3 = 2.75986060068931e-01,
     705             :          *       a4 = 7.49208077809799e-01.
     706             :          */
     707      265644 :         w = extract_l( L_shr( arg, 3 ) );               /* Q15  y = x/8 */
     708      265644 :         acc = L_add( 533625337L, 0 );                   /* Q31  c1 = a1*8^2 */
     709      265644 :         z = mac_r( acc, w, -2161 );                     /* Q15  c0 = a0*8^3 */
     710      265644 :         acc = L_add( -797517542L, 0 );                  /* Q31  c2 = a2*8 */
     711      265644 :         z = mac_r( acc, w, z );                         /* Q15 */
     712      265644 :         acc = L_add( 592675551L, 0 );                   /* Q31  c3 = a3 */
     713      265644 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q12) */
     714      265644 :         acc = L_add( 201114012L, 0 );                   /* Q28  c4 = a4 */
     715      265644 :         acc = L_mac( acc, w, z );                       /* Q28 */
     716      265644 :         angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14 result of atan(x), where 4 <= x < 8 */
     717             :     }
     718     6148466 :     ELSE IF( L_shr( arg, 1 + 15 ) != 0 )
     719             :     /*==========================*
     720             :      *      2.0 <= x < 4.0      *
     721             :      *==========================*/
     722             :     {
     723             :         /* interval: [1.999, 4.001]
     724             :          * atan(x) ~ (((a0*x    + a1)*x   +   a2)*x   + a3)*x   + a4
     725             :          *         = (((a0*4*y  + a1)*4*y +   a2)*4*y + a3)*4*y + a4   Substitute 4*y -> x
     726             :          *         = (((a0*16*y + a1*4)*y +   a2)*4*y + a3)*4*y + a4
     727             :          *         = (((a0*32*y + a1*8)*y + a2*2)*2*y + a3)*4*y + a4
     728             :          *         = (((   c0*y +   c1)*y +   c2)*2*y + c3)*4*y + c4,
     729             :          *  where y = x/4
     730             :          *   and a0 = -0.00262378195660943, a1 = 0.04089687039888652,
     731             :          *       a2 = -0.25631148958325911, a3 = 0.81685854627399479,
     732             :          *       a4 = 0.21358070563097167
     733             :          * */
     734      418649 :         w = extract_l( L_shr( arg, 2 ) );               /* Q15  y = x/4 */
     735      418649 :         acc = L_add( 702602883L, 0 );                   /* Q31  c1 = a1*8 */
     736      418649 :         z = mac_r( acc, w, -2751 );                     /* Q15  c0 = a0*32 */
     737      418649 :         acc = L_add( -1100849465L, 0 );                 /* Q31  c2 = a2*2 */
     738      418649 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q14) */
     739      418649 :         acc = L_add( 877095185L, 0 );                   /* Q30  c3 = a3 */
     740      418649 :         z = mac_r( acc, w, z );                         /* z (in:Q14, out:Q12) */
     741      418649 :         acc = L_add( 57332634L, 0 );                    /* Q28  c4 = a4 */
     742      418649 :         acc = L_mac( acc, w, z );                       /* Q28 */
     743      418649 :         angle = extract_l( L_shr( acc, ( 28 - 14 ) ) ); /* Q14  result of atan(x) where 2 <= x < 4 */
     744             :     }
     745     5729817 :     ELSE IF( L_shr( arg, 15 ) != 0 )
     746             :     /*==========================*
     747             :      *      1.0 <= x < 2.0      *
     748             :      *==========================*/
     749             :     {
     750             :         /* interval: [0.999, 2.001]
     751             :          * atan(x) ~ (((a0*x   +  1)*x   + a2)*x   +   a3)*x   + a4
     752             :          *         = (((a0*2*y + a1)*2*y + a2)*2*y +   a3)*2*y + a4    Substitute 2*y -> x
     753             :          *         = (((a0*4*y + a1*2)*y + a2)*2*y +   a3)*2*y + a4
     754             :          *         = (((a0*4*y + a1*2)*y + a2)*y   + a3/2)*4*y + a4
     755             :          *         = (((  c0*y +   c1)*y + c2)*y   +   c3)*4*y + c4,
     756             :          *  where y = x/2
     757             :          *   and a0 = -0.0160706457245251, a1 = 0.1527106504065224,
     758             :          *       a2 = -0.6123208404800871, a3 = 1.3307896976322915,
     759             :          *       a4 = -0.0697089375247448
     760             :          */
     761     1036339 :         w = extract_l( L_shr( arg, 1 ) ); /* Q15  y= x/2 */
     762     1036339 :         acc = L_add( 655887249L, 0 );     /* Q31  c1 = a1*2 */
     763     1036339 :         z = mac_r( acc, w, -2106 );       /* Q15  c0 = a0*4 */
     764     1036339 :         acc = L_add( -1314948992L, 0 );   /* Q31  c2 = a2 */
     765     1036339 :         z = mac_r( acc, w, z );
     766     1036339 :         acc = L_add( 1428924557L, 0 );                  /* Q31  c3 = a3/2 */
     767     1036339 :         z = mac_r( acc, w, z );                         /* z (in:Q15, out:Q13) */
     768     1036339 :         acc = L_add( -37424701L, 0 );                   /* Q29  c4 = a4 */
     769     1036339 :         acc = L_mac( acc, w, z );                       /* Q29 */
     770     1036339 :         angle = extract_l( L_shr( acc, ( 29 - 14 ) ) ); /* Q14  result of atan(x) where 1 <= x < 2 */
     771             :     }
     772             :     ELSE
     773             :     /*==========================*
     774             :      *      0.0 <= x < 1.0      *
     775             :      *==========================*/
     776             :     {
     777             :         /* interval: [-0.001, 1.001]
     778             :          * atan(x) ~ ((((a0*x   +   a1)*x   + a2)*x + a3)*x + a4)*x + a5
     779             :          *         = ((((a0*2*x + a1*2)*x/2 + a2)*x + a3)*x + a4)*x + a5
     780             :          *         = ((((  c0*x +   c1)*x/2 + c2)*x + c3)*x + c4)*x + c5
     781             :          *  where
     782             :          *    a0 = -5.41182677118661e-02, a1 = 2.76690449232515e-01,
     783             :          *    a2 = -4.63358392562492e-01, a3 = 2.87188466598566e-02,
     784             :          *    a4 =  9.97438122814383e-01, a5 = 5.36158556179092e-05.
     785             :          */
     786     4693478 :         w = extract_l( arg );                 /* Q15 */
     787     4693478 :         acc = L_add( 1188376431L, 0 );        /* Q31  c1 = a1*2 */
     788     4693478 :         z = mac_r( acc, w, -3547 );           /* Q15  c0 = a0*2 */
     789     4693478 :         acc = L_add( -995054571L, 0 );        /* Q31  c2 = a2 */
     790     4693478 :         z = extract_h( L_mac0( acc, w, z ) ); /* Q15  non-fractional mode multiply */
     791     4693478 :         acc = L_add( 61673254L, 0 );          /* Q31  c3 = a3 */
     792     4693478 :         z = mac_r( acc, w, z );
     793     4693478 :         acc = L_add( 2141982059L, 0 ); /* Q31  c4 = a4 */
     794     4693478 :         z = mac_r( acc, w, z );
     795     4693478 :         acc = L_add( 115139L, 0 );                  /* Q31  c5 = a5 */
     796     4693478 :         acc = L_mac( acc, w, z );                   /* Q31 */
     797     4693478 :         angle = extract_l( L_shr( acc, 31 - 14 ) ); /* Q14  result of atan(x), where 0 <= x < 1 */
     798             :     }
     799             : 
     800     6819194 :     return angle; /* Q14 between 0 and PI/2 radian. */
     801             : }

Generated by: LCOV version 1.14