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

Generated by: LCOV version 1.14