LCOV - code coverage report
Current view: top level - lib_enc - peak_vq_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 384 735 52.2 %
Date: 2025-05-03 01:55:50 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include <assert.h>
       7             : #include "options.h" /* Compilation switches                   */
       8             : #include "cnst.h"    /* Common constants                       */
       9             : //#include "prot_fx.h"
      10             : #include "rom_enc.h"
      11             : #include "rom_com_fx.h"
      12             : #include "rom_com.h"
      13             : #include "prot_fx.h"     /* Function prototypes                    */
      14             : #include "prot_fx_enc.h" /* Function prototypes                    */
      15             : 
      16             : /*--------------------------------------------------------------------------
      17             :  * Local function prototypes
      18             :  *--------------------------------------------------------------------------*/
      19             : 
      20             : static void quant_peaks_fx( BSTR_ENC_HANDLE hBstr, const Word32 *, Word32 *, const Word32 *, Word16 *, const Word16, const Word32, const Word16 );
      21             : static Word16 hvq_code_pos_fx( BSTR_ENC_HANDLE hBstr, const Word16 *inp, const Word16 length, const Word16 num_peaks );
      22             : static Word16 sparse_code_pos_fx( const Word16 *inp, const Word16 length, Word16 *result );
      23             : static Word16 hvq_code_pos_ivas_fx( BSTR_ENC_HANDLE hBstr, const Word16 *inp, const Word16 length, const Word16 num_peaks );
      24             : 
      25             : static void quant_peaks_ivas_fx(
      26             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle        */
      27             :     const Word32 *vect_in,   /* i  : Target vector in Q12    */
      28             :     Word32 *vect_out,        /* i/o: Quantized vector in Q12 */
      29             :     const Word32 *peak_gain, /* i  : Peak gain vector in Q12 */
      30             :     Word16 *vq_idx,          /* o  : Codebook index          */
      31             :     const Word16 overlap,    /* i  : Overlap indicator       */
      32             :     const Word32 core_brate, /* i  : Core bitrate            */
      33             :     const Word16 Npeaks      /* i  : Number of peaks         */
      34             : );
      35             : /*--------------------------------------------------------------------------
      36             :  * peak_vq_enc_fx()
      37             :  *
      38             :  * Vector Quantization of MDCT peaks
      39             :  *--------------------------------------------------------------------------*/
      40        1463 : Word16 peak_vq_enc_ivas_fx(
      41             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle    */
      42             :     const Word16 bwidth,     /* i  : audio bandwidth             */
      43             :     const Word32 *coefs,     /* i  : Input coefficient vector Q12    */
      44             :     Word32 *coefs_out,       /* o  : Quantized output vector Q12     */
      45             :     const Word32 core_brate, /* i  : Core bitrate                    */
      46             :     const Word16 num_bits,   /* i  : Number of bits for HVQ          */
      47             :     const Word16 vq_peaks,   /* i  : Number of identified peaks      */
      48             :     const Word16 *ynrm,      /* i  : Envelope coefficients           */
      49             :     Word16 *R,               /* i/o: Bit allocation/updated bit allocation */
      50             :     Word16 *vq_peak_idx,     /* i  : Peak index vector               */
      51             :     Word32 *nf_gains         /* i  : Estimated noise floor gains Q12 */
      52             : )
      53             : {
      54             :     Word16 pos_bits;
      55             :     Word32 normq;
      56             :     Word32 pgain_q[HVQ_MAX_PEAKS];
      57             :     Word32 peak_gains[HVQ_MAX_PEAKS];
      58             :     Word16 coefs_pvq[HVQ_PVQ_BUF_LEN], *pCoefsPvq; /* Q12 */
      59             :     Word32 pvq_vector[HVQ_PVQ_BUF_LEN], *pPvqVector;
      60             :     Word32 *pPvqVectorBandStart;
      61             :     Word16 pvq_vector_norm[HVQ_PVQ_BUF_LEN];
      62             :     Word16 fg_pred[NB_SFM_MAX];
      63             :     Word16 i, j, k, m, r, pvq_bands, num_overlap_bins;
      64             :     Word16 hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th, bin_th2;
      65             :     Word16 bits;
      66             :     Word16 nf_seed;
      67             :     Word16 pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; /* Q0 */
      68             :     Word16 pvq_norm[MAX_PVQ_BANDS];
      69             :     Word16 pvq_bits, bit_budget;
      70             :     Word16 pos_vec[HVQ_THRES_BIN_32k];
      71             :     Word16 npulses[MAX_PVQ_BANDS];
      72             :     Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN];
      73             :     Word16 k_sort[MAX_PVQ_BANDS];
      74             :     Word16 Rk[MAX_PVQ_BANDS];
      75             :     Word16 gopt[NB_SFM];
      76             :     Word16 tmp1, exp1;
      77             :     Word16 Q_coefs;
      78             : 
      79             : 
      80             :     Word16 indx, vqPeaksMinus1, tmp16, whiteNoise;
      81             :     Word16 *pPgainDifIdx, *pPgainCbIdx, *pVqPeakIdx, *pPosVec;
      82             :     Word32 *pPeakGains, *pCoefsOut;
      83             :     const Word32 *pCoefs;
      84             :     Word32 acc;
      85             :     UWord16 dontCare16;
      86             :     Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */
      87             :     Word16 expE_peak, expPeakGains, expPkEnrg;
      88             :     Word16 *pSelBnds;
      89             :     Word16 sel_bnds[HVQ_NUM_SFM_24k];
      90             :     Word16 hvq_band_end[MAX_PVQ_BANDS];
      91             :     Word16 hvq_band_start[MAX_PVQ_BANDS];
      92             :     Word16 hvq_band_width[MAX_PVQ_BANDS];
      93             :     Word16 n_sel_bnds;
      94             :     UWord32 lsb;
      95             : 
      96        1463 :     assert( ( core_brate > HQ_16k40 && core_brate <= HQ_48k ) && "HVQ rate not supported" );
      97             : 
      98             : 
      99        1463 :     max_peaks = extract_l( Mpy_32_32( L_add( imult3216( core_brate, HVQ_PEAKS_PER_DELTA ), HVQ_PEAKS_PER_DELTA_OFFS ), 282564 ) ); /* 1/HVQ_PEAKS_BPS_DELTA in Q31 */
     100             : 
     101        1463 :     bits = 0;
     102        1463 :     move16();
     103        1463 :     nf_seed = RANDOM_INITSEED;
     104        1463 :     move16();
     105             : 
     106             : 
     107        1463 :     set16_fx( coefs_pvq, 0, HVQ_PVQ_BUF_LEN );
     108        1463 :     set32_fx( pvq_vector, 0, HVQ_PVQ_BUF_LEN );
     109        1463 :     set16_fx( pvq_vector_norm, 0, HVQ_PVQ_BUF_LEN );
     110        1463 :     set16_fx( npulses, 0, MAX_PVQ_BANDS );
     111             : 
     112        1463 :     bin_th = HVQ_THRES_BIN_32k;
     113        1463 :     move16();
     114        1463 :     bin_th2 = HVQ_THRES_BIN_32k / HVQ_NF_GROUPS;
     115        1463 :     move16();
     116             :     /* Set bit-rate dependent variables */
     117        1463 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
     118             :     {
     119         849 :         bin_th = HVQ_THRES_BIN_24k;
     120         849 :         move16();
     121         849 :         bin_th2 = HVQ_THRES_BIN_24k / HVQ_NF_GROUPS;
     122         849 :         move16();
     123             :     }
     124             : 
     125      388119 :     FOR( i = 0; i < bin_th; i++ )
     126             :     {
     127      386656 :         pos_vec[i] = 0;
     128      386656 :         move16();
     129             :     }
     130             : 
     131             :     /* Quantize noise floor gains */
     132        4389 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     133             :     {
     134        2926 :         logqnorm_ivas_fx( &nf_gains[i], 12, &indx, 32, 1, &thren_HQ_fx[0] );
     135             : 
     136             :         /* De-quantization */
     137        2926 :         acc = dicn_fx[indx]; /* Q14 */
     138        2926 :         move32();
     139        2926 :         nf_gains[i] = L_shr( acc, 1 + 2 ); /* nf_gains in Q12. dicn_fx is in Q14. Need extra shift +2. */
     140        2926 :         move32();
     141             : 
     142        2926 :         push_indice( hBstr, IND_HVQ_NF_GAIN, indx, 5 );
     143        2926 :         bits = add( bits, 5 );
     144             :     }
     145             : 
     146             :     /* Signal number of peaks */
     147        1463 :     i = sub( max_peaks, vq_peaks );
     148        1463 :     push_indice( hBstr, IND_NUM_PEAKS, i, 5 );
     149        1463 :     bits = add( bits, 5 );
     150             : 
     151             :     /* Identify position of first peak and arrange peak gains by position */
     152        1463 :     pVqPeakIdx = &vq_peak_idx[0];
     153        1463 :     low_peak_bin = bin_th;
     154        1463 :     move16();
     155       26447 :     FOR( i = 0; i < vq_peaks; i++ )
     156             :     {
     157       24984 :         indx = *pVqPeakIdx++;
     158       24984 :         move16();
     159       24984 :         IF( LT_16( indx, low_peak_bin ) )
     160             :         {
     161        4283 :             low_peak_bin = indx;
     162        4283 :             move16();
     163             :         }
     164             :         /* Store the sign information. */
     165       24984 :         IF( coefs[indx] < 0 )
     166             :         {
     167       12687 :             pos_vec[indx] = -1; /* Negative. */
     168       12687 :             move16();
     169             :         }
     170             :         ELSE
     171             :         {
     172       12297 :             pos_vec[indx] = 1; /* Positive */
     173       12297 :             move16();
     174             :         }
     175             :     }
     176             : 
     177        1463 :     pPeakGains = &peak_gains[0];
     178        1463 :     pVqPeakIdx = &vq_peak_idx[0];
     179        1463 :     pPosVec = &pos_vec[0];
     180        1463 :     pCoefs = &coefs[0];
     181      388119 :     FOR( i = 0; i < bin_th; i++ )
     182             :     {
     183      386656 :         acc = *pCoefs++;
     184      386656 :         move32();
     185      386656 :         IF( *pPosVec++ != 0 )
     186             :         {
     187       24984 :             *pPeakGains++ = L_abs( acc ); /* in Q12 */
     188       24984 :             move32();
     189       24984 :             *pVqPeakIdx++ = i;
     190       24984 :             move16();
     191             :         }
     192             :     }
     193             : 
     194             :     /* Scale down peak gains */
     195             :     /* Divided by 4 is equivalent to consider peak_gains to be in Q14 from Q12.
     196             :      * No physical bit shift is actually required.
     197             :      */
     198             : 
     199             :     /* Quantize peak gains */
     200        1463 :     pPeakGains = &peak_gains[0];
     201        1463 :     pPgainCbIdx = &pgain_cb_idx[0];
     202        1463 :     logqnorm_ivas_fx( pPeakGains++, 14, pPgainCbIdx++, 32, 1, &thren_pg_fx[0] );
     203        1463 :     vqPeaksMinus1 = sub( vq_peaks, 1 );
     204       24984 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     205             :     {
     206       23521 :         logqnorm_ivas_fx( pPeakGains++, 14, pPgainCbIdx++, 45, 1, &thren_pg_fx[0] );
     207             :     }
     208             : 
     209             :     /* Code quantized peak gain indices
     210             :      * and also scale up peak gains. */
     211        1463 :     diffcod_fx( vq_peaks, pgain_cb_idx, &pgain_difidx[1] );
     212             :     /* Accumulate peak energy. */
     213        1463 :     manE_peak = L_deposit_l( 0 );
     214        1463 :     expE_peak = 32;
     215        1463 :     move16();
     216       26447 :     FOR( i = 0; i < vq_peaks; i++ )
     217             :     {
     218       24984 :         indx = pgain_cb_idx[i];
     219       24984 :         move16();
     220             :         /* Scale up peak gains */
     221       24984 :         pgain_q[i] = L_shl( dicn_pg_fx[indx], 2 ); /* pgain_q in Q12 */
     222       24984 :         move32();
     223             :         /* Use floating point operation to deal with wide dynamic range.l
     224             :          * 32-bit mantissa is used here. It should be even more accurate than
     225             :          * the floating-point reference code with 24-bit mantissa! */
     226       24984 :         expPeakGains = norm_l( pgain_q[i] );
     227       24984 :         manPeakGains = L_shl( pgain_q[i], expPeakGains );
     228       24984 :         Mpy_32_32_ss( manPeakGains, manPeakGains, &manPkEnrg, &lsb ); /* peak_gains square */
     229       24984 :         expPkEnrg = shl( expPeakGains, 1 );                           /* Multiply by 2 due to squaring. */
     230             :         /* True floating value = manPkEng x 2^(32 - 1 - expPkEnrg - 2*12).
     231             :          * In this context, the 32-bit manPkEng is in Q0.
     232             :          * 32 is due to Mpy_32_32() only providing the 32 MSBs of the 64 bits product.
     233             :          * -1 is due fractional mode Multiply. 2*12 is due to square of Q12. */
     234       24984 :         floating_point_add( &manE_peak, &expE_peak, manPkEnrg, expPkEnrg );
     235             :     }
     236        1463 :     pgain_difidx[0] = pgain_cb_idx[0];
     237        1463 :     move16();
     238             : 
     239             :     /* Huffman coding */
     240        1463 :     hcode_l = 0;
     241        1463 :     move16();
     242        1463 :     pPgainDifIdx = &pgain_difidx[1];
     243       24984 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     244             :     {
     245       23521 :         indx = *pPgainDifIdx++;
     246       23521 :         move16();
     247       23521 :         hcode_l = add( hcode_l, pgain_huffsizn[indx] );
     248             :     }
     249             : 
     250        1463 :     FlagN = HUFCODE;
     251        1463 :     move16();
     252             : 
     253        1463 :     tmp16 = extract_l( L_mult0( GAINI_BITS, vqPeaksMinus1 ) );
     254        1463 :     IF( GE_16( hcode_l, tmp16 ) )
     255             :     {
     256          25 :         hcode_l = tmp16;
     257          25 :         move16();
     258          25 :         FlagN = NOHUFCODE;
     259          25 :         move16();
     260             :     }
     261             : 
     262        1463 :     push_indice( hBstr, IND_FLAGN, FlagN, 1 );
     263        1463 :     push_indice( hBstr, IND_PG_IDX, pgain_difidx[0], GAIN0_BITS );
     264             : 
     265        1463 :     IF( FlagN )
     266             :     {
     267        1438 :         pPgainDifIdx = &pgain_difidx[1];
     268       24594 :         FOR( i = 0; i < vqPeaksMinus1; i++ )
     269             :         {
     270       23156 :             j = *pPgainDifIdx++;
     271       23156 :             move16();
     272       23156 :             m = pgain_huffnorm[j];
     273       23156 :             move16();
     274       23156 :             r = pgain_huffsizn[j];
     275       23156 :             move16();
     276             : 
     277       23156 :             push_indice( hBstr, IND_PG_IDX, m, r );
     278             :         }
     279             :     }
     280             :     ELSE
     281             :     {
     282          25 :         pPgainDifIdx = &pgain_difidx[1];
     283         390 :         FOR( i = 0; i < vqPeaksMinus1; i++ )
     284             :         {
     285         365 :             push_indice( hBstr, IND_PG_IDX, ( *pPgainDifIdx++ ), GAINI_BITS );
     286             :         }
     287             :     }
     288             : 
     289             :     /* Number of bits used for peak gain quantization */
     290        1463 :     bits = add( bits, add( FLAGN_BITS + GAIN0_BITS, hcode_l ) );
     291             : 
     292             :     /* Add sign for peak shape normalization */
     293       26447 :     FOR( i = 0; i < vq_peaks; i++ )
     294             :     {
     295       24984 :         indx = vq_peak_idx[i];
     296       24984 :         move16();
     297       24984 :         peak_gains[i] = pgain_q[i]; /* Q12 */
     298       24984 :         move32();
     299       24984 :         IF( pos_vec[indx] < 0 )
     300             :         {
     301       12687 :             peak_gains[i] = L_negate( peak_gains[i] ); /* Q12 */
     302       12687 :             move32();
     303             :         }
     304             :     }
     305             : 
     306             :     /* Quantize peak shapes */
     307       24984 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     308             :     {
     309       23521 :         num_overlap_bins = sub( 5, sub( vq_peak_idx[i + 1], vq_peak_idx[i] ) );
     310       23521 :         indx = sub( vq_peak_idx[i], 2 );
     311       23521 :         quant_peaks_ivas_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, num_overlap_bins, core_brate, vq_peaks );
     312       23521 :         push_indice( hBstr, IND_HVQ_PEAKS, vq_cb_idx, 8 );
     313       23521 :         bits = add( bits, 9 );
     314             :     }
     315             : 
     316        1463 :     indx = sub( vq_peak_idx[i], 2 );
     317        1463 :     quant_peaks_ivas_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, 0, core_brate, vq_peaks );
     318        1463 :     push_indice( hBstr, IND_HVQ_PEAKS, vq_cb_idx, 8 );
     319        1463 :     bits = add( bits, 9 );
     320             : 
     321             :     /* Quantize peak positions and sign with HVQ */
     322        1463 :     pos_bits = hvq_code_pos_ivas_fx( hBstr, pos_vec, bin_th, vq_peaks );
     323             : 
     324        1463 :     bits = add( bits, pos_bits );
     325        1463 :     bit_budget = sub( num_bits, bits );
     326             : 
     327             :     /* Calculate number of PVQ bands to code and assign bits */
     328        1463 :     pvq_bands = hvq_pvq_bitalloc_fx( bit_budget, core_brate, bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds );
     329             : 
     330             :     /* Get band limits for concatenated PVQ target */
     331        1463 :     hvq_concat_bands_fx( pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end );
     332             : 
     333             :     /* Quantize PVQ bands */
     334        1463 :     pCoefsOut = coefs_out;
     335        1463 :     pCoefs = coefs;
     336        1463 :     pPvqVector = pvq_vector;
     337        1463 :     pSelBnds = sel_bnds;
     338        1463 :     m = bin_th;
     339        1463 :     move16();
     340        4308 :     FOR( k = 0; k < pvq_bands; k++ )
     341             :     {
     342        2845 :         IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) )
     343             :         {
     344         366 :             i = band_start_harm[*pSelBnds++];
     345         366 :             move16();
     346         366 :             pCoefs = coefs + i;
     347         366 :             pCoefsOut = coefs_out + i;
     348             :         }
     349        2845 :         k_sort[k] = k;
     350        2845 :         move16();
     351        2845 :         j = 0;
     352        2845 :         move16();
     353        2845 :         pPvqVectorBandStart = pPvqVector;
     354      115423 :         WHILE( LT_16( j, hvq_band_width[k] ) )
     355             :         {
     356      112578 :             IF( *pCoefsOut++ == 0 )
     357             :             {
     358       75032 :                 *pPvqVector++ = *pCoefs; /* Q12 */
     359       75032 :                 move32();
     360       75032 :                 j = add( j, 1 );
     361             :             }
     362      112578 :             pCoefs++;
     363             :         }
     364        2845 :         logqnorm_ivas_fx( pPvqVectorBandStart, 12, &pvq_norm[k], 40, hvq_band_width[k], &thren_HQ_fx[0] );
     365             :     }
     366             : 
     367             :     /* Normalize coefficients */
     368        1463 :     normalizecoefs_fx( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end, pvq_vector_norm );
     369        1463 :     Q_coefs = 12;
     370        1463 :     move16();
     371             : 
     372        1463 :     bit_budget = sub( bit_budget, i_mult2( HVQ_PVQ_GAIN_BITS, pvq_bands ) );
     373             : 
     374        1463 :     pvq_bits = bit_budget;
     375        1463 :     move16();
     376        1463 :     set16_fx( npulses, 0, MAX_PVQ_BANDS );
     377             : 
     378        1463 :     pvq_encode_frame_ivas_fx( hBstr, pvq_vector_norm, Q_coefs, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands,
     379             :                               Rk, pvq_bits, HQ_CORE );
     380             : 
     381        4308 :     FOR( i = 0; i < pvq_bands; i++ )
     382             :     {
     383        2845 :         k_sort[i] = i;
     384        2845 :         move16();
     385             :     }
     386             : 
     387             : 
     388        1463 :     fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, pvq_bands, coefs_pvq,
     389             :                        pvq_inp_vector, fg_pred, HQ_CORE );
     390             : 
     391        1463 :     pCoefsOut = &coefs_out[0];
     392        1463 :     pSelBnds = &sel_bnds[0];
     393        1463 :     pCoefsPvq = &coefs_pvq[0];
     394        4308 :     FOR( k = 0; k < pvq_bands; k++ )
     395             :     {
     396        2845 :         indx = pvq_norm[k];
     397        2845 :         move16();
     398        2845 :         tmp1 = ratio( gopt[k], fg_pred[k], &exp1 );
     399        2845 :         tmp1 = shr( tmp1, sub( 1, exp1 ) );                       /* Q13 */
     400        2845 :         Mpy_32_16_ss( dicn_fx[indx], tmp1, &normq, &dontCare16 ); /* dicn_fx in Q14, sorted_pvq_gain_pred_err_fx in Q13. */
     401             : 
     402        2845 :         logqnorm_fx( &normq, 12, &pvq_norm[k], 40, 1, 0 ); /* normq in Q(14+(16+13)+1-32)=Q12 */
     403        2845 :         pvq_norm[k] = sub( pvq_norm[k], 8 );
     404        2845 :         move16();
     405        2845 :         IF( pvq_norm[k] < 0 )
     406             :         {
     407           0 :             pvq_norm[k] = 0;
     408           0 :             move16();
     409             :         }
     410             : 
     411        2845 :         push_indice( hBstr, IND_HVQ_PVQ_GAIN, pvq_norm[k], HVQ_PVQ_GAIN_BITS );
     412        2845 :         pvq_bits = add( pvq_bits, HVQ_PVQ_GAIN_BITS );
     413             : 
     414        2845 :         pvq_norm[k] = add( pvq_norm[k], 8 );
     415        2845 :         move16();
     416        2845 :         indx = pvq_norm[k];
     417        2845 :         move16();
     418        2845 :         normq = dicn_fx[indx]; /* in Q14 */
     419        2845 :         move32();
     420        2845 :         j = 0;
     421        2845 :         move16();
     422        2845 :         IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) )
     423             :         {
     424         366 :             i = band_start_harm[*pSelBnds++];
     425         366 :             move16();
     426         366 :             pCoefsOut = coefs_out + i;
     427             :         }
     428      115423 :         WHILE( LT_16( j, hvq_band_width[k] ) )
     429             :         {
     430      112578 :             IF( *pCoefsOut == 0 )
     431             :             {
     432       75032 :                 acc = L_mult( *pCoefsPvq++, fg_pred[k] );        /* in Q(15 + 1 + 12 = 28) */
     433       75032 :                 tmp16 = extract_h( acc );                        /* in Q(28 - 16 = 12) */
     434       75032 :                 Mpy_32_16_ss( normq, tmp16, &acc, &dontCare16 ); /* acc(Q11), normq(Q14), tmp16(Q12) */
     435       75032 :                 *pCoefsOut = L_shl( acc, 12 - 11 );              /* Q12 */
     436       75032 :                 move32();
     437       75032 :                 j = add( j, 1 );
     438             :             }
     439      112578 :             pCoefsOut++;
     440             :         }
     441             :     }
     442        1463 :     bits = add( bits, pvq_bits );
     443             : 
     444             :     /* Noise fill unqantized coeffs with one gain per group */
     445        1463 :     pCoefsOut = &coefs_out[-1];
     446        4389 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     447             :     {
     448      389582 :         FOR( j = 0; j < bin_th2; j++ )
     449             :         {
     450      386656 :             IF( *( ++pCoefsOut ) == 0 )
     451             :             {
     452      224484 :                 whiteNoise = Random( &nf_seed );                                 /* Q15 */
     453      224484 :                 Mpy_32_16_ss( nf_gains[i], whiteNoise, pCoefsOut, &dontCare16 ); /* nf_gains in Q12. *pCoefsOut in Q12 */
     454             :             }
     455             :         }
     456             :     }
     457             : 
     458        1463 :     return bits;
     459             : }
     460           0 : Word16 peak_vq_enc_fx(
     461             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle    */
     462             :     const Word16 bwidth,     /* i  : audio bandwidth             */
     463             :     const Word32 *coefs,     /* i  : Input coefficient vector Q12    */
     464             :     Word32 *coefs_out,       /* o  : Quantized output vector Q12     */
     465             :     const Word32 core_brate, /* i  : Core bitrate                    */
     466             :     const Word16 num_bits,   /* i  : Number of bits for HVQ          */
     467             :     const Word16 vq_peaks,   /* i  : Number of identified peaks      */
     468             :     const Word16 *ynrm,      /* i  : Envelope coefficients           */
     469             :     Word16 *R,               /* i/o: Bit allocation/updated bit allocation */
     470             :     Word16 *vq_peak_idx,     /* i  : Peak index vector               */
     471             :     Word32 *nf_gains         /* i  : Estimated noise floor gains Q12 */
     472             : )
     473             : {
     474             :     Word16 pos_bits;
     475             :     Word32 normq;
     476             :     Word32 pgain_q[HVQ_MAX_PEAKS];
     477             :     Word32 peak_gains[HVQ_MAX_PEAKS];
     478             :     Word16 coefs_pvq[HVQ_PVQ_BUF_LEN], *pCoefsPvq; /* Q12 */
     479             :     Word32 pvq_vector[HVQ_PVQ_BUF_LEN], *pPvqVector;
     480             :     Word32 *pPvqVectorBandStart;
     481             :     Word16 pvq_vector_norm[HVQ_PVQ_BUF_LEN];
     482             :     Word16 fg_pred[NB_SFM_MAX];
     483             :     Word16 i, j, k, m, r, pvq_bands, num_overlap_bins;
     484             :     Word16 hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th, bin_th2;
     485             :     Word16 bits;
     486             :     Word16 nf_seed;
     487             :     Word16 pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; /* Q0 */
     488             :     Word16 pvq_norm[MAX_PVQ_BANDS];
     489             :     Word16 pvq_bits, bit_budget;
     490             :     Word16 pos_vec[HVQ_THRES_BIN_32k];
     491             :     Word16 npulses[MAX_PVQ_BANDS];
     492             :     Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN];
     493             :     Word16 k_sort[MAX_PVQ_BANDS];
     494             :     Word16 Rk[MAX_PVQ_BANDS];
     495             :     Word16 gopt[NB_SFM];
     496             :     Word16 tmp1, exp1;
     497             :     Word16 Q_coefs;
     498             : 
     499             : 
     500             :     Word16 indx, vqPeaksMinus1, tmp16, whiteNoise;
     501             :     Word16 *pPgainDifIdx, *pPgainCbIdx, *pVqPeakIdx, *pPosVec;
     502             :     Word32 *pPeakGains, *pCoefsOut;
     503             :     const Word32 *pCoefs;
     504             :     Word32 acc;
     505             :     UWord16 dontCare16;
     506             :     Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */
     507             :     Word16 expE_peak, expPeakGains, expPkEnrg;
     508             :     Word16 *pSelBnds;
     509             :     Word16 sel_bnds[HVQ_NUM_SFM_24k];
     510             :     Word16 hvq_band_end[MAX_PVQ_BANDS];
     511             :     Word16 hvq_band_start[MAX_PVQ_BANDS];
     512             :     Word16 hvq_band_width[MAX_PVQ_BANDS];
     513             :     Word16 n_sel_bnds;
     514             :     UWord32 lsb;
     515             : 
     516           0 :     assert( ( core_brate > HQ_16k40 && core_brate <= HQ_48k ) && "HVQ rate not supported" );
     517             : 
     518             :     // PMT("max_peaks equation needs to be converted")
     519           0 :     max_peaks = (Word16) ( ( core_brate * HVQ_PEAKS_PER_DELTA + HVQ_PEAKS_PER_DELTA_OFFS ) / HVQ_PEAKS_BPS_DELTA );
     520             : 
     521             : 
     522           0 :     bits = 0;
     523           0 :     move16();
     524           0 :     nf_seed = RANDOM_INITSEED;
     525           0 :     move16();
     526             : 
     527             : 
     528           0 :     set16_fx( coefs_pvq, 0, HVQ_PVQ_BUF_LEN );
     529           0 :     set32_fx( pvq_vector, 0, HVQ_PVQ_BUF_LEN );
     530           0 :     set16_fx( pvq_vector_norm, 0, HVQ_PVQ_BUF_LEN );
     531           0 :     set16_fx( npulses, 0, MAX_PVQ_BANDS );
     532             : 
     533           0 :     bin_th = HVQ_THRES_BIN_32k;
     534           0 :     move16();
     535           0 :     bin_th2 = HVQ_THRES_BIN_32k / HVQ_NF_GROUPS;
     536           0 :     move16();
     537             :     /* Set bit-rate dependent variables */
     538           0 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
     539             :     {
     540           0 :         bin_th = HVQ_THRES_BIN_24k;
     541           0 :         move16();
     542           0 :         bin_th2 = HVQ_THRES_BIN_24k / HVQ_NF_GROUPS;
     543           0 :         move16();
     544             :     }
     545             : 
     546           0 :     FOR( i = 0; i < bin_th; i++ )
     547             :     {
     548           0 :         pos_vec[i] = 0;
     549           0 :         move16();
     550             :     }
     551             : 
     552             :     /* Quantize noise floor gains */
     553           0 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     554             :     {
     555           0 :         logqnorm_fx( &nf_gains[i], 12, &indx, 32, 1, 0 );
     556             : 
     557             :         /* De-quantization */
     558           0 :         acc = dicn_fx[indx]; /* Q14 */
     559           0 :         move32();
     560           0 :         nf_gains[i] = L_shr( acc, 1 + 2 ); /* nf_gains in Q12. dicn_fx is in Q14. Need extra shift +2. */
     561           0 :         move32();
     562           0 :         push_indice( hBstr, IND_HVQ_NF_GAIN, indx, 5 );
     563           0 :         bits = add( bits, 5 );
     564             :     }
     565             : 
     566             :     /* Signal number of peaks */
     567           0 :     i = sub( max_peaks, vq_peaks );
     568           0 :     push_indice( hBstr, IND_NUM_PEAKS, i, 5 );
     569           0 :     bits = add( bits, 5 );
     570             : 
     571             :     /* Identify position of first peak and arrange peak gains by position */
     572           0 :     pVqPeakIdx = &vq_peak_idx[0];
     573           0 :     low_peak_bin = bin_th;
     574           0 :     FOR( i = 0; i < vq_peaks; i++ )
     575             :     {
     576           0 :         indx = *pVqPeakIdx++;
     577           0 :         move16();
     578           0 :         IF( LT_16( indx, low_peak_bin ) )
     579             :         {
     580           0 :             low_peak_bin = indx;
     581           0 :             move16();
     582             :         }
     583             :         /* Store the sign information. */
     584           0 :         IF( coefs[indx] < 0 )
     585             :         {
     586           0 :             pos_vec[indx] = -1; /* Negative. */
     587           0 :             move16();
     588             :         }
     589             :         ELSE
     590             :         {
     591           0 :             pos_vec[indx] = 1; /* Positive */
     592           0 :             move16();
     593             :         }
     594             :     }
     595             : 
     596           0 :     pPeakGains = &peak_gains[0];
     597           0 :     pVqPeakIdx = &vq_peak_idx[0];
     598           0 :     pPosVec = &pos_vec[0];
     599           0 :     pCoefs = &coefs[0];
     600           0 :     FOR( i = 0; i < bin_th; i++ )
     601             :     {
     602           0 :         acc = *pCoefs++;
     603           0 :         IF( *pPosVec++ != 0 )
     604             :         {
     605           0 :             *pPeakGains++ = L_abs( acc ); /* in Q12 */
     606           0 :             move32();
     607           0 :             *pVqPeakIdx++ = i;
     608           0 :             move16();
     609             :         }
     610             :     }
     611             : 
     612             :     /* Scale down peak gains */
     613             :     /* Divided by 4 is equivalent to consider peak_gains to be in Q14 from Q12.
     614             :      * No physical bit shift is actually required.
     615             :      */
     616             : 
     617             :     /* Quantize peak gains */
     618           0 :     pPeakGains = &peak_gains[0];
     619           0 :     pPgainCbIdx = &pgain_cb_idx[0];
     620           0 :     logqnorm_fx( pPeakGains++, 14, pPgainCbIdx++, 32, 1, 1 );
     621           0 :     vqPeaksMinus1 = sub( vq_peaks, 1 );
     622           0 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     623             :     {
     624           0 :         logqnorm_fx( pPeakGains++, 14, pPgainCbIdx++, 45, 1, 1 );
     625             :     }
     626             : 
     627             :     /* Code quantized peak gain indices
     628             :      * and also scale up peak gains. */
     629           0 :     diffcod_fx( vq_peaks, pgain_cb_idx, &pgain_difidx[1] );
     630             :     /* Accumulate peak energy. */
     631           0 :     manE_peak = L_deposit_l( 0 );
     632           0 :     expE_peak = 32;
     633           0 :     move16();
     634           0 :     FOR( i = 0; i < vq_peaks; i++ )
     635             :     {
     636           0 :         indx = pgain_cb_idx[i];
     637           0 :         move16();
     638             :         /* Scale up peak gains */
     639           0 :         pgain_q[i] = L_shl( dicn_pg_fx[indx], 2 ); /* pgain_q in Q12 */
     640           0 :         move32();
     641             :         /* Use floating point operation to deal with wide dynamic range.l
     642             :          * 32-bit mantissa is used here. It should be even more accurate than
     643             :          * the floating-point reference code with 24-bit mantissa! */
     644           0 :         expPeakGains = norm_l( pgain_q[i] );
     645           0 :         manPeakGains = L_shl( pgain_q[i], expPeakGains );
     646           0 :         Mpy_32_32_ss( manPeakGains, manPeakGains, &manPkEnrg, &lsb ); /* peak_gains square */
     647           0 :         expPkEnrg = shl( expPeakGains, 1 );                           /* Multiply by 2 due to squaring. */
     648             :         /* True floating value = manPkEng x 2^(32 - 1 - expPkEnrg - 2*12).
     649             :          * In this context, the 32-bit manPkEng is in Q0.
     650             :          * 32 is due to Mpy_32_32() only providing the 32 MSBs of the 64 bits product.
     651             :          * -1 is due fractional mode Multiply. 2*12 is due to square of Q12. */
     652           0 :         floating_point_add( &manE_peak, &expE_peak, manPkEnrg, expPkEnrg );
     653             :     }
     654           0 :     pgain_difidx[0] = pgain_cb_idx[0];
     655           0 :     move16();
     656             : 
     657             :     /* Huffman coding */
     658           0 :     hcode_l = 0;
     659           0 :     move16();
     660           0 :     pPgainDifIdx = &pgain_difidx[1];
     661           0 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     662             :     {
     663           0 :         indx = *pPgainDifIdx++;
     664           0 :         move16();
     665           0 :         hcode_l = add( hcode_l, pgain_huffsizn[indx] );
     666             :     }
     667             : 
     668           0 :     FlagN = HUFCODE;
     669           0 :     move16();
     670             : 
     671           0 :     tmp16 = extract_l( L_mult0( GAINI_BITS, vqPeaksMinus1 ) );
     672           0 :     IF( GE_16( hcode_l, tmp16 ) )
     673             :     {
     674           0 :         hcode_l = tmp16;
     675           0 :         move16();
     676           0 :         FlagN = NOHUFCODE;
     677           0 :         move16();
     678             :     }
     679             : 
     680           0 :     push_indice( hBstr, IND_FLAGN, FlagN, 1 );
     681           0 :     push_indice( hBstr, IND_PG_IDX, pgain_difidx[0], GAIN0_BITS );
     682             : 
     683           0 :     IF( FlagN )
     684             :     {
     685           0 :         pPgainDifIdx = &pgain_difidx[1];
     686           0 :         FOR( i = 0; i < vqPeaksMinus1; i++ )
     687             :         {
     688           0 :             j = *pPgainDifIdx++;
     689           0 :             move16();
     690           0 :             m = pgain_huffnorm[j];
     691           0 :             move16();
     692           0 :             r = pgain_huffsizn[j];
     693           0 :             move16();
     694             : 
     695           0 :             push_indice( hBstr, IND_PG_IDX, m, r );
     696             :         }
     697             :     }
     698             :     ELSE
     699             :     {
     700           0 :         pPgainDifIdx = &pgain_difidx[1];
     701           0 :         FOR( i = 0; i < vqPeaksMinus1; i++ )
     702             :         {
     703           0 :             push_indice( hBstr, IND_PG_IDX, ( *pPgainDifIdx++ ), GAINI_BITS );
     704             :         }
     705             :     }
     706             : 
     707             :     /* Number of bits used for peak gain quantization */
     708           0 :     bits = add( bits, add( FLAGN_BITS + GAIN0_BITS, hcode_l ) );
     709             : 
     710             :     /* Add sign for peak shape normalization */
     711           0 :     FOR( i = 0; i < vq_peaks; i++ )
     712             :     {
     713           0 :         indx = vq_peak_idx[i];
     714           0 :         move16();
     715           0 :         peak_gains[i] = pgain_q[i]; /* Q12 */
     716           0 :         move32();
     717           0 :         IF( pos_vec[indx] < 0 )
     718             :         {
     719           0 :             peak_gains[i] = L_negate( peak_gains[i] ); /* Q12 */
     720           0 :             move32();
     721             :         }
     722             :     }
     723             : 
     724             :     /* Quantize peak shapes */
     725           0 :     FOR( i = 0; i < vqPeaksMinus1; i++ )
     726             :     {
     727           0 :         num_overlap_bins = sub( 5, sub( vq_peak_idx[i + 1], vq_peak_idx[i] ) );
     728           0 :         indx = sub( vq_peak_idx[i], 2 );
     729           0 :         quant_peaks_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, num_overlap_bins, core_brate, vq_peaks );
     730           0 :         push_indice( hBstr, IND_HVQ_PEAKS, vq_cb_idx, 8 );
     731           0 :         bits = add( bits, 9 );
     732             :     }
     733             : 
     734           0 :     indx = sub( vq_peak_idx[i], 2 );
     735           0 :     quant_peaks_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, 0, core_brate, vq_peaks );
     736           0 :     push_indice( hBstr, IND_HVQ_PEAKS, vq_cb_idx, 8 );
     737           0 :     bits = add( bits, 9 );
     738             : 
     739             :     /* Quantize peak positions and sign with HVQ */
     740           0 :     pos_bits = hvq_code_pos_fx( hBstr, pos_vec, bin_th, vq_peaks );
     741             : 
     742           0 :     bits = add( bits, pos_bits );
     743           0 :     bit_budget = sub( num_bits, bits );
     744             : 
     745             :     /* Calculate number of PVQ bands to code and assign bits */
     746           0 :     pvq_bands = hvq_pvq_bitalloc_fx( bit_budget, core_brate, bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds );
     747             : 
     748             :     /* Get band limits for concatenated PVQ target */
     749           0 :     hvq_concat_bands_fx( pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end );
     750             : 
     751             :     /* Quantize PVQ bands */
     752           0 :     pCoefsOut = coefs_out;
     753           0 :     pCoefs = coefs;
     754           0 :     pPvqVector = pvq_vector;
     755           0 :     pSelBnds = sel_bnds;
     756           0 :     m = bin_th;
     757           0 :     move16();
     758           0 :     FOR( k = 0; k < pvq_bands; k++ )
     759             :     {
     760           0 :         IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) )
     761             :         {
     762           0 :             i = band_start_harm[*pSelBnds++];
     763           0 :             move16();
     764           0 :             pCoefs = coefs + i;
     765           0 :             pCoefsOut = coefs_out + i;
     766             :         }
     767           0 :         k_sort[k] = k;
     768           0 :         move16();
     769           0 :         j = 0;
     770           0 :         move16();
     771           0 :         pPvqVectorBandStart = pPvqVector;
     772           0 :         WHILE( LT_16( j, hvq_band_width[k] ) )
     773             :         {
     774           0 :             IF( *pCoefsOut++ == 0 )
     775             :             {
     776           0 :                 *pPvqVector++ = *pCoefs; /* Q12 */
     777           0 :                 move32();
     778           0 :                 j = add( j, 1 );
     779             :             }
     780           0 :             pCoefs++;
     781             :         }
     782           0 :         logqnorm_fx( pPvqVectorBandStart, 12, &pvq_norm[k], 40, hvq_band_width[k], 0 );
     783             :     }
     784             : 
     785             :     /* Normalize coefficients */
     786           0 :     normalizecoefs_fx( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end, pvq_vector_norm );
     787           0 :     Q_coefs = 12;
     788           0 :     move16();
     789             : 
     790           0 :     bit_budget = sub( bit_budget, i_mult2( HVQ_PVQ_GAIN_BITS, pvq_bands ) );
     791             : 
     792           0 :     pvq_bits = bit_budget;
     793           0 :     move16();
     794           0 :     set16_fx( npulses, 0, MAX_PVQ_BANDS );
     795             : 
     796           0 :     pvq_encode_frame_fx( hBstr, pvq_vector_norm, Q_coefs, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands,
     797             :                          Rk, pvq_bits, HQ_CORE );
     798             : 
     799           0 :     FOR( i = 0; i < pvq_bands; i++ )
     800             :     {
     801           0 :         k_sort[i] = i;
     802           0 :         move16();
     803             :     }
     804             : 
     805             : 
     806           0 :     fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, pvq_bands, coefs_pvq,
     807             :                        pvq_inp_vector, fg_pred, HQ_CORE );
     808             : 
     809           0 :     pCoefsOut = &coefs_out[0];
     810           0 :     pSelBnds = &sel_bnds[0];
     811           0 :     pCoefsPvq = &coefs_pvq[0];
     812           0 :     FOR( k = 0; k < pvq_bands; k++ )
     813             :     {
     814           0 :         indx = pvq_norm[k];
     815           0 :         move16();
     816           0 :         tmp1 = ratio( gopt[k], fg_pred[k], &exp1 );
     817           0 :         tmp1 = shr( tmp1, sub( 1, exp1 ) );                       /* Q13 */
     818           0 :         Mpy_32_16_ss( dicn_fx[indx], tmp1, &normq, &dontCare16 ); /* dicn_fx in Q14, sorted_pvq_gain_pred_err_fx in Q13. */
     819             : 
     820           0 :         logqnorm_fx( &normq, 12, &pvq_norm[k], 40, 1, 0 ); /* normq in Q(14+(16+13)+1-32)=Q12 */
     821           0 :         pvq_norm[k] = sub( pvq_norm[k], 8 );
     822           0 :         move16();
     823           0 :         IF( pvq_norm[k] < 0 )
     824             :         {
     825           0 :             pvq_norm[k] = 0;
     826           0 :             move16();
     827             :         }
     828             : 
     829           0 :         push_indice( hBstr, IND_HVQ_PVQ_GAIN, pvq_norm[k], HVQ_PVQ_GAIN_BITS );
     830           0 :         pvq_bits = add( pvq_bits, HVQ_PVQ_GAIN_BITS );
     831             : 
     832           0 :         pvq_norm[k] = add( pvq_norm[k], 8 );
     833           0 :         move16();
     834           0 :         indx = pvq_norm[k];
     835           0 :         move16();
     836           0 :         normq = L_add( dicn_fx[indx], 0 ); /* in Q14 */
     837           0 :         j = 0;
     838           0 :         move16();
     839           0 :         IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) )
     840             :         {
     841           0 :             i = band_start_harm[*pSelBnds++];
     842           0 :             move16();
     843           0 :             pCoefsOut = coefs_out + i;
     844             :         }
     845           0 :         WHILE( LT_16( j, hvq_band_width[k] ) )
     846             :         {
     847           0 :             IF( EQ_32( *pCoefsOut, 0 ) )
     848             :             {
     849           0 :                 acc = L_mult( *pCoefsPvq++, fg_pred[k] );        /* in Q(15 + 1 + 12 = 28) */
     850           0 :                 tmp16 = extract_h( acc );                        /* in Q(28 - 16 = 12) */
     851           0 :                 Mpy_32_16_ss( normq, tmp16, &acc, &dontCare16 ); /* acc(Q11), normq(Q14), tmp16(Q12) */
     852           0 :                 *pCoefsOut = L_shl( acc, 12 - 11 );              /* Q12 */
     853           0 :                 move32();
     854           0 :                 j = add( j, 1 );
     855             :             }
     856           0 :             pCoefsOut++;
     857             :         }
     858             :     }
     859           0 :     bits = add( bits, pvq_bits );
     860             : 
     861             :     /* Noise fill unqantized coeffs with one gain per group */
     862           0 :     pCoefsOut = &coefs_out[-1];
     863           0 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     864             :     {
     865           0 :         FOR( j = 0; j < bin_th2; j++ )
     866             :         {
     867           0 :             IF( *( ++pCoefsOut ) == 0 )
     868             :             {
     869           0 :                 whiteNoise = Random( &nf_seed );                                 /* Q15 */
     870           0 :                 Mpy_32_16_ss( nf_gains[i], whiteNoise, pCoefsOut, &dontCare16 ); /* nf_gains in Q12. *pCoefsOut in Q12 */
     871             :             }
     872             :         }
     873             :     }
     874             : 
     875           0 :     return bits;
     876             : }
     877             : 
     878             : /*--------------------------------------------------------------------------
     879             :  * quant_peaks_fx()
     880             :  *
     881             :  * Applies VQ on input vector
     882             :  *--------------------------------------------------------------------------*/
     883       24984 : static void quant_peaks_ivas_fx(
     884             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle        */
     885             :     const Word32 *vect_in,   /* i  : Target vector in Q12    */
     886             :     Word32 *vect_out,        /* i/o: Quantized vector in Q12 */
     887             :     const Word32 *peak_gain, /* i  : Peak gain vector in Q12 */
     888             :     Word16 *vq_idx,          /* o  : Codebook index          */
     889             :     const Word16 overlap,    /* i  : Overlap indicator       */
     890             :     const Word32 core_brate, /* i  : Core bitrate            */
     891             :     const Word16 Npeaks      /* i  : Number of peaks         */
     892             : )
     893             : {
     894             :     Word16 x[4];       /* Qx */
     895             :     Word16 xq[4];      /* Q15 */
     896             :     Word16 weights[4]; /* Q0 */
     897             :     Word16 *pWeights;
     898             :     Word16 i, cb_class, search_overlap, indx, cbSize;
     899             :     Word16 expPeakGain, manPeakGain, expIn, manIn;
     900             :     Word32 vectIn, absPeakGain1, absPeakGain;
     901             :     UWord16 dontCare;
     902             :     Word16 Qx_vec[4];
     903       24984 :     Word16 Qx = 15;
     904       24984 :     move16();
     905       24984 :     set16_fx( weights, 1, 4 );
     906             : 
     907             :     /* Divide vect_in[] by peak_gain to yield x[]. */
     908       24984 :     expPeakGain = norm_l( *peak_gain );                          /* exponent */
     909       24984 :     manPeakGain = extract_h( L_shl( *peak_gain, expPeakGain ) ); /* mantissa */
     910       24984 :     manPeakGain = abs_s( manPeakGain );                          /* Prepare for div_s() only accepting +ve. */
     911      124920 :     FOR( i = 0; i < 4; i++ )
     912             :     {
     913       99936 :         indx = hvq_index_mapping_fx[i];
     914       99936 :         move16();
     915       99936 :         vectIn = L_add( vect_in[indx], 0 );
     916       99936 :         expIn = norm_l( vectIn ); /* exponent */
     917       99936 :         expIn = sub( expIn, 1 );
     918       99936 :         expIn = s_min( expIn, expPeakGain );         /* highest Q is Q15 */
     919       99936 :         manIn = extract_h( L_shl( vectIn, expIn ) ); /* mantissa */
     920       99936 :         manIn = abs_s( manIn );                      /* Prepare for div_s() only accepting +ve. */
     921             : 
     922       99936 :         x[i] = div_s( manIn, manPeakGain ); /* in Q(15+expIn-expPeakGain) */
     923       99936 :         move16();
     924       99936 :         Qx_vec[i] = add( 15, sub( expIn, expPeakGain ) );
     925       99936 :         move16();
     926       99936 :         Qx = s_min( Qx, Qx_vec[i] );
     927             : 
     928             :         /* Restore the sign destroyed by abs operations. */
     929       99936 :         IF( L_xor( vectIn, *peak_gain ) < 0 ) /* Check the sign bits (MSB). */
     930             :         {
     931       42840 :             x[i] = negate( x[i] );
     932       42840 :             move16();
     933             :         }
     934             :     }
     935      124920 :     FOR( i = 0; i < 4; i++ )
     936             :     {
     937       99936 :         IF( NE_16( Qx_vec[i], Qx ) )
     938             :         {
     939       23778 :             x[i] = shr( x[i], sub( Qx_vec[i], Qx ) ); /* Qx */
     940       23778 :             move16();
     941             :         }
     942             :     }
     943       24984 :     absPeakGain = L_abs( peak_gain[0] );
     944       24984 :     IF( vect_out[0] != 0 )
     945             :     {
     946        2292 :         absPeakGain1 = L_abs( peak_gain[-1] );
     947        2292 :         IF( GT_32( absPeakGain1, absPeakGain ) )
     948             :         {
     949        1659 :             weights[0] = 0;
     950        1659 :             move16();
     951        1659 :             if ( vect_out[1] != 0 )
     952             :             {
     953         963 :                 weights[1] = 0;
     954         963 :                 move16();
     955             :             }
     956             :         }
     957             :     }
     958       24984 :     IF( overlap > 0 )
     959             :     {
     960        4402 :         absPeakGain1 = L_abs( peak_gain[1] );
     961        4402 :         IF( GT_32( absPeakGain1, absPeakGain ) )
     962             :         {
     963        2110 :             indx = sub( 4, overlap );
     964        2110 :             pWeights = &weights[indx];
     965        5735 :             FOR( i = 0; i < overlap; i++ )
     966             :             {
     967        3625 :                 *pWeights++ = 0;
     968        3625 :                 move16();
     969             :             }
     970             :         }
     971             :     }
     972             : 
     973             :     /* Classify */
     974       24984 :     cb_class = w_vquant_fx( x, Qx, weights, 0, hvq_class_c_fx, HVQ_NUM_CLASS, 0 );
     975       24984 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
     976             :     {
     977       12327 :         indx = s_max( 0, sub( HVQ_MAX_PEAKS_24k, Npeaks ) );
     978       12327 :         search_overlap = hvq_cb_search_overlap24k[indx];
     979       12327 :         move16();
     980             :     }
     981             :     ELSE
     982             :     {
     983       12657 :         indx = s_max( 0, sub( HVQ_MAX_PEAKS_32k, Npeaks ) );
     984       12657 :         search_overlap = hvq_cb_search_overlap32k[indx];
     985       12657 :         move16();
     986             :     }
     987             : 
     988             :     /* Quantize */
     989       24984 :     cbSize = add( HVQ_CB_SIZE / 2, search_overlap );
     990       24984 :     IF( cb_class == 0 )
     991             :     {
     992        6884 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 0 );
     993        6884 :         move16();
     994        6884 :         push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 );
     995             :     }
     996       18100 :     ELSE IF( EQ_16( cb_class, 1 ) )
     997             :     {
     998        5849 :         indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) );
     999        5849 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 0 );
    1000        5849 :         move16();
    1001        5849 :         *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) );
    1002        5849 :         move16();
    1003        5849 :         push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 );
    1004             :     }
    1005       12251 :     ELSE IF( EQ_16( cb_class, 2 ) )
    1006             :     {
    1007        5726 :         indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) );
    1008        5726 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 1 );
    1009        5726 :         move16();
    1010        5726 :         *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) );
    1011        5726 :         move16();
    1012        5726 :         push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 );
    1013             :     }
    1014             :     ELSE
    1015             :     {
    1016        6525 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 1 );
    1017        6525 :         move16();
    1018        6525 :         push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 );
    1019             :     }
    1020             : 
    1021      124920 :     FOR( i = 0; i < 4; i++ )
    1022             :     {
    1023       99936 :         indx = hvq_index_mapping_fx[i];
    1024       99936 :         move16();
    1025       99936 :         IF( weights[i] != 0 )
    1026             :         {
    1027       93689 :             Mpy_32_16_ss( *peak_gain, xq[i], &vect_out[indx], &dontCare ); /* peak_gains in Q12, xq in Q15 -> Q12. */
    1028       93689 :             move32();
    1029             :         }
    1030             :     }
    1031       24984 :     vect_out[2] = *peak_gain;
    1032       24984 :     move32(); /* vect_out in Q12 */
    1033             : 
    1034       24984 :     return;
    1035             : }
    1036             : 
    1037           0 : static void quant_peaks_fx(
    1038             :     BSTR_ENC_HANDLE hBstr,   /* i/o: encoder bitstream handle        */
    1039             :     const Word32 *vect_in,   /* i  : Target vector in Q12    */
    1040             :     Word32 *vect_out,        /* i/o: Quantized vector in Q12 */
    1041             :     const Word32 *peak_gain, /* i  : Peak gain vector in Q12 */
    1042             :     Word16 *vq_idx,          /* o  : Codebook index          */
    1043             :     const Word16 overlap,    /* i  : Overlap indicator       */
    1044             :     const Word32 core_brate, /* i  : Core bitrate            */
    1045             :     const Word16 Npeaks      /* i  : Number of peaks         */
    1046             : )
    1047             : {
    1048             :     Word16 x[4];       /* Qx */
    1049             :     Word16 xq[4];      /* Q15 */
    1050             :     Word16 weights[4]; /* Q0 */
    1051             :     Word16 *pWeights;
    1052             :     Word16 i, cb_class, search_overlap, indx, cbSize;
    1053             :     Word16 expPeakGain, manPeakGain, expIn, manIn;
    1054             :     Word32 vectIn, absPeakGain1, absPeakGain;
    1055             :     UWord16 dontCare;
    1056             :     Word16 Qx_vec[4];
    1057           0 :     Word16 Qx = 15;
    1058             : 
    1059           0 :     set16_fx( weights, 1, 4 );
    1060             : 
    1061             :     /* Divide vect_in[] by peak_gain to yield x[]. */
    1062           0 :     expPeakGain = norm_l( *peak_gain );                          /* exponent */
    1063           0 :     manPeakGain = extract_h( L_shl( *peak_gain, expPeakGain ) ); /* mantissa */
    1064           0 :     manPeakGain = abs_s( manPeakGain );                          /* Prepare for div_s() only accepting +ve. */
    1065           0 :     FOR( i = 0; i < 4; i++ )
    1066             :     {
    1067           0 :         indx = hvq_index_mapping_fx[i];
    1068           0 :         move16();
    1069           0 :         vectIn = L_add( vect_in[indx], 0 );
    1070           0 :         expIn = norm_l( vectIn ); /* exponent */
    1071           0 :         expIn = sub( expIn, 1 );
    1072           0 :         expIn = s_min( expIn, expPeakGain );         /* highest Q is Q15 */
    1073           0 :         manIn = extract_h( L_shl( vectIn, expIn ) ); /* mantissa */
    1074           0 :         manIn = abs_s( manIn );                      /* Prepare for div_s() only accepting +ve. */
    1075             : 
    1076           0 :         x[i] = div_s( manIn, manPeakGain ); /* in Q(15+expIn-expPeakGain) */
    1077             : 
    1078           0 :         Qx_vec[i] = add( 15, sub( expIn, expPeakGain ) );
    1079           0 :         move16();
    1080           0 :         Qx = s_min( Qx, Qx_vec[i] );
    1081             : 
    1082             :         /* Restore the sign destroyed by abs operations. */
    1083           0 :         if ( L_xor( vectIn, *peak_gain ) < 0 ) /* Check the sign bits (MSB). */
    1084             :         {
    1085           0 :             x[i] = negate( x[i] );
    1086           0 :             move16();
    1087             :         }
    1088             :     }
    1089           0 :     FOR( i = 0; i < 4; i++ )
    1090             :     {
    1091           0 :         IF( NE_16( Qx_vec[i], Qx ) )
    1092             :         {
    1093           0 :             x[i] = shr( x[i], sub( Qx_vec[i], Qx ) ); /* Qx */
    1094           0 :             move16();
    1095             :         }
    1096             :     }
    1097           0 :     absPeakGain = L_abs( peak_gain[0] );
    1098           0 :     IF( vect_out[0] != 0 )
    1099             :     {
    1100           0 :         absPeakGain1 = L_abs( peak_gain[-1] );
    1101           0 :         IF( GT_32( absPeakGain1, absPeakGain ) )
    1102             :         {
    1103           0 :             weights[0] = 0;
    1104           0 :             move16();
    1105           0 :             if ( vect_out[1] != 0 )
    1106             :             {
    1107           0 :                 weights[1] = 0;
    1108           0 :                 move16();
    1109             :             }
    1110             :         }
    1111             :     }
    1112           0 :     IF( overlap > 0 )
    1113             :     {
    1114           0 :         absPeakGain1 = L_abs( peak_gain[1] );
    1115           0 :         IF( GT_32( absPeakGain1, absPeakGain ) )
    1116             :         {
    1117           0 :             indx = sub( 4, overlap );
    1118           0 :             pWeights = &weights[indx];
    1119           0 :             FOR( i = 0; i < overlap; i++ )
    1120             :             {
    1121           0 :                 *pWeights++ = 0;
    1122           0 :                 move16();
    1123             :             }
    1124             :         }
    1125             :     }
    1126             : 
    1127             :     /* Classify */
    1128             : #if HVQ_VQ_DIM != 5
    1129             : #error w_vquant_fx() is hard-wired to dim = 4 = (HVQ_VQ_DIM - 1).
    1130             : #endif
    1131           0 :     cb_class = w_vquant_fx( x, Qx, weights, 0, hvq_class_c_fx, HVQ_NUM_CLASS, 0 );
    1132           0 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
    1133             :     {
    1134           0 :         indx = sub( HVQ_MAX_PEAKS_24k, Npeaks );
    1135           0 :         search_overlap = hvq_cb_search_overlap24k[indx];
    1136           0 :         move16();
    1137             :     }
    1138             :     ELSE
    1139             :     {
    1140           0 :         indx = sub( HVQ_MAX_PEAKS_32k, Npeaks );
    1141           0 :         search_overlap = hvq_cb_search_overlap32k[indx];
    1142           0 :         move16();
    1143             :     }
    1144             : 
    1145             :     /* Quantize */
    1146           0 :     cbSize = add( HVQ_CB_SIZE / 2, search_overlap );
    1147           0 :     IF( cb_class == 0 )
    1148             :     {
    1149           0 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 0 );
    1150           0 :         move16();
    1151           0 :         push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 );
    1152             :     }
    1153           0 :     ELSE IF( EQ_16( cb_class, 1 ) )
    1154             :     {
    1155           0 :         indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) );
    1156           0 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 0 );
    1157           0 :         move16();
    1158           0 :         *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) );
    1159           0 :         move16();
    1160           0 :         push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 );
    1161             :     }
    1162           0 :     ELSE IF( EQ_16( cb_class, 2 ) )
    1163             :     {
    1164           0 :         indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) );
    1165           0 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 1 );
    1166           0 :         move16();
    1167           0 :         *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) );
    1168           0 :         move16();
    1169           0 :         push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 );
    1170             :     }
    1171             :     ELSE
    1172             :     {
    1173           0 :         *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 1 );
    1174           0 :         move16();
    1175           0 :         push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 );
    1176             :     }
    1177             : 
    1178           0 :     FOR( i = 0; i < 4; i++ )
    1179             :     {
    1180           0 :         indx = hvq_index_mapping_fx[i];
    1181           0 :         move16();
    1182           0 :         IF( weights[i] != 0 )
    1183             :         {
    1184           0 :             Mpy_32_16_ss( *peak_gain, xq[i], &vect_out[indx], &dontCare ); /* peak_gains in Q12, xq in Q15 -> Q12. */
    1185           0 :             move32();
    1186             :         }
    1187             :     }
    1188           0 :     vect_out[2] = *peak_gain;
    1189           0 :     move32(); /* vect_out in Q12 */
    1190             : 
    1191           0 :     return;
    1192             : }
    1193             : 
    1194             : /*--------------------------------------------------------------------------
    1195             :  * code_pos()
    1196             :  *
    1197             :  * Code pulse positions
    1198             :  *--------------------------------------------------------------------------*/
    1199             : 
    1200        1463 : static Word16 sparse_code_pos_fx(
    1201             :     const Word16 *inp,
    1202             :     const Word16 length,
    1203             :     Word16 *result )
    1204             : {
    1205             :     Word16 layer2[HVQ_CP_L2_MAX];
    1206             :     Word16 layer_length;
    1207             :     Word16 i, j, tmp;
    1208             :     Word16 val, idx;
    1209        1463 :     Word16 bits = 0;
    1210             :     Word16 mask;
    1211             : 
    1212        1463 :     set16_fx( layer2, 0, HVQ_CP_L2_MAX );
    1213             : 
    1214             :     /*layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); */
    1215        1463 :     layer_length = round_fx( L_mult0( length, 13107 ) ); /* 0+16-16, 13107 is 1/5 in Q16  */
    1216             : 
    1217       78964 :     FOR( j = 0; j < layer_length; j++ )
    1218             :     {
    1219       77501 :         tmp = s_min( i_mult2( add( j, 1 ), HVQ_CP_L1_LEN ), length );
    1220      392399 :         FOR( i = i_mult2( j, HVQ_CP_L1_LEN ); i < tmp; i++ )
    1221             :         {
    1222      338594 :             IF( inp[i] != 0 )
    1223             :             {
    1224       23696 :                 layer2[j] = 1;
    1225       23696 :                 move16();
    1226       23696 :                 BREAK;
    1227             :             }
    1228             :         }
    1229             :     }
    1230             : 
    1231       78964 :     FOR( i = 0; i < layer_length; i++ )
    1232             :     {
    1233       77501 :         result[i] = layer2[i];
    1234       77501 :         move16();
    1235             :     }
    1236        1463 :     bits = add( bits, layer_length );
    1237             : 
    1238       78964 :     FOR( j = 0; j < layer_length; j++ )
    1239             :     {
    1240       77501 :         IF( layer2[j] != 0 )
    1241             :         {
    1242       23696 :             val = 0;
    1243       23696 :             move16();
    1244       23696 :             tmp = s_min( i_mult2( add( j, 1 ), HVQ_CP_L1_LEN ), length );
    1245      142158 :             FOR( i = i_mult2( j, HVQ_CP_L1_LEN ); i < tmp; i++ )
    1246             :             {
    1247      118462 :                 val = shl( val, 1 );
    1248      118462 :                 val = s_or( val, inp[i] );
    1249             :             }
    1250             : 
    1251       77447 :             FOR( idx = 0; idx < HVQ_CP_MAP_LEN; idx++ )
    1252             :             {
    1253       77447 :                 IF( EQ_16( hvq_cp_layer1_map5[idx], val ) )
    1254             :                 {
    1255       23696 :                     BREAK;
    1256             :                 }
    1257             :             }
    1258             : 
    1259       23696 :             mask = shl( 1, HVQ_CP_MAP_IDX_LEN - 1 );
    1260       94784 :             FOR( i = 0; i < HVQ_CP_MAP_IDX_LEN; i++ )
    1261             :             {
    1262       71088 :                 result[bits++] = shr( s_and( idx, mask ), sub( HVQ_CP_MAP_IDX_LEN - 1, i ) );
    1263       71088 :                 mask = shr( mask, 1 );
    1264             :             }
    1265             :         }
    1266             :     }
    1267             : 
    1268        1463 :     return bits;
    1269             : }
    1270             : 
    1271             : /*--------------------------------------------------------------------------
    1272             :  * hvq_code_pos()
    1273             :  *
    1274             :  * Code pulse positions
    1275             :  *--------------------------------------------------------------------------*/
    1276        1463 : static Word16 hvq_code_pos_ivas_fx(
    1277             :     BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle   */
    1278             :     const Word16 *inp,
    1279             :     const Word16 length,
    1280             :     const Word16 num_peaks )
    1281             : {
    1282             :     Word16 sparse_result[4 * HVQ_THRES_BIN_32k / HVQ_CP_L1_LEN];
    1283             :     Word16 delta[HVQ_MAX_PEAKS];
    1284             :     Word16 peak_idx[HVQ_MAX_PEAKS];
    1285             :     Word16 inp_abs[HVQ_THRES_BIN_32k];
    1286             :     Word16 inp_sign[HVQ_MAX_PEAKS];
    1287             : 
    1288             :     Word16 i, j;
    1289             :     Word16 bits;
    1290             :     Word16 delta_max;
    1291             :     Word16 delta_bits, sparse_bits;
    1292             :     Word16 tmp;
    1293             : 
    1294        1463 :     bits = 0;
    1295        1463 :     move16();
    1296             : 
    1297             :     /* Extract sorted peak index vector and sign vector */
    1298        1463 :     j = 0;
    1299        1463 :     move16();
    1300      388119 :     FOR( i = 0; i < length; i++ )
    1301             :     {
    1302      386656 :         inp_abs[i] = abs_s( inp[i] );
    1303      386656 :         move16();
    1304      386656 :         IF( inp[i] != 0 )
    1305             :         {
    1306       24984 :             peak_idx[j] = i;
    1307       24984 :             move16();
    1308       24984 :             inp_sign[j] = inp[i];
    1309       24984 :             move16();
    1310       24984 :             j = add( j, 1 );
    1311             :         }
    1312             :     }
    1313             : 
    1314             :     /* Calculate delta */
    1315        1463 :     delta[0] = add( peak_idx[0], HVQ_CP_HUFF_OFFSET );
    1316        1463 :     move16();
    1317        1463 :     delta_max = delta[0];
    1318        1463 :     move16();
    1319       24984 :     FOR( i = 1; i < num_peaks; i++ )
    1320             :     {
    1321       23521 :         delta[i] = sub( sub( peak_idx[i], peak_idx[i - 1] ), HVQ_CP_HUFF_OFFSET );
    1322       23521 :         move16();
    1323       23521 :         if ( LT_16( delta_max, delta[i] ) )
    1324             :         {
    1325        3181 :             delta_max = delta[i];
    1326        3181 :             move16();
    1327             :         }
    1328             :     }
    1329             : 
    1330             :     /* Calculate bits needed for huffman coding of deltas */
    1331        1463 :     delta_bits = -1;
    1332        1463 :     move16();
    1333        1463 :     IF( LE_16( delta_max, HVQ_CP_HUFF_MAX ) )
    1334             :     {
    1335        1416 :         delta_bits = 0;
    1336        1416 :         move16();
    1337       25797 :         FOR( i = 0; i < num_peaks; i++ )
    1338             :         {
    1339       24381 :             delta_bits = add( delta_bits, hvq_cp_huff_len[delta[i]] );
    1340             :         }
    1341             :     }
    1342             : 
    1343             :     /* Calculate bits neeed for sparse coding */
    1344        1463 :     sparse_bits = sparse_code_pos_fx( inp_abs, length, sparse_result );
    1345             : 
    1346             :     /* Decide which coding mode to use */
    1347        1463 :     test();
    1348        1463 :     IF( GT_16( delta_bits, sparse_bits ) || delta_bits < 0 )
    1349             :     {
    1350         167 :         push_indice( hBstr, IND_POS_IDX, HVQ_CP_SPARSE, 1 );
    1351             : 
    1352       15197 :         FOR( i = 0; i < sparse_bits; i++ )
    1353             :         {
    1354       15030 :             push_indice( hBstr, IND_POS_IDX, sparse_result[i], 1 );
    1355             :         }
    1356         167 :         bits = add( add( bits, sparse_bits ), 1 );
    1357             :     }
    1358             :     ELSE
    1359             :     {
    1360        1296 :         push_indice( hBstr, IND_POS_IDX, HVQ_CP_DELTA, 1 );
    1361             : 
    1362       23719 :         FOR( i = 0; i < num_peaks; i++ )
    1363             :         {
    1364       22423 :             j = delta[i];
    1365       22423 :             move16();
    1366       22423 :             push_indice( hBstr, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j] );
    1367             :         }
    1368        1296 :         bits = add( add( bits, delta_bits ), 1 );
    1369             :     }
    1370             : 
    1371             :     /* Send sign */
    1372       26447 :     FOR( i = 0; i < num_peaks; i++ )
    1373             :     {
    1374       24984 :         tmp = 1;
    1375       24984 :         move16();
    1376       24984 :         if ( inp_sign[i] < 0 )
    1377             :         {
    1378       12687 :             tmp = 0;
    1379       12687 :             move16();
    1380             :         }
    1381       24984 :         push_indice( hBstr, IND_POS_IDX, tmp, 1 );
    1382             :     }
    1383        1463 :     bits = add( bits, num_peaks );
    1384             : 
    1385        1463 :     return bits;
    1386             : }
    1387             : 
    1388           0 : static Word16 hvq_code_pos_fx(
    1389             :     BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle   */
    1390             :     const Word16 *inp,
    1391             :     const Word16 length,
    1392             :     const Word16 num_peaks )
    1393             : {
    1394             :     Word16 sparse_result[4 * HVQ_THRES_BIN_32k / HVQ_CP_L1_LEN];
    1395             :     Word16 delta[HVQ_MAX_PEAKS];
    1396             :     Word16 peak_idx[HVQ_MAX_PEAKS];
    1397             :     Word16 inp_abs[HVQ_THRES_BIN_32k];
    1398             :     Word16 inp_sign[HVQ_MAX_PEAKS];
    1399             : 
    1400             :     Word16 i, j;
    1401             :     Word16 bits;
    1402             :     Word16 delta_max;
    1403             :     Word16 delta_bits, sparse_bits;
    1404             :     Word16 tmp;
    1405             : 
    1406           0 :     bits = 0;
    1407           0 :     move16();
    1408             : 
    1409             :     /* Extract sorted peak index vector and sign vector */
    1410           0 :     j = 0;
    1411           0 :     move16();
    1412           0 :     FOR( i = 0; i < length; i++ )
    1413             :     {
    1414           0 :         inp_abs[i] = abs_s( inp[i] );
    1415           0 :         IF( inp[i] != 0 )
    1416             :         {
    1417           0 :             peak_idx[j] = i;
    1418           0 :             move16();
    1419           0 :             inp_sign[j] = inp[i];
    1420           0 :             move16();
    1421           0 :             j = add( j, 1 );
    1422             :         }
    1423             :     }
    1424             : 
    1425             :     /* Calculate delta */
    1426           0 :     delta[0] = add( peak_idx[0], HVQ_CP_HUFF_OFFSET );
    1427           0 :     move16();
    1428           0 :     delta_max = delta[0];
    1429           0 :     move16();
    1430           0 :     FOR( i = 1; i < num_peaks; i++ )
    1431             :     {
    1432           0 :         delta[i] = sub( sub( peak_idx[i], peak_idx[i - 1] ), HVQ_CP_HUFF_OFFSET );
    1433           0 :         move16();
    1434           0 :         if ( LT_16( delta_max, delta[i] ) )
    1435             :         {
    1436           0 :             delta_max = delta[i];
    1437           0 :             move16();
    1438             :         }
    1439             :     }
    1440             : 
    1441             :     /* Calculate bits needed for huffman coding of deltas */
    1442           0 :     delta_bits = -1;
    1443           0 :     move16();
    1444           0 :     IF( LE_16( delta_max, HVQ_CP_HUFF_MAX ) )
    1445             :     {
    1446           0 :         delta_bits = 0;
    1447           0 :         move16();
    1448           0 :         FOR( i = 0; i < num_peaks; i++ )
    1449             :         {
    1450           0 :             delta_bits = add( delta_bits, hvq_cp_huff_len[delta[i]] );
    1451             :         }
    1452             :     }
    1453             : 
    1454             :     /* Calculate bits neeed for sparse coding */
    1455           0 :     sparse_bits = sparse_code_pos_fx( inp_abs, length, sparse_result );
    1456             : 
    1457             :     /* Decide which coding mode to use */
    1458           0 :     test();
    1459           0 :     IF( GT_16( delta_bits, sparse_bits ) || delta_bits < 0 )
    1460             :     {
    1461           0 :         push_indice( hBstr, IND_POS_IDX, HVQ_CP_SPARSE, 1 );
    1462             : 
    1463           0 :         FOR( i = 0; i < sparse_bits; i++ )
    1464             :         {
    1465           0 :             push_indice( hBstr, IND_POS_IDX, sparse_result[i], 1 );
    1466             :         }
    1467           0 :         bits = add( add( bits, sparse_bits ), 1 );
    1468             :     }
    1469             :     ELSE
    1470             :     {
    1471           0 :         push_indice( hBstr, IND_POS_IDX, HVQ_CP_DELTA, 1 );
    1472             : 
    1473           0 :         FOR( i = 0; i < num_peaks; i++ )
    1474             :         {
    1475           0 :             j = delta[i];
    1476           0 :             move16();
    1477           0 :             push_indice( hBstr, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j] );
    1478             :         }
    1479           0 :         bits = add( add( bits, delta_bits ), 1 );
    1480             :     }
    1481             : 
    1482             :     /* Send sign */
    1483           0 :     FOR( i = 0; i < num_peaks; i++ )
    1484             :     {
    1485           0 :         tmp = 1;
    1486           0 :         move16();
    1487           0 :         if ( inp_sign[i] < 0 )
    1488             :         {
    1489           0 :             tmp = 0;
    1490           0 :             move16();
    1491             :         }
    1492           0 :         push_indice( hBstr, IND_POS_IDX, tmp, 1 );
    1493             :     }
    1494           0 :     bits = add( bits, num_peaks );
    1495             : 
    1496           0 :     return bits;
    1497             : }

Generated by: LCOV version 1.14