LCOV - code coverage report
Current view: top level - lib_lc3plus - sns_quantize_scf.c (source / functions) Hit Total Coverage
Test: Coverage on main -- conformance test test_26252.py @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 225 806 27.9 %
Date: 2025-11-01 05:07:43 Functions: 13 30 43.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.6.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             : 
      10             : #include "options.h"
      11             : #include "wmc_auto.h"
      12             : #include "functions.h"
      13             : 
      14             : #ifdef CR9_C_ADD_1p25MS_LRSNS
      15             : 
      16             : static LC3_INT16 get_lead_sign( LC3_UINT32* ind_in );
      17             : static void mind2vec_one( LC3_UINT8 k_val_in, LC3_INT16 leading_sign, LC3_INT32* vec_out );
      18             : 
      19           0 : LC3_INT16 get_lead_sign( LC3_UINT32* ind_in )
      20             : {
      21             :     LC3_INT16 leading_sign;
      22           0 :     leading_sign = +1;
      23           0 :     if ( ( ( *ind_in ) & 0x1 ) != 0 )
      24             :     {
      25           0 :         leading_sign = -1;
      26             :     }
      27           0 :     ( *ind_in ) = ( *ind_in >> 1 );
      28             : 
      29           0 :     return leading_sign;
      30             : }
      31             : 
      32           0 : void mind2vec_one( LC3_UINT8 k_val_in,     /* i:  nb unit pulses  */
      33             :                    LC3_INT16 leading_sign, /* i: leading sign  -1, 1 */
      34             :                    LC3_INT32* vec_out /* o:  updated pulse train   */ )
      35             : {
      36             :         LC3_INT32 amp;
      37           0 :     amp = k_val_in;
      38           0 :     if ( leading_sign < 0 )
      39             :     {
      40           0 :         amp = -k_val_in;
      41             :     }
      42           0 :     *vec_out = amp;
      43           0 : }
      44             : 
      45             : static LC3_UINT8 setval_update_sign( LC3_INT16 k_delta, LC3_UINT8 k_max_local_in, LC3_INT16* leading_sign, LC3_UINT32* ind_in, LC3_INT32* vec_out );
      46             : 
      47             : static void mind2vec_tab( LC3_UINT8 dim_in, LC3_UINT8 k_max_local, LC3_INT16 leading_sign, LC3_UINT32 ind, LC3_INT32* vec_out );
      48             : 
      49             : #endif
      50             : 
      51             : #ifdef CR9_C_ADD_1p25MS_LRSNS
      52             : static void MPVQdeenum( LC3_UINT8 dim_in, LC3_UINT8 k_val_in, LC3_INT32 LS_ind, LC3_INT32 MPVQ_ind, LC3_INT32* vec_out );
      53             : #endif
      54             : 
      55             : #ifdef CR9_C_ADD_1p25MS_LRSNS
      56             : 
      57           0 : LC3_UINT8 setval_update_sign( LC3_INT16 k_delta,        /* i  */
      58             :                               LC3_UINT8 k_max_local_in, /* i  */
      59             :                               LC3_INT16* leading_sign,  /* i/o */
      60             :                               LC3_UINT32* ind_in,       /* i/o */
      61             :                               LC3_INT32* vec_out /* i/o */ )
      62             : {
      63             :     LC3_UINT8 k_max_local_out;
      64           0 :     k_max_local_out = k_max_local_in;
      65           0 :     if ( k_delta != 0 )
      66             :     {
      67           0 :         mind2vec_one( k_delta, *leading_sign, vec_out );
      68           0 :         *leading_sign = get_lead_sign( ind_in );
      69           0 :         k_max_local_out -= k_delta;
      70             :     }
      71             : 
      72           0 :     return k_max_local_out;
      73             : }
      74             : 
      75             : #endif
      76             : 
      77             : #ifdef CR9_C_ADD_1p25MS_LRSNS
      78             : 
      79           0 : void mind2vec_tab( LC3_UINT8 dim_in,       /* i:  dimension        */
      80             :                    LC3_UINT8 k_max_local,  /* i:  nb unit pulses   */
      81             :                    LC3_INT16 leading_sign, /* i:  leading sign     */
      82             :                    LC3_UINT32 ind,         /* i:  MPVQ-index       */
      83             :                    LC3_INT32* vec_out /* o:  pulse train      */ )
      84             : {
      85             :      /* pvq_enc_A = MPVQ_offsets */
      86             :         LC3_UINT8 pos, k_acc;
      87             :         LC3_UINT32 UL_tmp_offset;
      88             :         LC3_INT32 UL_diff;
      89             :         LC3_INT16 wrap_flag, k_delta;
      90             :         const LC3_UINT32* h_row_ptr;
      91             :     /* init */
      92           0 :     h_row_ptr = &( pvq_enc_A[( dim_in - 1 )][0] );
      93           0 :     k_acc = k_max_local;
      94             : 
      95             :     /* loop over positions */
      96           0 :     for ( pos = 0; pos < dim_in; pos++ )
      97             :     {
      98           0 :         if ( ind != 0 )
      99             :         {
     100           0 :             k_acc = k_max_local;
     101           0 :             UL_tmp_offset = h_row_ptr[k_acc];
     102             : 
     103           0 :             wrap_flag = ( ind < UL_tmp_offset );
     104           0 :             UL_diff = (LC3_INT32) ( (LC3_INT32) ind - (LC3_INT32) UL_tmp_offset );
     105             : 
     106           0 :             while ( wrap_flag != 0 )
     107             :             {
     108           0 :                 k_acc--;
     109           0 :                 wrap_flag = ( ind < h_row_ptr[k_acc] );
     110           0 :                 UL_diff = (LC3_INT32) ( (LC3_INT32) ind - (LC3_INT32) h_row_ptr[k_acc] );
     111             :             }
     112           0 :             ind = UL_diff;
     113           0 :             k_delta = k_max_local - k_acc;
     114             :         }
     115             :         else
     116             :         {
     117           0 :             mind2vec_one( k_max_local, leading_sign, &vec_out[pos] );
     118           0 :             break;
     119             :         }
     120           0 :         k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos] );
     121           0 :         h_row_ptr -= 11; /* reduce dimension in MPVQ_offsets table */
     122             :     }
     123           0 : }
     124             : 
     125             : #endif
     126             : 
     127             : #ifdef CR9_C_ADD_1p25MS_LRSNS
     128             : 
     129           0 : void MPVQdeenum( LC3_UINT8 dim_in,   /* i :  dimension of vec_out     */
     130             :                  LC3_UINT8 k_val_in, /* i :  number of unit pulses    */
     131             :                  LC3_INT32 LS_ind,   /* i :  leading sign index       */
     132             :                  LC3_INT32 MPVQ_ind, /* i :  MPVQ shape index         */
     133             :                  LC3_INT32* vec_out /* o :  PVQ integer pulse train  */ )
     134             : {
     135             :         LC3_INT32 leading_sign;
     136             : 
     137             : 
     138           0 :     leading_sign = 1;
     139           0 :     if ( LS_ind != 0 )
     140             :     {
     141           0 :         leading_sign = -1;
     142             :     }
     143             : 
     144           0 :     mind2vec_tab( dim_in, k_val_in, leading_sign, MPVQ_ind, vec_out );
     145           0 : }
     146             : 
     147             : /* local funcs*/
     148             : 
     149             : static void FESSdeenum(LC3_UINT8 dim_in,    /* i :  dimension of vec_out     */
     150             :     LC3_UINT8 n_env,     /* i :  number envelopes    */
     151             :     LC3_UINT8 n_shift,   /* i :  number shifts        */
     152             :     LC3_UINT8 n_signs,   /* i :  number signs          */
     153             :     LC3_INT32 env_ind,   /*  i:indx */
     154             :     LC3_INT32 shift_ind, /*  i:indx */
     155             :     LC3_INT32 sign_ind,  /*  i:indx */
     156             :     LC3_INT32* vec_out /* o :  FESS  integer  pulse train  */);
     157             : 
     158             : LC3_INT32 snsQuantScfEncLRSt1ABC(LC3_FLOAT* env, LC3_INT32* L_index, LC3_FLOAT *min_mse_saveBCA_ptr,
     159             :     LC3_INT32* ind_saveB_ptr, LC3_FLOAT* st1_vectors,
     160             :     LC3_INT32 pitch_rx, LC3_INT32 ltpf_rx);
     161             :  
     162             : #endif /*  CR9_C_ADD_1p25MS_LRSNS*/
     163             : 
     164             : static void pvq_dec(LC3_INT k, LC3_INT m, LC3_INT LS_ind, LC3_INT MPVQ_ind, LC3_INT* pulses);
     165             : static LC3_INT  find_last_indice_le(LC3_INT compare, const LC3_UINT32* array, LC3_INT len);
     166             : static void idct_II(LC3_FLOAT* in, LC3_FLOAT* out, LC3_INT len);
     167             : 
     168     1181012 : void idct_II(LC3_FLOAT* in, LC3_FLOAT* out, LC3_INT len)
     169             : {
     170             :     LC3_INT i;
     171             :     LC3_FLOAT norm1, sum;
     172             : 
     173     1181012 :     norm1 = 0.353553390593274; /* sqrt(2 / 16) */
     174             :     
     175    20077204 :     for (i = 0; i < len; i++) {
     176    18896192 :         sum = mac_loop(in, idct_lookup[i], len);
     177    18896192 :         out[i] = norm1 * sum;
     178             :     }
     179     1181012 : }
     180             : 
     181             : #ifdef FIX_FLOAT_ENC_PVQ_PULSE_LOOP 
     182             : static LC3_INT32 pvq_pulse_search_lc(LC3_FLOAT* xabs, LC3_FLOAT* ener, LC3_FLOAT* corr, LC3_INT32* y, LC3_INT32 start, LC3_INT32 end)
     183             : {
     184             :     Dyn_Mem_Deluxe_In(
     185             :     LC3_INT32 i;
     186             :     LC3_INT32 nBest;
     187             :     LC3_FLOAT max_norm_ratio, cand_norm_ratio;
     188             :     LC3_FLOAT currCorr;
     189             :     LC3_INT32 currEnInt;
     190             :     const LC3_FLOAT* isqrt_QxTab;
     191             :     );
     192             : 
     193             :     const LC3_INT16 isqrt_Q16tab[1 + 64] = {     /* table generated using ISqrt16 function + shift to Q16 */
     194             :                                                 32767, 32767, 32767, 32767, 32766, 29308, 26754, 24770, 23169, 21844,
     195             :                                                 20723, 19759, 18918, 18176, 17515, 16921, 16383, 15894, 15446, 15034,
     196             :                                                 14654, 14300, 13972, 13665, 13377, 13107, 12852, 12612, 12385, 12169,
     197             :                                                 11965, 11770, 11584, 11407, 11238, 11077, 10922, 10773, 10631, 10493,
     198             :                                                 10361, 10234, 10112, 9993, 9879, 9769, 9662, 9559, 9459, 9362,
     199             :                                                 9268, 9176, 9088, 9001, 8918, 8836, 8757, 8680, 8605, 8532,
     200             :                                                 8460, 8390, 8323, 8256, 8191
     201             :     };
     202             :      LC3_FLOAT isqrt_Q16tabFlt[1 + 64];
     203             : 
     204             :     const LC3_INT16 isqrt_Q15tab[1 + 6] = {
     205             :         /* onepulse_search_tab based search , Q15 table generated using isqrt_Q16tab table for idx=[8(4*2),16(4*4), 20(4*5),24(4*6)  ]    */
     206             :         /* this slighly suboptimal inv_sqrt(x) table is used to enable optional exact use of the ROM saving BASOP ISqrt16() function */
     207             : 
     208             :                                                    32767/*0*/, 32766/*1*/, 23169 /*2*/, 18918 /*3*/ , 16384/*4*/ , 14654 /*5*/,  13377/*6*/
     209             :                                                    /* i.e. value in isqrt_Q15tab[n=0..6]  ==  isqrt_Q16tab[4*n]  */
     210             :     };
     211             :    LC3_FLOAT isqrt_Q15tabFlt[1 + 6];
     212             : 
     213             :     for ( i = 0; i <= 64; i++ ) 
     214             :     {
     215             :         isqrt_Q16tabFlt[i] = isqrt_Q16tab[i] / 65536.0; 
     216             :     }
     217             :     for (i = 0; i <= 6; i++)
     218             :     {
     219             :         isqrt_Q15tabFlt[i] = isqrt_Q15tab[i] / 32768.0;
     220             :     }
     221             : 
     222             : 
     223             :     isqrt_QxTab = isqrt_Q16tabFlt;    /* Q16 table valid for energies 4...64  */
     224             :   
     225             :     assert( *ener >= 0.0 );
     226             :     *ener += 1.0;  /* Added once for the entire loop */
     227             :     if (*ener  <= 3.0 ) /* +1 for the inloop value of *ener  was preadded before */
     228             :     {
     229             :         isqrt_QxTab = isqrt_Q15tabFlt;      /* energies:  1...6   */
     230             :     }
     231             : 
     232             :     nBest = -1;
     233             :     max_norm_ratio = -1.0; 
     234             :     /* Iterative max search using tabulated  inv sqrt  */
     235             :     for (  i = start; i < end; i++)
     236             :     {
     237             :         currCorr = *corr + xabs[i];
     238             :         currEnInt  = ((LC3_INT32) *ener)  + (2 * y[i]);
     239             : 
     240             :         cand_norm_ratio =  currCorr *  isqrt_QxTab[currEnInt];
     241             : 
     242             :         if ( cand_norm_ratio >=  max_norm_ratio ) 
     243             :         {
     244             :             nBest = i;
     245             :         }
     246             :         max_norm_ratio = LC3_FMAX(max_norm_ratio, cand_norm_ratio); /* always update */
     247             :     }
     248             : 
     249             :     *corr += xabs[nBest];
     250             :     *ener += (2 * y[nBest]);
     251             : 
     252             :     assert(nBest >= 0);
     253             :     assert(nBest <=M);
     254             :     assert(*ener <= 64.0);
     255             :     y[nBest] += 1; /* Add the selected unit pulse */
     256             : 
     257             :     Dyn_Mem_Deluxe_Out();
     258             :     return nBest;
     259             : }
     260             : #endif 
     261             : 
     262     7387957 : static LC3_INT pvq_pulse_search(LC3_FLOAT *xabs, LC3_FLOAT *ener, LC3_FLOAT *corr, LC3_INT *y, LC3_INT start, LC3_INT end)
     263             : {
     264             :     LC3_INT i;
     265             :     LC3_INT nBest;
     266             :     LC3_FLOAT bestCorrSq, bestEn;
     267             :     LC3_FLOAT corrSq, currCorr, currEn;
     268             : 
     269     7387957 :     nBest = 0;
     270     7387957 :     bestCorrSq = 0.0;
     271     7387957 :     bestEn = 0.0;
     272             : 
     273     7387957 :     *ener += 1; /* Added once for the entire loop */
     274             : 
     275     7387957 :     i = start;
     276             : 
     277     7387957 :     currCorr = *corr + xabs[i];
     278     7387957 :     currEn = *ener + (2 * y[i]);
     279             : 
     280     7387957 :     corrSq = currCorr * currCorr;
     281             : 
     282     7387957 :     bestEn = currEn;
     283     7387957 :     bestCorrSq = corrSq;
     284     7387957 :     nBest = i;
     285             : 
     286             :     /* Iterative max search as recommended in the spec */
     287   106299685 :     for (; i < end; i++)
     288             :     {
     289    98911728 :         currCorr = *corr + xabs[i];
     290    98911728 :         currEn = *ener + (2 * y[i]);
     291             : 
     292    98911728 :         corrSq = currCorr * currCorr;
     293             : 
     294    98911728 :         if ((corrSq * bestEn) > (bestCorrSq * currEn))
     295             :         {
     296    15023366 :             bestEn = currEn;
     297    15023366 :             bestCorrSq = corrSq;
     298    15023366 :             nBest = i;
     299             :         }
     300             :     }
     301             : 
     302     7387957 :     *corr += xabs[nBest];
     303     7387957 :     *ener += (2 * y[nBest]);
     304             : 
     305     7387957 :     y[nBest] += 1; /* Add the selected unit pulse */
     306             : 
     307     7387957 :     return nBest;
     308             : }
     309             : 
     310     2362024 : static void pvq_enc_vec_normalize(LC3_FLOAT *vec, LC3_INT N)
     311             : {
     312     2362024 :     LC3_FLOAT mag = 0.0, norm_fac;
     313             :     LC3_INT i;
     314             : 
     315    40154408 :     for (i = 0; i < N; i++)
     316             :     {
     317    37792384 :         mag += (vec[i] * vec[i]);
     318             :     }
     319             : 
     320     2362024 :     norm_fac = 1.0 / LC3_SQRT(mag);
     321             : 
     322    40154408 :     for (i = 0; i < N; i++)
     323             :     {
     324    37792384 :         vec[i] = vec[i] * norm_fac;
     325             :     }
     326             : 
     327     2362024 :     return;
     328             : }
     329             : 
     330      590506 : static void pvq_enc_search(LC3_FLOAT* x_in, LC3_INT y[4][M])
     331             : {
     332             :     LC3_INT i, N, K, pulse_total, N_setA;
     333             :     LC3_FLOAT abs_sum, projfac;
     334             :     LC3_FLOAT xabs[16];
     335             :     LC3_FLOAT yy, xy;
     336             : 
     337      590506 :     abs_sum = 0.0;
     338             : 
     339             :     /* Step 1 : Projection to pyramid N=16, K=6 */
     340      590506 :     N = 16;
     341      590506 :     K = 6;
     342      590506 :     pulse_total = 0;
     343      590506 :     N_setA = 10;
     344             : 
     345      590506 :     yy = xy = 0.0f;
     346             : 
     347    10038602 :     for (i = 0; i < N; i++)
     348             :     {
     349     9448096 :         xabs[i] = LC3_FABS(x_in[i]);
     350     9448096 :         abs_sum += xabs[i];
     351             :     }
     352             : 
     353      590506 :     projfac = (K - 1) / abs_sum;
     354             : 
     355    10038602 :     for (i = 0; i < N; i++)
     356             :     {
     357     9448096 :         y[3][i] = floor(xabs[i] * projfac);
     358             : 
     359     9448096 :         pulse_total += y[3][i];
     360             : 
     361     9448096 :         yy += (y[3][i] * y[3][i]);
     362     9448096 :         xy += (xabs[i] * y[3][i]);
     363             :     }
     364             : 
     365             :     /* Step 2: Adding unit pulses up to K = 6 */
     366     3975191 :     for (; pulse_total < K; pulse_total++)
     367             :     {
     368     3384685 :         pvq_pulse_search(xabs, &yy, &xy, y[3], 0, N);
     369             :     }
     370             : 
     371             :     /* Step 3: Adding unit pulses up to K = 8 */
     372      590506 :     memcpy(y[2], y[3], sizeof(LC3_INT)*N);
     373      590506 :     K = 8;
     374             : 
     375     1771518 :     for (; pulse_total < K; pulse_total++)
     376             :     {
     377     1181012 :         pvq_pulse_search(xabs, &yy, &xy, y[2], 0, N);
     378             :     }
     379             : 
     380      590506 :     memcpy(y[1], y[2], sizeof(LC3_INT)*N_setA);
     381             : 
     382             :     /* Step 4: Remove unit pulses not belonging to set A */
     383     4133542 :     for (i = N_setA; i < N; i++)
     384             :     {
     385     3543036 :         y[1][i] = 0;
     386             :     }
     387             : 
     388             :     /* Step 5: Update yy and xy terms to reflect y1 */
     389      590506 :     yy = 0;
     390      590506 :     xy = 0;
     391      590506 :     pulse_total = 0;
     392             : 
     393     6495566 :     for (i = 0; i < N_setA; i++)
     394             :     {
     395     5905060 :         yy += (y[1][i] * y[1][i]);
     396     5905060 :         xy += (xabs[i] * y[1][i]);
     397             : 
     398     5905060 :         pulse_total += y[1][i];
     399             :     }
     400             : 
     401             :     /* Step 6: Add unit pulses until K = 10 over N = 10 */
     402      590506 :     K = 10;
     403     2822260 :     for (; pulse_total < K; pulse_total++)
     404             :     {
     405     2231754 :         pvq_pulse_search(xabs, &yy, &xy, y[1], 0, N_setA);
     406             :     }
     407             : 
     408      590506 :     memcpy(y[0], y[1], sizeof(LC3_INT)*N);
     409             : 
     410             :     /* Step 7: Add unit pulses until K = 1 over N = 6 in set B*/
     411      590506 :     pvq_pulse_search(xabs, &yy, &xy, y[0], N_setA, N);
     412             : 
     413             :     /* Step 8: Add signs to each of the 4 vectors from x */
     414    10038602 :     for (i = 0; i < N; i++)
     415             :     {
     416     9448096 :         if (x_in[i] < 0)
     417             :         {
     418     4605166 :             y[0][i] = -y[0][i];
     419     4605166 :             y[1][i] = -y[1][i];
     420     4605166 :             y[2][i] = -y[2][i];
     421     4605166 :             y[3][i] = -y[3][i];
     422             :         }
     423             :     }
     424             : 
     425      590506 :     return;
     426             : }
     427             : 
     428    10629108 : static LC3_FLOAT calc_mse(LC3_FLOAT *t2rot, LC3_FLOAT *y, LC3_FLOAT gain, LC3_INT N)
     429             : {
     430             :     LC3_FLOAT mse;
     431             :     LC3_INT i;
     432             : 
     433    10629108 :     mse = 0.0;
     434             : 
     435   180694836 :     for (i = 0; i < N; i++)
     436             :     {
     437   170065728 :         LC3_FLOAT err = (t2rot[i] - gain * y[i]);
     438   170065728 :         mse += (err * err);
     439             :     }
     440             : 
     441    10629108 :     return mse;
     442             : }
     443             : 
     444      590506 : static void sns_quant_adj_gain_shape_search(LC3_FLOAT *t2rot, LC3_INT y[4][M] ,
     445             :     LC3_INT *gain_idx, LC3_INT *shape_idx, LC3_FLOAT *y_norm, LC3_FLOAT *scq_gain)
     446             : {
     447             :     LC3_INT gidx, sidx;
     448             :     LC3_FLOAT min_mse, mse;
     449             :     LC3_INT N;
     450             :     LC3_FLOAT yCur[4][16];
     451             :     LC3_INT i;
     452             : 
     453      590506 :     const LC3_INT gain_levels[4] = { 2, 4, 4, 8 };
     454      590506 :     const LC3_FLOAT *sns_vq_gains[4] = { sns_vq_reg_adj_gains_fl , sns_vq_reg_lf_adj_gains_fl ,
     455             :         sns_vq_near_adj_gains_fl , sns_vq_far_adj_gains_fl };
     456             : 
     457      590506 :     min_mse = -1.0;
     458      590506 :     N = 16;
     459             : 
     460             : 
     461      590506 :     *gain_idx = *shape_idx = 0;
     462             : 
     463     2952530 :     for (sidx = 0; sidx < 4; sidx++)
     464             :     {
     465    40154408 :         for (i = 0; i < N; i++)
     466             :         {
     467    37792384 :             yCur[sidx][i] = (LC3_FLOAT)y[sidx][i];
     468             :         }
     469             : 
     470             :         /* Step 9: Normalize the vectors */
     471     2362024 :         pvq_enc_vec_normalize(yCur[sidx], N);
     472             : 
     473    12991132 :         for (gidx = 0; gidx < gain_levels[sidx]; gidx++)
     474             :         {
     475    10629108 :             mse = calc_mse(t2rot, yCur[sidx], sns_vq_gains[sidx][gidx], N);
     476             : 
     477    10629108 :             if ((mse < min_mse)  || (min_mse < 0))
     478             :             {
     479     1231707 :                 *gain_idx = gidx;
     480     1231707 :                 *shape_idx = sidx;
     481     1231707 :                 min_mse = mse;
     482             :             }
     483             :         }
     484             :     }
     485             : 
     486    10038602 :     for (i = 0; i < N; i++)
     487             :     {
     488     9448096 :         y_norm[i] = yCur[*shape_idx][i];
     489             :     }
     490             : 
     491      590506 :     *scq_gain = sns_vq_gains[*shape_idx][*gain_idx];
     492             : 
     493      590506 :     return;
     494             : }
     495             : 
     496     9353164 : static void enc_push_sign(LC3_FLOAT val, LC3_UINT32 *next_sign_ind, LC3_INT *index)
     497             : {
     498     9353164 :     if (((*next_sign_ind & 0x80000000U) == 0) && (val != 0)) {
     499     3580664 :         *index = 2 * (*index) + *next_sign_ind;
     500             :     }
     501     9353164 :     if (val < 0) {
     502     2126458 :         *next_sign_ind = 1;
     503             :     }
     504     9353164 :     if (val > 0) {
     505     2314397 :         *next_sign_ind = 0;
     506             :     }
     507             : 
     508     9353164 :     return;
     509             : }
     510             : 
     511      860191 : static void MPVQ_enum(LC3_INT dim, LC3_INT *sns_vec, LC3_INT *index_val, LC3_INT *lead_sign_ind)
     512             : {
     513             :     LC3_UINT32 next_sign_ind;
     514             :     LC3_INT k_val_acc;
     515             :     LC3_INT pos;
     516             :     LC3_INT index, n;
     517             :     LC3_INT const *row_ptr;
     518             : 
     519             :     /* MPVQ-index composition loop */
     520             :     LC3_INT tmp_h_row;
     521             :     LC3_INT tmp_val;
     522             : 
     523      860191 :     next_sign_ind = 0x80000000U;
     524      860191 :     k_val_acc = 0;
     525      860191 :     pos = dim;
     526      860191 :     index = 0;
     527      860191 :     n = 0;
     528             : 
     529      860191 :     row_ptr = (LC3_INT const *)&(pvq_enc_A[n]);
     530      860191 :     tmp_h_row = row_ptr[0];
     531             : 
     532    10213355 :     for (pos--; pos >= 0; pos--)
     533             :     {
     534     9353164 :         tmp_val = sns_vec[pos];
     535     9353164 :         enc_push_sign(tmp_val, &next_sign_ind, &index);
     536             : 
     537     9353164 :         index += tmp_h_row;
     538     9353164 :         k_val_acc += abs(tmp_val);
     539     9353164 :         if (pos != 0) {
     540     8492973 :             n += 1; /* switch row in offset table MPVQ_offsets(n, k) */
     541             :         }
     542     9353164 :         row_ptr = (LC3_INT const *)&(pvq_enc_A[n]);
     543             : 
     544     9353164 :         tmp_h_row = row_ptr[k_val_acc];
     545             :     }
     546             : 
     547      860191 :     *index_val = index;
     548      860191 :     *lead_sign_ind = next_sign_ind;
     549             : 
     550      860191 :     return;
     551             : }
     552             : 
     553     1181012 : static LC3_INT MSEsearch (LC3_FLOAT *scf, const LC3_FLOAT sns_CB[8][32])
     554             : {
     555             :     LC3_FLOAT distance, mse;
     556             :     LC3_INT i, n, ind;
     557             : 
     558     1181012 :     ind = 0;
     559             : 
     560     1181012 :     distance = (LC3_FLOAT) LC3_CONST_POW_2_100;
     561    38973396 :     for (i = 0; i < 32; i++) {
     562    37792384 :         mse = 0;
     563   340131456 :         for (n = 0; n < 8; n++) {
     564   302339072 :             mse += (scf[n] - sns_CB[n][i]) * (scf[n] - sns_CB[n][i]);
     565             :         }
     566             : 
     567    37792384 :         if (mse < distance) {
     568     4846883 :             distance = mse;
     569     4846883 :             ind      = i;
     570             :         }
     571             :     }
     572     1181012 :     return ind;
     573             : }
     574             : 
     575      590506 : void process_snsQuantizesScf_Enc(LC3_FLOAT* env, LC3_INT* index, LC3_FLOAT* envq, Dct2 dct2structSNS)
     576             : {
     577             :     LC3_FLOAT stage2_en1_norm_sub[M];
     578             :     LC3_INT i, j;
     579             :     LC3_FLOAT st1_vector[M];
     580             :     LC3_FLOAT pvq_target_pre[M];
     581             :     LC3_FLOAT pvq_target[M];
     582             :     LC3_FLOAT stage2_en1_norm_pre_sub[M];
     583             :     LC3_INT gain, shape;
     584             :     LC3_FLOAT scfq_gain;
     585             :     LC3_INT y[4][M];
     586             : 
     587             :     /* Stage 1 split VQ */
     588      590506 :     index[0] = MSEsearch(&env[0], sns_LFCB);  /* ind_LF */
     589      590506 :     index[1] = MSEsearch(&env[8], sns_HFCB);  /* ind_HF */
     590             : 
     591      590506 :     j = 8;
     592     5314554 :     for (i = 0; i < 8; i++, j++) {
     593     4724048 :         st1_vector[i] = sns_LFCB[i][index[0]];
     594     4724048 :         st1_vector[j] = sns_HFCB[i][index[1]];
     595             :     }
     596             : 
     597             :     /* STAGE 2 */
     598    10038602 :     for (i = 0; i < 16; i++) {
     599     9448096 :         pvq_target_pre[i] = env[i] - st1_vector[i];
     600             :     }
     601             : 
     602      590506 :     dct2_apply(&dct2structSNS, pvq_target_pre, pvq_target);
     603      590506 :     pvq_enc_search(pvq_target, y);
     604      590506 :     sns_quant_adj_gain_shape_search(pvq_target, y, &gain, &shape, stage2_en1_norm_pre_sub, &scfq_gain);
     605             : 
     606             :     /* Inverse transform */
     607      590506 :     idct_II(stage2_en1_norm_pre_sub, stage2_en1_norm_sub, M);
     608             : 
     609      590506 :     index[2] = shape;
     610      590506 :     index[3] = gain;
     611             : 
     612      590506 :     if (shape < 2) {
     613      285507 :         MPVQ_enum(10, y[shape], &index[5], &index[4]);
     614             :     }
     615             :     else {
     616      304999 :         MPVQ_enum(M, y[shape], &index[5], &index[4]);
     617             :     }
     618             : 
     619      590506 :     if (shape == 0) {
     620             :         LC3_INT ls_ind, ind;
     621      269685 :         MPVQ_enum(6, &y[shape][10], &ind, &ls_ind);
     622      269685 :         index[6] = ind * 2 + ls_ind;
     623             :     }
     624      320821 :     else if (shape == 2) {
     625      293724 :         index[6] = -1;
     626             :     }
     627             :     else {
     628       27097 :         index[6] = -2;
     629             :     }
     630             : 
     631    10038602 :     for (i = 0; i < M; i++) {
     632     9448096 :         envq[i] = st1_vector[i] + (stage2_en1_norm_sub[i] * scfq_gain);
     633             :     }
     634      590506 : }
     635             : 
     636     6990963 : LC3_INT find_last_indice_le(LC3_INT compare, const LC3_UINT32* array, LC3_INT len)
     637             : {
     638     6990963 :     LC3_INT idx = 0, i = 0;
     639             : 
     640    47551324 :     for (i = 0; i < len; i++) {
     641    40560361 :         if ((LC3_UINT32)compare >= array[i]) {
     642    35963104 :             idx++;
     643             :         }
     644             :     }
     645             : 
     646     6990963 :     if (idx > 0) {
     647     6990963 :         idx--;
     648             :     }
     649             : 
     650     6990963 :     return idx;
     651             : }
     652             : 
     653      860191 : void pvq_dec(LC3_INT k, LC3_INT m, LC3_INT LS_ind, LC3_INT MPVQ_ind, LC3_INT* pulses)
     654             : {
     655      860191 :     LC3_INT leading_sign, idx, k_delta = 0, pos;
     656             : 
     657      860191 :     leading_sign = 1 - 2 * LS_ind;
     658             : 
     659             :     /* Decoding loop */
     660             : 
     661     7851154 :     for (pos = 0; pos < m; pos++) {
     662     7851154 :         if (MPVQ_ind != 0) {
     663             :             /* Find last indice */
     664     6990963 :             idx      = find_last_indice_le(MPVQ_ind, &pvq_enc_A[m - pos - 1][0], k + 1);
     665     6990963 :             MPVQ_ind = MPVQ_ind - pvq_enc_A[m - pos - 1][idx];
     666     6990963 :             k_delta  = k - idx;
     667             :         } else {
     668      860191 :             pulses[pos] = leading_sign * k;
     669      860191 :             break;
     670             :         }
     671             : 
     672     6990963 :         if (k_delta != 0) {
     673     3580664 :             pulses[pos] = leading_sign * k_delta;
     674     3580664 :             if ((MPVQ_ind % 2) != 0) {
     675     1718953 :                 leading_sign = -1;
     676             :             } else {
     677     1861711 :                 leading_sign = 1;
     678             :             }
     679             : 
     680     3580664 :             MPVQ_ind = floor(MPVQ_ind / 2);
     681     3580664 :             k        = k - k_delta;
     682             :         }
     683             :     }
     684      860191 : }
     685             : 
     686      590506 : void process_snsQuantizesScf_Dec(LC3_INT* scf_idx, LC3_FLOAT* scf_q)
     687             : {
     688             :     LC3_INT   i, submode;
     689      590506 :     LC3_INT   pulses2[6] = {0}, pulses[M] = {0};
     690      590506 :     LC3_FLOAT st2_vector[M], st2_vector_idct[M], sum = 0;
     691             : 
     692             :     /* Decode first stage */
     693             : 
     694     5314554 :     for (i = 0; i < 8; i++) {
     695     4724048 :         scf_q[i]     = sns_LFCB[i][scf_idx[0]];
     696     4724048 :         scf_q[i + 8] = sns_HFCB[i][scf_idx[1]];
     697             :     }
     698             : 
     699             :     /* STAGE 2 */
     700             :     /* Decode submode */
     701             : 
     702      590506 :     submode = scf_idx[2];
     703             : 
     704             :     /* Decode pulses */
     705             : 
     706      590506 :     if (submode < 2) {
     707      285507 :         pvq_dec(10, 10, scf_idx[4], scf_idx[5], pulses);
     708             : 
     709      285507 :         if (submode == 0) {
     710      269685 :             pvq_dec(1, 6, (scf_idx[6] % 2), floor(scf_idx[6] / 2), pulses2);
     711             : 
     712      269685 :             move_int(&pulses[10], pulses2, 6);
     713             : 
     714             :         } else {
     715       15822 :             pulses[15] = 0;
     716             :         }
     717      304999 :     } else if (submode == 2) {
     718      293724 :         pvq_dec(8, 16, scf_idx[4], scf_idx[5], pulses);
     719             :     } else {
     720       11275 :         pvq_dec(6, 16, scf_idx[4], scf_idx[5], pulses);
     721             :     }
     722             : 
     723             :     /* Normalization */
     724             : 
     725    10038602 :     for (i = 0; i < M; i++) {
     726     9448096 :         sum += pulses[i] * pulses[i];
     727             :     }
     728             : 
     729      590506 :     sum = 1.0 / LC3_SQRT(sum);
     730             : 
     731    10038602 :     for (i = 0; i < M; i++) {
     732     9448096 :     st2_vector[i] = pulses[i] * sum;
     733             :     }
     734             : 
     735             :     /* Inverse transform */
     736      590506 :     idct_II(st2_vector, st2_vector_idct, M);
     737             : 
     738             :     /* Gain */
     739             :     /* Add stage 1 and stage 2 */
     740    10038602 :     for (i = 0; i < M; i++) {
     741     9448096 :         scf_q[i] += st2_vector_idct[i] * sns_dec_gains[submode][scf_idx[3]];
     742             :     }
     743      590506 : }
     744             : 
     745             : #ifdef CR9_C_ADD_1p25MS_LRSNS
     746             : 
     747             : /* 29/30 bits  optimized search functions for PVQ and FESS  */
     748             : /* stage 2 submode shape  0:  "splitLF"  (N=5,K=6)(N=8,K=2)   or (N=5,K=8)(N=8,K=0) , 4 gains */
     749             : /* stage 2 submode shape  1:  "full" FB (N=15,K=5), 4xfixed  , 8 gains */
     750             : /* stage 2 submode shape  2-5: "fixed env "  (N=13-15,K=10-12), 4xfixed  , 8 gains */
     751             :  
     752           0 : static void pvq_fess_enc_search(LC3_FLOAT* x_in    /* i:   0...M-1 */
     753             :     , LC3_INT32 y[SNSLR_MAX_PVQ_SEARCH_CAND][M],   /* o:  [3]*[0...M-1] */
     754             :     LC3_INT32  *fixShapeNb                         /* o:   [-1, 0...3]  */
     755             : )
     756             : {
     757             :     LC3_INT32 i, j, curr_cand;
     758             :     LC3_INT32 NcandLF, Ngrp, Kgrp, Ktop_LF, Ntop_LF;
     759             :     LC3_INT32 NcandFB, Kfull;
     760             :     LC3_INT32 NcandFix, Kfix, Nsigns_fix;
     761             : 
     762             :     LC3_INT32 N, K, pulse_total, top_pulses;
     763             :     LC3_FLOAT abs_sum, projfac;
     764             :     LC3_FLOAT yy, xy;    /* in-loop energy  and corr  */
     765             : 
     766             :     LC3_FLOAT  yy_n5k8, xy_n5k8;
     767             :     LC3_FLOAT  xabs[M];
     768             :     LC3_INT32  y_tmp_n5k8[M];
     769             :     LC3_INT32  y_tmp[M];
     770             :     LC3_INT16  n, fix_ind, shift_ind;
     771             :     LC3_INT16 best_env_ind;
     772             :     LC3_INT16 best_shift_ind;
     773             :     LC3_INT16 best_ind;
     774             :     LC3_INT16 pulse_total_n5k8;
     775             :     LC3_FLOAT f_normcorr_fixenv[SNSLR_N_FIXENV][SNSLR_N_FIXENV_SHIFTS];
     776             :     LC3_FLOAT *p;
     777             :     const LC3_INT32* env_ptr;
     778             : 
     779             : #define SC 1 /*Starting coeff position of PVQ target  , (we have no DC) */
     780             :     {
     781             :         /*  no DC coeff , only coeff 1..15 is quantized in  the  range 0..15  */
     782           0 :         NcandLF = 1;
     783             : 
     784           0 :         Ngrp = 5;      /* PVQ(5, 6) = 10.94b , + P(8,2)=7b  + P(2,0)=0b */
     785           0 :         Kgrp = 6;
     786           0 :         Ntop_LF = 8;   /*   allow to encode less than M-sc -Ngrp  */
     787           0 :         Ktop_LF = 2;   /*   fill a few unit pulses in the HF region   */
     788             :                        /*   P(5,8)+P(10,0)  will also fit in  13 bits */
     789             :         /*  Fullband safety net */
     790           0 :         NcandFB = 1;
     791           0 :         Kfull = 5; ;      /* PVQ(15,5)= 16.65   bits  ,   */
     792             : 
     793             :         /*fixed env */
     794           0 :         NcandFix = 4;         /* 4th only has 10 signs */
     795           0 :         Kfix = 12;            /* number of signs  */
     796           0 :         Nsigns_fix = 12;       /* area to cover and  number of signs */
     797             :     }
     798             : 
     799           0 :     for (i = SC; i < (M); i++)
     800             :     {
     801           0 :         xabs[i] = LC3_FABS(x_in[i]);
     802             :     }
     803           0 :     xabs[0] = 0;
     804             : 
     805             :     /*   splitLF LFfocus subshape idx 0   */
     806           0 :     if (Kgrp > 0 && NcandLF > 0)
     807             :     {
     808           0 :         curr_cand = 0;
     809             :         /*   Projection to LF pyramid N=Ngrp, K=Kgrp  */
     810           0 :         abs_sum = 0.0;
     811           0 :         N = Ngrp;
     812           0 :         K = Kgrp;
     813           0 :         pulse_total = 0;
     814             : 
     815           0 :         for (i = SC; i < (SC + N); i++)
     816             :         {
     817           0 :             abs_sum += xabs[i];
     818             :         }
     819           0 :         projfac = (K - 1) / abs_sum;
     820             : 
     821           0 :         if (abs_sum == 0.0)
     822             :         {
     823           0 :             projfac = 0.0;
     824             :         }
     825             : 
     826           0 :         yy = xy = 0.0f;
     827           0 :         for (i = SC; i < (SC + N); i++)
     828             :         {
     829           0 :             y_tmp[i] = LC3_FLOOR(xabs[i] * projfac);    /* local projection within group over N coeffs used here  */
     830             : 
     831           0 :             pulse_total += y_tmp[i];
     832             : 
     833           0 :             yy += (y_tmp[i] * y_tmp[i]);
     834           0 :             xy += (xabs[i] * y_tmp[i]);
     835             :         }
     836             : 
     837             :         /* LF  Adding unit pulses up to K in LF */
     838           0 :         for (; pulse_total < K; pulse_total++)
     839             :         {
     840           0 :             pvq_pulse_search(xabs, &yy, &xy, y_tmp, SC, SC + N);
     841             :         }
     842             : 
     843             :         {
     844             :             /* allow (N=5,K=(6+2)=8) in low band only,  higher part is then zeroed  */
     845             :             /* can be multiplexed put in 13 bits */
     846           0 :             yy_n5k8 = yy;
     847           0 :             xy_n5k8 = xy;
     848           0 :             pulse_total_n5k8 = pulse_total;
     849             : 
     850           0 :             memset(y_tmp_n5k8, 0, sizeof(*y_tmp_n5k8)*M);
     851           0 :             memcpy(y_tmp_n5k8, y_tmp, sizeof(*y_tmp)*(SC + N));  /* cpy LF initial search result for n5k6 to n5k8 output  */
     852             : 
     853           0 :             for (; pulse_total_n5k8 < (K + 2); pulse_total_n5k8++)
     854             :             {
     855           0 :                 pvq_pulse_search(xabs, &yy_n5k8, &xy_n5k8, y_tmp_n5k8, SC, SC + N);
     856             :             }
     857             :         }
     858             : 
     859             : 
     860             :         /* split  HF    :   longer M vector  */
     861           0 :         memset(y[curr_cand], 0, sizeof(*y_tmp)*M);         /*zero full candidate vector  */
     862           0 :         memcpy(&(y[curr_cand]), y_tmp, sizeof(*y_tmp)*(SC + N));  /* cpy LF-part   to output  */
     863             : 
     864             : 
     865           0 :         if (Ktop_LF && (M - Ngrp - SC >= Ntop_LF))
     866             :         {
     867             : 
     868             :             /* xy = 0.0; yy = 0.0;   */
     869           0 :             memset(&(y_tmp[Ngrp]), 0, (M - SC - Ngrp) * sizeof(*y_tmp));
     870           0 :             top_pulses = 0;
     871             : 
     872           0 :             for (; top_pulses < Ktop_LF; top_pulses++)
     873             :             {
     874           0 :                 pvq_pulse_search(xabs, &yy, &xy, y_tmp, SC + N, SC + N + Ntop_LF);
     875             :             }
     876             : 
     877           0 :             for (j = SC + N; j < (SC + N + Ntop_LF); j++)
     878             :             {
     879           0 :                 y[curr_cand][j] = y_tmp[j];
     880             :             }
     881             :         }
     882             : 
     883             :         {
     884             :             /* shape 0 : decide on best split alternative  "0a" n5k6 + n8k2 + n2k0   or  "0b"  n5k8 + n10k0,
     885             :               shape only assessed , i.e. assume same  gain quantizer */
     886           0 :             if ((xy_n5k8*xy_n5k8)*yy > (xy*xy)*yy_n5k8)
     887             :             {
     888             :                 /* use  n5k8, with zeroed high band */
     889             :                 /* i.e. better to put two additional pulses in the n5 low band than in the higher band */
     890           0 :                 memcpy(&(y[curr_cand]), y_tmp_n5k8, sizeof(*y_tmp_n5k8)*(M));   /* cpy LFonly   to output  */
     891             :             }
     892             :         }
     893             : 
     894             :         /*  assign signs to the cand  vector  from x_in */
     895           0 :         for (i = SC; i < (M); i++)
     896             :         {
     897           0 :             if (x_in[i] < 0)
     898             :             {
     899           0 :                 y[curr_cand][i] *= -1;
     900             :             }
     901             :         }
     902           0 :         y[curr_cand][0] = 0;  /* DC */
     903             : 
     904             :     }
     905             : 
     906             :     /* shape 1 :  Full band shape analysis      */
     907           0 :     if (Kfull > 0 && NcandFB > 0)
     908             :     {
     909           0 :         curr_cand = 1;
     910           0 :         N = M - SC;
     911           0 :         K = Kfull;
     912             : 
     913             :         /* project */
     914           0 :         pulse_total = 0;
     915           0 :         yy = xy = 0.0f;
     916           0 :         abs_sum = 0.0;
     917           0 :         for (i = SC; i < SC + N; i++)
     918             :         {
     919           0 :             abs_sum += xabs[i];/* over N */
     920             :         }
     921             : 
     922           0 :         projfac = (K - 1) / abs_sum;
     923           0 :         if (abs_sum == 0.0)
     924             :         {
     925           0 :             projfac = 0.0;
     926             :         }
     927             : 
     928             : 
     929           0 :         memset(y_tmp, 0, sizeof(*y_tmp)*M);
     930           0 :         for (i = SC; i < SC + N; i++)
     931             :         {
     932           0 :             y_tmp[i] = LC3_FLOOR(xabs[i] * projfac);    /*  projection over N coeffs  */
     933           0 :             pulse_total += y_tmp[i];
     934           0 :             yy += (y_tmp[i] * y_tmp[i]);
     935           0 :             xy += (xabs[i] * y_tmp[i]);
     936             :         }
     937             : 
     938           0 :         for (; pulse_total < K; pulse_total++)
     939             :         {
     940           0 :             pvq_pulse_search(xabs, &yy, &xy, y_tmp, SC, SC + N);
     941             :         }
     942           0 :         memcpy(&(y[curr_cand]), y_tmp, sizeof(*y_tmp)*M);  /* cpy to output  */
     943             : 
     944             :        /* Step: Add signs to each of the full  vector from input  */
     945           0 :         for (i = SC; i < M; i++)
     946             :         {
     947           0 :             if (x_in[i] < 0)
     948             :             {
     949           0 :                 y[curr_cand][i] *= -1; ;
     950             :             }
     951             :         }
     952           0 :         y[curr_cand][0] = 0;
     953             :     } /* Fullband  */
     954             : 
     955             : 
     956             :     { /* fixed envelopes shifted signs shapes 2 ... 5 */
     957           0 :         best_env_ind = -1;
     958           0 :         best_shift_ind = -1;
     959             :  
     960             :         /* search fixed env shapes first */
     961             :          /* search shape of all fixed flat-ish envelopes using an optimal  nb_env*nbshifts shape analysis */
     962           0 :         if (Kfix > 0 && NcandFix > 0)
     963             :         {
     964           0 :             curr_cand = 2;
     965           0 :             N = Nsigns_fix;
     966           0 :             K = Kfix;
     967             : 
     968             :             /* find the minimum shape error across all possible 4  fixed envelopes and all 4 shifts */
     969             :             /* maximise normalized cross correlation  target*y  *(1/sqrt(y^2))  to minimize shape error */
     970             : 
     971           0 :             for (fix_ind = 0; fix_ind < SNSLR_N_FIXENV; fix_ind++)
     972             :             {
     973           0 :                 for (shift_ind = 0; shift_ind < SNSLR_N_FIXENV_SHIFTS; shift_ind++)
     974             :                 {
     975           0 :                     f_normcorr_fixenv[fix_ind][shift_ind] = 0.0;
     976           0 :                     for (n = 0; n < signs_fix[fix_ind]; n++)
     977             :                     {
     978           0 :                         f_normcorr_fixenv[fix_ind][shift_ind] += (xabs[SC + n + shift_ind] * env_ptrs[fix_ind][n + shift_ind]);
     979             :                     }
     980             :                     /*   energy normalize, for the specific shift and env,
     981             :                         otherwise it is not possible to compare among the shifted envelopes properly */
     982             : 
     983           0 :                     f_normcorr_fixenv[fix_ind][shift_ind] *= shift_en_norm_factors[fix_ind][shift_ind];
     984             :                 }
     985             :             }
     986             : 
     987             :             /* now actually pick the env[0,1,2,3] and env shift[0,1,2,3] option which maximizes the normcorr
     988             :                (minimizes shape mse as all fixed envelopes have the same gain quantizer) */
     989           0 :             p = &(f_normcorr_fixenv[0][0]);
     990           0 :             best_ind = 0;
     991           0 :             for (n = 1; n < (SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS); n++)
     992             :             {
     993           0 :                 if (p[n] > p[best_ind])
     994             :                 {
     995           0 :                     best_ind = n;
     996             :                 }
     997             :             }
     998           0 :             best_env_ind = best_ind / SNSLR_N_FIXENV_SHIFTS;
     999           0 :             best_shift_ind = best_ind - best_env_ind * SNSLR_N_FIXENV;
    1000           0 :             assert(best_env_ind >= 0 && best_env_ind < SNSLR_N_FIXENV);
    1001           0 :             assert(best_shift_ind >= 0 && best_shift_ind < SNSLR_N_FIXENV_SHIFTS);
    1002             :         }
    1003             :         /* o: best_shift_ind; o: best_env_ind */
    1004             : 
    1005           0 :         *fixShapeNb = best_env_ind; /* best normalized correlation out of the 4x4 = 16 envelope options */
    1006             :         /*best shift ind, later re-established/found via output vector y[2] */
    1007             : 
    1008             :         /* Fixed envelope "flat-ish" signband coding , including  sign coding  of shifted  block  */
    1009             :         /* submode idx 2,3,4     , "1"/env    1(s0)+ 2(shift)+ 11bits(s1..s11)   +   always a 3 bits gain  */
    1010             :         /* submode idx  5        , "1"/env    1(s0)+ 2(shift)+  9bits(s1..s9)    +   always a 3 bits gain  */
    1011             :         /*
    1012             :          2,  init_bell_12signs , [ 8,8,8, 7,7 ... ]
    1013             :          3,  decaying envelope 12 signs, [ 12,12,11,11, ... ]
    1014             :          4,  start_bell_12signs ,[ 7,7,8,8,8, 7,... ]
    1015             :          5,  early_bell_10signs,[ 6,6, 7,7,8,8,8,7,... ]
    1016             :        */
    1017             : 
    1018             :         {
    1019             :             /* construct the selected fix shape with its corresponding shift  */
    1020           0 :             memset(y[curr_cand], 0, sizeof(LC3_INT32)*M);    /* zero  output  */
    1021           0 :             env_ptr = env_ptrs[best_env_ind];
    1022             : 
    1023           0 :             Nsigns_fix = signs_fix[best_env_ind];
    1024             : 
    1025             :             /*  now assign unit amplitude and signs to each of the  fixed env  vector from x_in  in the band */
    1026           0 :             for (i = best_shift_ind; i < (Nsigns_fix + best_shift_ind); i++)
    1027             :             {
    1028           0 :                 y[curr_cand][SC + i] = env_ptr[i];
    1029             :             }
    1030           0 :             for (i = (SC + best_shift_ind); i < (SC + Nsigns_fix + best_shift_ind); i++)
    1031             :             {
    1032           0 :                 if (x_in[i] < 0)
    1033             :                 {
    1034           0 :                     y[curr_cand][i] *= -1;
    1035             :                 }
    1036             :             }
    1037           0 :             y[curr_cand][0] = 0;
    1038             :         }
    1039             :     }
    1040             : 
    1041           0 :     return;
    1042             : }
    1043             : 
    1044           0 : static void lrsns_quant_shape_gain(
    1045             :     LC3_FLOAT* t2rot, LC3_INT32 y[SNSLR_MAX_PVQ_SEARCH_CAND][M],
    1046             :     LC3_INT32* gain_idx, LC3_INT32 *shape_idx, LC3_FLOAT* y_norm, LC3_FLOAT* scq_gain, LC3_INT32 n_cand )
    1047             : {
    1048             :         LC3_INT32 gidx, sidx;
    1049             :     LC3_FLOAT min_mse, mse;
    1050             :  
    1051             :     LC3_INT32 i;
    1052             :     LC3_INT16  start_shape;
    1053             :     LC3_INT16  end_shape;
    1054             :     LC3_INT32 gain_levels[SNSLR_MAX_PVQ_SEARCH_CAND];   
    1055             :     LC3_FLOAT yCur[SNSLR_MAX_PVQ_SEARCH_CAND][M];
    1056             :     const LC3_FLOAT *lrsns_vq_gains[SNSLR_MAX_PVQ_SEARCH_CAND];
    1057             : 
    1058           0 :     gain_levels[0] = 4;     /* splitLF */
    1059           0 :     gain_levels[1] = 8;     /* full     */
    1060           0 :     gain_levels[2] = 8;     /* Fix-env{ 0,1,2,3,4}  */
    1061             : 
    1062           0 :     lrsns_vq_gains[0] = &(lrsns_gains_Q11[0][0]);
    1063           0 :     lrsns_vq_gains[1] = &(lrsns_gains_Q11[1][0]);
    1064           0 :     lrsns_vq_gains[2] = &(lrsns_gains_Q11[2][0]);
    1065             :    
    1066           0 :     min_mse = LC3_CONST_FLOATMAX;
    1067             :    
    1068             : 
    1069           0 :     *gain_idx = 0;
    1070           0 :     *shape_idx = 0;
    1071           0 :     start_shape = 0;
    1072           0 :     end_shape = n_cand;
    1073             : 
    1074           0 :     for (sidx = start_shape; sidx < end_shape; sidx++)
    1075             :     {
    1076             :         /*  Normalize the vectors */
    1077           0 :         for (i = 0; i < M; i++)
    1078             :         {
    1079           0 :             yCur[sidx][i] = (LC3_FLOAT)y[sidx][i];
    1080             :         }
    1081           0 :         pvq_enc_vec_normalize(yCur[sidx], M);
    1082             : 
    1083           0 :         for (gidx = 0; gidx < gain_levels[sidx]; gidx++)
    1084             :         {
    1085           0 :             mse = calc_mse(t2rot, yCur[sidx], lrsns_vq_gains[sidx][gidx], M);
    1086             : 
    1087           0 :             if (mse < min_mse)
    1088             :             {
    1089           0 :                 *gain_idx = gidx;
    1090           0 :                 *shape_idx = sidx;
    1091           0 :                 min_mse = mse;
    1092             :             }
    1093             :         }
    1094             : 
    1095             :     }
    1096             : 
    1097           0 :     for (i = 0; i < M; i++)
    1098             :     {
    1099           0 :         y_norm[i] = yCur[*shape_idx][i];
    1100             :     }
    1101             : 
    1102           0 :     *scq_gain = lrsns_vq_gains[*shape_idx][*gain_idx];
    1103             : 
    1104           0 :     return;
    1105             : }
    1106             : 
    1107           0 : LC3_INT32 MSEsearchGeneric(LC3_FLOAT *scf, const LC3_FLOAT *sns_CB, LC3_INT32 v_len, LC3_INT32 cb_len, LC3_FLOAT* min_mse)
    1108             : {
    1109             : 
    1110             :         LC3_FLOAT f_tmp, mse;
    1111             :     LC3_INT32 i, n, ind;
    1112             : 
    1113           0 :     ind = -1;
    1114             : 
    1115           0 :     *min_mse = (LC3_FLOAT)LC3_CONST_POW_2_100;
    1116           0 :     for (i = 0; i < cb_len; i++)
    1117             :     {
    1118           0 :         mse = 0;
    1119           0 :         for (n = 0; n < v_len; n++)
    1120             :         {
    1121           0 :             f_tmp = (scf[n] - sns_CB[i * v_len + n]);
    1122           0 :             mse += (f_tmp * f_tmp);
    1123             :         }
    1124             : 
    1125           0 :         if (mse < *min_mse)
    1126             :         {
    1127           0 :             *min_mse = mse;
    1128           0 :             ind = i;
    1129             :         }
    1130             :     }
    1131           0 :     assert(ind >= 0 && ind < cb_len);
    1132             : 
    1133           0 :     return ind;
    1134             : }
    1135             : 
    1136           0 : void snslr_st1B_vector_dec(LC3_INT16 idx, const LC3_INT16* LFCB, const LC3_INT16 *HFCB, const LC3_INT16* seg_cnt_cum, const LC3_INT16* idx12b_cb, LC3_FLOAT *st1B_vector)
    1137             : {
    1138             :     /* decompose the received 0 ... 169 index , into the correct intger  and float st1B vector  */
    1139             :     LC3_INT32 i, seg; /*counters*/
    1140             :     const LC3_INT16 *lf_cb, *hf_cb;
    1141             :     LC3_INT16 idx_12b, lf_sign, hf_sign;
    1142             :     LC3_INT16 idx_LF, idx_HF;
    1143             :     LC3_INT16 buf[M];
    1144             :     LC3_INT16 st1B_W16Q11[M];
    1145           0 :     LC3_FLOAT f_Q11_scale = (1.0 / 2048.0);
    1146             : 
    1147           0 :     assert(idx >= 0 && idx < 170);
    1148           0 :     seg = 0;
    1149           0 :     while (seg_cnt_cum[seg + 1] <= idx) {
    1150           0 :         seg++;
    1151             :     }
    1152           0 :     assert(seg >= 0 && seg < 4);
    1153             : 
    1154           0 :     idx_12b = idx12b_cb[idx];  /* from sequential value to a coded 12b index*/
    1155             : 
    1156           0 :     lf_sign = 1; /*   assume a 0 bit -> "+"  */
    1157           0 :     if ((0x0800 & idx_12b) != 0) {
    1158           0 :         lf_sign = -1; /*   assume a 1 bit -> " -"  */
    1159             :     }
    1160             : 
    1161           0 :     hf_sign = 1; /*   assume a 0 bit -> "+"  */
    1162           0 :     if ((0x0400 & idx_12b) != 0) {
    1163           0 :         hf_sign = -1; /*   assume a 1 bit -> "-"  */
    1164             :     }
    1165           0 :     idx_LF = (0x03e0 & idx_12b) >> 5;
    1166           0 :     idx_HF = (0x001f & idx_12b);
    1167             : 
    1168             :     /* extseg0  f,f  */
    1169           0 :     lf_cb = &(LFCB[idx_LF*(M / 2)]);
    1170           0 :     hf_cb = &(HFCB[idx_HF*(M / 2)]);
    1171           0 :     for (i = 0; i < (M / 2); i++)
    1172             :     {
    1173           0 :         st1B_W16Q11[i] = lf_sign * lf_cb[i];     /* imult()  or negate */
    1174           0 :         st1B_W16Q11[M / 2 + i] = hf_sign * hf_cb[i];
    1175             :     }
    1176           0 :     memcpy(buf, st1B_W16Q11, sizeof(*buf)*M); /* buffer cpy needed for reversal sections */
    1177             : 
    1178           0 :     if ((seg & 0x0002) != 0)
    1179             :     {   /* r,*  */     /* flip LF */
    1180           0 :         for (i = 0; i < (M / 2); i++)
    1181             :         {
    1182           0 :             st1B_W16Q11[i] = buf[(M / 2 - 1) - i];
    1183             :         }
    1184             :     }
    1185             : 
    1186           0 :     if ((seg & 0x0001) != 0)
    1187             :     {  /* *,r */ /* flip HF */
    1188           0 :         for (i = 0; i < (M / 2); i++)
    1189             :         {
    1190           0 :             st1B_W16Q11[(M / 2) + i] = buf[(M - 1) - i];
    1191             :         }
    1192             :     }
    1193             : 
    1194             :     /* Cfloat: convert  the 16bit integer  Q11 values from LFCB, and HFCB into  floats */
    1195           0 :     for (i = 0; i < M; i++)
    1196             :     {
    1197           0 :         st1B_vector[i] = ((LC3_FLOAT)st1B_W16Q11[i]) * f_Q11_scale;
    1198             :     }
    1199           0 : }
    1200             : 
    1201           0 : LC3_INT32 MSEsearchCbBIdxMap(const LC3_FLOAT *scf, const LC3_INT16 *LFCB, const LC3_INT16 *HFCB, const LC3_INT16 *seg_cnt_cum, const LC3_INT16* idx12b_cb, LC3_INT32 v_len, LC3_INT32 cb_len, LC3_FLOAT* min_mse)
    1202             : {
    1203             :     LC3_INT32  seg, i, j; /*counters */
    1204             :     LC3_INT32  L_mse;
    1205             :     LC3_INT16   scfLF_Q11[M], tmp_buf[M];
    1206             :     LC3_INT16*  scfHF_Q11;
    1207             :     const LC3_INT16 *lf_cb, *hf_cb;
    1208             :     LC3_INT16  err, best_ind, idx_12b, signbitLF, signbitHF, idx_LF, idx_HF;
    1209           0 :     LC3_INT32 L_mse_best = INT_MAX; /*a huge positive number */
    1210             :     
    1211             :     UNUSED(cb_len); /*cb_len only used for assert/verification */
    1212             : 
    1213           0 :     assert(v_len == M);
    1214             : 
    1215           0 :     scfHF_Q11 = (&scfLF_Q11[v_len / 2]); /* ptr init */
    1216             : 
    1217             :     /*set up   fwd,fwd search */
    1218           0 :     for (i = 0; i < M; i++)
    1219             :     {
    1220           0 :         tmp_buf[i] = (LC3_INT16)LC3_ROUND(scf[i] * 2048.0);  /*   scf  target  moved to  BASOP signed Word16Q11 integer domain */
    1221             :     }
    1222             : 
    1223           0 :     best_ind = -1;   /*for debug*/
    1224           0 :     for (seg = 0; seg < 4; seg++)
    1225             :     {
    1226           0 :         memcpy(scfLF_Q11, tmp_buf, M * sizeof(*scfLF_Q11));  /*  M * move16() */
    1227             :         /*seg==0: fwd, fwd */
    1228             :         /*seg==1: fwd, rev */
    1229             :         /*seg==2: fwd, fwd */
    1230             :         /*seg==3: rev, rev */
    1231             : 
    1232           0 :         if ((seg & 0x0002) != 0)
    1233             :         {   /* {r,*}  */     /* flip LF */
    1234           0 :             for (i = 0; i < (M / 2); i++)
    1235             :             {
    1236           0 :                 scfLF_Q11[i] = tmp_buf[(M / 2 - 1) - i];
    1237             :             }
    1238             :         }
    1239           0 :         if ((seg & 0x0001) != 0)
    1240             :         {  /* {*,r} */    /* flip HF */
    1241           0 :             for (i = 0; i < (M / 2); i++)
    1242             :             {
    1243           0 :                 scfLF_Q11[M / 2 + i] = tmp_buf[(M - 1) - i];
    1244             :             }
    1245             :         }
    1246             : 
    1247           0 :         for (i = seg_cnt_cum[seg]; i < seg_cnt_cum[seg + 1]; i++)
    1248             :         {
    1249           0 :             idx_12b = idx12b_cb[i];           /* indirect adressing lookup of  12b index pointing to LF and HF + individual sign swaps  */
    1250           0 :             signbitLF = (0x0800 & idx_12b);   /* b11 logical          */
    1251           0 :             signbitHF = (0x0400 & idx_12b);   /* b10 logical          */
    1252           0 :             idx_LF = (0x03e0 & idx_12b) >> 5; /* b9...b5              */
    1253           0 :             idx_HF = (0x001f & idx_12b);      /* b4..b0 lowest 5 bits */
    1254             : 
    1255           0 :             lf_cb = &(LFCB[idx_LF * M / 2]);    /* ptr init */
    1256           0 :             hf_cb = &(HFCB[idx_HF * M / 2]);    /* ptr init */
    1257             : 
    1258           0 :             L_mse = 0; /* move32() */ /* we accumulate energies on the positive  side   */
    1259           0 :             for (j = 0; j < (M / 2); j++)
    1260             :             {
    1261           0 :                 err = (scfLF_Q11[j] - lf_cb[j]);  /* a "+"sign,  LF err in Q11 */
    1262           0 :                 if (signbitLF != 0)
    1263             :                 {  /* negate LF*/
    1264           0 :                     err = (scfLF_Q11[j] + lf_cb[j]); /* "-""-"  --> "+"  LF err in Q11 ,single BASOP */
    1265             :                 }
    1266           0 :                 L_mse += (err * err);  /* simulate L_mac0 , accumulate towards max positive side */
    1267             : 
    1268           0 :                 err = (scfHF_Q11[j] - hf_cb[j]); /* a "+"sign, HF err in Q11 */
    1269           0 :                 if (signbitHF != 0)
    1270             :                 {   /* negate HF */
    1271           0 :                     err = (scfHF_Q11[j] + hf_cb[j]);  /* -- --> "+",  LF err in Q11 ,single BASOP */
    1272             :                 }
    1273           0 :                 L_mse += (err * err);   /*simulate L_mac0 */ /* now total error */
    1274             :             }
    1275             : 
    1276           0 :             L_mse_best = MIN(L_mse, L_mse_best); /* 1 cycle BASOP preupdate best  */
    1277           0 :             if ((L_mse - L_mse_best) == 0)
    1278             :             {
    1279           0 :                 best_ind = i;      /* update winner, single BASOP */
    1280             :             }
    1281             :         }
    1282             :     }/* segment seg */
    1283             : 
    1284           0 :     *min_mse = (LC3_FLOAT)((double)L_mse_best) / (2048.0*2048.0);  /* Word32 mse -> Cfloat output calculation  */
    1285             : 
    1286           0 :     assert(best_ind >= 0 && best_ind < cb_len);
    1287             : 
    1288           0 :     return (LC3_INT32)best_ind;
    1289             : }
    1290             : 
    1291           0 : void snslr_st1C_vector_dec(LC3_INT16 idx, const LC3_INT8* CBW8, LC3_INT16 scaleQ4, LC3_INT16 inv_scaleQ15, LC3_INT32 v_len, LC3_INT32 cb_len, LC3_FLOAT *st1C_vector)
    1292             : {
    1293             :     /* decompose the received 0... 169 index , into the correct (integer and)  float st1C vector  */
    1294             :     /* even in C-float the st1C coeffs  are put into a S16Q11 final integers domain  */
    1295             :     /* Enables BE compatibility between {BASOP, float, double}  arithmetic implmentations */
    1296             : 
    1297             : 
    1298             :     LC3_INT32 i; /*counter*/
    1299             :     const LC3_INT8 *cb;
    1300             :     LC3_INT32 L_tmp;
    1301             :     LC3_INT16  s_tmp, st1C_Q11[M];
    1302             : 
    1303             :     UNUSED(v_len);
    1304             :     UNUSED(cb_len);
    1305             :     UNUSED(inv_scaleQ15);  /* req for debugging only */
    1306           0 :     assert(idx >= 0 && idx < cb_len);
    1307           0 :     assert(v_len == M);
    1308             : 
    1309           0 :     cb = &(CBW8[idx*M]);                 /* pointer init */
    1310           0 :     for (i = 0; i < (M); i++)
    1311             :     {
    1312             :         /* BASOP: L_tmp = L_mult0((int16_t)cb[i], scaleQ4 ); */ /*S8Q7 * S15Q4 */ /*sign+7bit, sign+4 bits --> sign+11bit  .lt  sign+23 bits*/
    1313           0 :         L_tmp = ((int16_t)cb[i] /*S8Q7*/ * scaleQ4 /* S16Q4 */);  /* S32Q11 */
    1314             : 
    1315             :         /* Cfloat: convert to  Word16 Q11  integer  as  Word16 Q11 SNS domain bits, and then into floats */    
    1316           0 :         assert(L_tmp >= -32768L && L_tmp <= 32767L); /* INT16 domain check*/
    1317           0 :         s_tmp = (int16_t)(L_tmp);
    1318           0 :         st1C_Q11[i] = s_tmp;
    1319             :     }
    1320             : 
    1321             :     /* Cfloat: convert  the Word16 Q11 SNS domain bits, and then into floats */
    1322           0 :     for (i = 0; i < M; i++)
    1323             :     {
    1324           0 :         st1C_vector[i] = ((LC3_FLOAT)st1C_Q11[i])*(1.0 / 2048.0);
    1325             :     }
    1326           0 : }
    1327             : 
    1328           0 : LC3_INT32 MSEsearchGenericScaledW8(LC3_FLOAT *scf, const LC3_INT8 *sns_CBW8, LC3_INT16 scaleQ4, LC3_INT16 inv_scaleQ15, LC3_INT32 v_len, LC3_INT32 cb_len, LC3_FLOAT* min_mse)
    1329             : {
    1330             :     /*   scf float input values are  typically in the range  +12.0  to -12.0.
    1331             :         ROM table stored in WORD8 [+127,-128], format  corresponding to   ]+1.0  .. -1.0 ]
    1332             :         inv_scaleQ15, [downscaling  value in Q15]  applied before search
    1333             :         scaleQ12   upscaling value quantized in Q12,  used in the mse calulation and in the common float and BASOP  synthesis routines
    1334             : 
    1335             :         L_mse evaluated here in a positive integer Word32 domain to match   BASOP
    1336             : 
    1337             :             Fuzzing/saturation considerations
    1338             :             max M==16 values (4 bits) yields  16*(256*256)=>2^(4+8+8)=2^20  .lt  2^31,
    1339             :             IntegerWord32  is a safe search domain
    1340             : 
    1341             :            a WC input analysis  would be when half  target  entries are  "-256" and half +255
    1342             : 
    1343             :      */
    1344             :         LC3_INT32 i, n, best_ind; /*counters*/
    1345             :     LC3_INT32 L_mse, L_mse_best;
    1346             :     LC3_INT16  targetW16[M], err;
    1347             :     LC3_FLOAT  f_tmp, f_scale;
    1348             :     const LC3_INT8  * cbW8;
    1349             : 
    1350           0 :     f_scale = ((LC3_FLOAT)inv_scaleQ15) / 32768.0;
    1351           0 :     for (i = 0; i < v_len; i++) {
    1352           0 :         f_tmp = (scf[i] * f_scale);
    1353           0 :         assert(f_tmp >= -4.0 && f_tmp < 4.0);    /* check for about 2  bit  integer margin in the target */
    1354           0 :         targetW16[i] = (LC3_INT16)LC3_FLOOR(f_tmp*128.0);    /*cast to INT16   W8Q7   */
    1355             :     };
    1356             :     /* in BASOP  1/32768 and  *128 is handled by one single shift) */
    1357             : 
    1358           0 :     L_mse_best = INT_MAX;  /* largest possible positive number in INT32 */
    1359           0 :     best_ind = -1;
    1360             : 
    1361           0 :     for (i = 0; i < cb_len; i++) {
    1362           0 :         L_mse = (0L);   /* move32() */
    1363             :         /* we accumulate energies on the positive side Word8 vectors do not have any issue with  saturation  (16*256*256) ==2^(4+8+8)  .lt 2^31  MAX_INT */
    1364             : 
    1365           0 :         cbW8 = &sns_CBW8[i*v_len];  /*ptr init */
    1366           0 :         for (n = 0; n < v_len; n++)
    1367             :         {
    1368           0 :             err = (targetW16[n] - ((LC3_INT16)cbW8[n]));     /* cast from Word8 to Word16 is not for free,
    1369             :                                                                  actual cost in a Word16 architecture is a  L_and(x,0x00ffff)  or  a shr(x,8) */
    1370             : 
    1371           0 :             L_mse += (err*err);    /* L_mse = L_mac0(L_mse, err, err); */
    1372             :         }
    1373             : 
    1374           0 :         if ((L_mse - L_mse_best) <= 0)
    1375             :         {  /* a value closer to 0  */
    1376           0 :             best_ind = i;     /* single BASOP for best idx update */
    1377             :         }
    1378           0 :         L_mse_best = MIN(L_mse, L_mse_best); /* always update best MSE using L_min() in the idx loop, reduces WC WMOPS  */
    1379             :     }
    1380           0 :     assert(best_ind >= 0 && best_ind < cb_len);
    1381             : 
    1382             : 
    1383           0 :     *min_mse = (LC3_FLOAT)((double)(L_mse_best)) / (128.0*128.0);  /* Word32 L_mse in Q7   ->  Cfloat output calculation  */
    1384             : 
    1385           0 :     f_tmp = (((double)scaleQ4) / 16.0);
    1386           0 :     *min_mse *= (f_tmp*f_tmp);              /* make gain scaling a part of  Word32 L_mse  ->  Cfloat output calculation  */
    1387             : 
    1388           0 :     return best_ind;
    1389             : }
    1390             : 
    1391             : /*   LRSNS stage 1 functionality */
    1392           0 : LC3_INT32 snsQuantScfEncLRSt1ABC(LC3_FLOAT* env, LC3_INT32* L_index, LC3_FLOAT *min_mse_saveBCA_ptr,
    1393             :     LC3_INT32* ind_saveB_ptr, LC3_FLOAT* st1_vectors, LC3_INT32 pitch_rx, LC3_INT32 ltpf_rx)
    1394             : {
    1395             : 
    1396             :     LC3_INT32 i;
    1397             :     LC3_FLOAT *st1_vector, *st1_vectorA, *st1_vectorB, *st1_vectorC, target[M];
    1398             :     LC3_FLOAT  st1_vectorBC[M];
    1399             :     LC3_FLOAT  min_mse_saveA, min_mse_saveB, min_mse_saveC, min_mse_saveBC;
    1400             :     LC3_INT32 ind_saveA, ind_saveC;
    1401             :     const LC3_FLOAT *cb;
    1402             :     LC3_INT16  stage1_mode; /*0=A, 1=B, 2=C. -1==fail*/
    1403             :     LC3_FLOAT min_mse_saveB_fxlike;
    1404           0 :     LC3_INT32 ind_saveB_fxlike = -1;
    1405             :     LC3_FLOAT st1_vectorB_idx[M];
    1406             :     LC3_FLOAT st1C_lim;
    1407             :     LC3_FLOAT f_mse_tmp;
    1408           0 :     LC3_INT32 ind_saveC_ScaledW8 = -1;
    1409             :     LC3_FLOAT min_mse_saveC_ScaledW8;
    1410             : 
    1411             : #ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY
    1412             :     UNUSED(ltpf_rx);
    1413             : #endif 
    1414             : 
    1415           0 :     stage1_mode = -1;         /* output mode */
    1416             : 
    1417           0 :     st1_vectorA = &(st1_vectors[0]);
    1418           0 :     st1_vectorB = &(st1_vectors[1 * M]);
    1419           0 :     st1_vectorC = &(st1_vectors[2 * M]);
    1420           0 :     st1_vector = &(st1_vectors[3 * M]);
    1421             : 
    1422             :     /* snslr stage1  B(170) and C(170), A(2)  evaluation */
    1423             :     /*        b0-b8     b9
    1424             :        segm ,  idx9b , stop bit,  comment use
    1425             :        -----+--------+---------
    1426             :         A   | 510,511| n/a,   2 entries,  9 bit total
    1427             :       ------+--------+--------
    1428             :       ------+--------+--------+-------
    1429             :         B   | 0--169 |   1  ,  170 entries,  10 bit total
    1430             :       ------+--------+--------
    1431             :         C   | 170-339|   1  , 170 entries,   10 bit total
    1432             :       ------+--------+--------+------------
    1433             :       ------+--------+--------+------------
    1434             :         B*  | 340-509|   1     --> aux=1, 170, 3b+17b for stage2 'LR_full/LR_fix', 30 bit total
    1435             :       ------+--------+--------+-------
    1436             :         B*  | 0--169 |   0  ,  --> aux=0, 170,  2b+17b for stage2 'LR_SplitLF' ,  29 bit total
    1437             :       ------+--------+--------+-------
    1438             :         B*  | 170-339|   0  ,  --> aux=1, 170,  2b+17b for stage2 'LR_SplitLF',29 bit total
    1439             :       ------+--------+--------+-------
    1440             :         B*  | 340-509|   0     --> aux=0, 170, 3b+17b for stage2 'LR_full/LR_fix', 30 bit total
    1441             :       ------+--------+--------+-------
    1442             :      */
    1443             : 
    1444             :     {   /* stage 1 section A(2),  a very small 2xM entry  cb  */
    1445           0 :         cb = lrsns_st1A_topTab_1bitNoDC;
    1446             : 
    1447           0 :         memcpy(target, env, sizeof(LC3_FLOAT)*M);
    1448             : 
    1449           0 :         ind_saveA = MSEsearchGeneric(target, cb, M, 2, &min_mse_saveA);
    1450           0 :         memcpy(st1_vectorA, &(cb[ind_saveA*M]), sizeof(LC3_FLOAT)*M);
    1451             :     }
    1452             : 
    1453           0 :     min_mse_saveB = LC3_CONST_FLOATMAX; /*safety init*/
    1454             : 
    1455             :     {  /* stage1 section B(170) MSE analysis */
    1456           0 :         memcpy(target, env, sizeof(LC3_FLOAT)*M);
    1457           0 :         *ind_saveB_ptr = -1;
    1458             : 
    1459           0 :         ind_saveB_fxlike = MSEsearchCbBIdxMap(target, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11,
    1460             :             lrsns_st1B_merged170orderSortedSegmCum, lrsns_st1B_merged170orderSort12bitIdx, M, 170, &min_mse_saveB_fxlike); /*st1B LF,HF idx lookup search 170 ,170 Word16s ,  0.34kB ROM */
    1461           0 :         snslr_st1B_vector_dec(ind_saveB_fxlike, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, lrsns_st1B_merged170orderSortedSegmCum, lrsns_st1B_merged170orderSort12bitIdx,
    1462             :             st1_vectorB_idx);
    1463             : 
    1464           0 :         *ind_saveB_ptr = ind_saveB_fxlike;
    1465           0 :         min_mse_saveB = min_mse_saveB_fxlike;
    1466           0 :         memcpy(st1_vectorB, st1_vectorB_idx, sizeof(LC3_FLOAT)*M); /*use low ROM version */
    1467             : 
    1468             :         {
    1469             :             /* remove DC that can remain in the LF,HF index  stored stage cb  B structure  */
    1470             :             /* a very slight offline decrease in perf 0.001 dB in AvSD when searching with DC above,
    1471             :                but it allows much better stage1 ROM-reuse performance
    1472             :             */
    1473           0 :             LC3_FLOAT dc = snslr_remove_st1_DC_fQ11(st1_vectorB, M); /* inplace removal of dc in st1_vectorB */
    1474             :             LC3_FLOAT f_tmp;
    1475           0 :             assert(min_mse_saveB >= 0.0);
    1476             : 
    1477           0 :             f_tmp = min_mse_saveB - M * (dc*dc);
    1478           0 :             min_mse_saveB = MAX(f_tmp, 0.0); /* truncation in DC removal can cause negative MSE, limit to 0 */
    1479             :         }
    1480             :     } /* end of stage 1 section B , search */
    1481             : 
    1482             : 
    1483             : 
    1484           0 :     st1C_lim = 3.97; /*  corresponding  to an  SD limit of  = 1.5  */
    1485           0 :     f_mse_tmp = MIN(min_mse_saveA*0.875, min_mse_saveB);
    1486             :     
    1487           0 :     if (f_mse_tmp < st1C_lim)  /*  skip C search if SD is already low enough < 1.5dB)  to save average WMOPS */
    1488             : 
    1489             :     {
    1490           0 :         min_mse_saveC = 2 * 5.579999923706055;  /*disable C selection in consecutive  logic */
    1491           0 :         ind_saveC = 0;    /* a valid index that will not be used */
    1492             :     }
    1493             :     else
    1494             :     {   /* search stage1 C */
    1495             :         /* search another set (pitch dependent section C) of 170 mean residual vectors  */
    1496             :         /* pitch_info rx selects a  mean   and then employ a trained  residual 1x170W8 based harmonic outlier table */
    1497             : 
    1498             :             /* float means are based on  Word16 S16Q11 values,  so that BASOP and float  always may become BE in synthesis*/
    1499           0 :         int16_t CBCmeanp_ind = pitch_rx; /* 0 or 1 */
    1500             : 
    1501             : #ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY 
    1502           0 :         if (pitch_rx != 0 && ltpf_rx != 0)
    1503             :         {
    1504           0 :             CBCmeanp_ind = CBCmeanp_ind + 1;  /*LTPF_rx is also active */
    1505             :         }
    1506             : #else 
    1507             :     /* CbC only dependent on LTP transmission on/off */
    1508             : #endif 
    1509             : 
    1510           0 :         for (i = 0; i < M; i++)
    1511             :         {
    1512           0 :             target[i] = env[i] - lrsns_st1CTrainedMapMeans[CBCmeanp_ind][i];
    1513             :         }
    1514             : 
    1515           0 :         ind_saveC_ScaledW8 = MSEsearchGenericScaledW8(target, lrsns_st1C_Both_Word8,
    1516           0 :             lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1],
    1517             :             M, 170, &(min_mse_saveC_ScaledW8));
    1518             : 
    1519           0 :         snslr_st1C_vector_dec(ind_saveC_ScaledW8, lrsns_st1C_Both_Word8, lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1],
    1520             :             M, 170, st1_vectorC);
    1521             :         /* integer based decoder side synthesis of scaled W8 table for best possible interop */
    1522             : 
    1523           0 :         ind_saveC = ind_saveC_ScaledW8;
    1524           0 :         min_mse_saveC = min_mse_saveC_ScaledW8;
    1525             : 
    1526           0 :         for (i = 0; i < M; i++) {
    1527           0 :             st1_vectorC[i] += lrsns_st1CTrainedMapMeans[CBCmeanp_ind][i]; /*  Q11 means*/
    1528             :         }
    1529             :     }
    1530             : 
    1531             :     /* BC stage1    comparison   */
    1532             :     /* initially assume B as stage 1 winner */
    1533           0 :     min_mse_saveBC = min_mse_saveB;
    1534           0 :     L_index[0] = *ind_saveB_ptr;  /* 0...169   */
    1535             : 
    1536           0 :     memcpy(st1_vector, st1_vectorB, sizeof(LC3_FLOAT)*M);   /* stage 1 segmentB result without DC  copied as base for st2 */
    1537             : 
    1538             : 
    1539           0 :     if (min_mse_saveC < min_mse_saveBC)
    1540             :     {  /* C better than B */
    1541           0 :         min_mse_saveBC = min_mse_saveC;
    1542           0 :         L_index[0] = 170 + ind_saveC;  /* [2x 170] (9+1)b             [170-339] ,  ">=170"  is a signal to multiplexor  */
    1543           0 :         memcpy(st1_vector, st1_vectorC, sizeof(LC3_FLOAT)*M);
    1544             :     }
    1545             : 
    1546           0 :     memcpy(st1_vectorBC, st1_vector, sizeof(LC3_FLOAT)*M);
    1547           0 :     L_index[1] = -10;
    1548           0 :     assert(min_mse_saveBC >= 0.0);
    1549             : 
    1550             :     /* (9(A)<->10(BC) bit weighted comparison   */
    1551           0 :     *min_mse_saveBCA_ptr = min_mse_saveBC;
    1552           0 :     if (min_mse_saveA*0.875 < min_mse_saveBC)  /* a minor favouring of the 9b vector results  sqrt(0.875)  =>  approx  0.6dB level domain  */
    1553             :     {
    1554           0 :         L_index[0] = 510 + ind_saveA;  /*   only [510, 511]  possible */
    1555           0 :         L_index[1] = -9;
    1556             : 
    1557           0 :         cb = lrsns_st1A_topTab_1bitNoDC;
    1558           0 :         memcpy(st1_vectorA, &(cb[ind_saveA*M]), sizeof(LC3_FLOAT)*M);
    1559           0 :         memcpy(st1_vector, st1_vectorA, sizeof(LC3_FLOAT)*M);
    1560             : 
    1561           0 :         *min_mse_saveBCA_ptr = min_mse_saveA * 0.875;;
    1562             :     }
    1563             : 
    1564             :     /* index0_saveBCA = index[0];*/    /*  0 ... 511 */
    1565             :     /* index1_saveBCA = index[1];*/    /* -9 or -10 */
    1566             : 
    1567           0 :     stage1_mode = 2; /* C , assumed */
    1568           0 :     if (L_index[0] >= 510)
    1569             :     {
    1570           0 :         stage1_mode = 0; /* A */
    1571             :     }
    1572           0 :     if (L_index[0] <= 169) {
    1573           0 :         stage1_mode = 1; /* B */
    1574             :     }
    1575             : 
    1576           0 :     return stage1_mode; /* return best  stage1  mode */
    1577             : }
    1578             : 
    1579           0 : LC3_INT16 snsQuantScfEncLR(LC3_FLOAT* env, LC3_INT32* L_index, LC3_FLOAT* envq, Dct2 dct2structSNS, LC3_INT32 pitch_rx, LC3_INT32 ltpf_rx)
    1580             : {
    1581             :     LC3_INT32 i;
    1582             :     LC3_FLOAT min_mse_saveBCA;
    1583             :     LC3_INT32 ind_saveB;
    1584             :     LC3_INT16 st1_mode;
    1585             : 
    1586             :     LC3_FLOAT stage2_en1_norm_sub[M];
    1587             :     LC3_FLOAT st1_vectors[(SNSLR_MAX_PVQ_SEARCH_CAND+1)*M], *st1_vectorA, *st1_vectorB, *st1_vectorC, *st1_vector;
    1588             :     LC3_FLOAT pvq_target_pre[M];
    1589             :     LC3_FLOAT pvq_target[M];
    1590             : #ifdef LRSNS_WMC_FIX
    1591             :     LC3_INT32 y[SNSLR_MAX_PVQ_SEARCH_CAND][M];  /* o:  [3]*[0...M-1] */
    1592             : #else
    1593             :     LC3_INT32 y_tmp[3*M];
    1594             : #endif 
    1595             :     LC3_FLOAT stage2_en1_norm_pre_sub[M];
    1596             :     LC3_FLOAT envq_st1B_st2[M];
    1597             :     LC3_FLOAT mse_st1B_st2;
    1598             :     LC3_FLOAT mse_st1B_st2_dct_domain;
    1599             :     LC3_INT32 gain_idx, shape;
    1600             :     LC3_FLOAT scfq_gain;
    1601             :     LC3_INT32 fix_shape_idx;
    1602             :     LC3_INT16 envelope_bits; /* function output */  
    1603             :     LC3_INT32 fix_shift_ind, fix_shift_bits, fix_end_sign, LS_tmp_ind;
    1604             :     LC3_INT32 shape_local;
    1605             : 
    1606             :     UNUSED(fix_shift_bits); /* used for assert */
    1607             : 
    1608             : #ifndef LRSNS_WMC_FIX
    1609             :     LC3_INT32(*y)[M];   /* C-construct to allow matrix adressing into a scratch area  */
    1610             : #endif 
    1611           0 :     envelope_bits = -1;   /* output : 9,10, 29/30 */
    1612           0 :     gain_idx = 1;         /* stage 2 gain idx range 0 ... 7 , or 0 ... 3 */
    1613           0 :     shape = -1;           /* stage 2 shape range    0 ... 5  */
    1614             : 
    1615           0 :     st1_vectorA = &(st1_vectors[0]);
    1616           0 :     st1_vectorB = &(st1_vectors[1 * M]);
    1617           0 :     st1_vectorC = &(st1_vectors[2 * M]);
    1618           0 :     st1_vector = &(st1_vectors[3 * M]);
    1619             : 
    1620             : 
    1621             : #ifndef LRSNS_WMC_FIX
    1622             :     y = (LC3_INT32(*)[M]) &(y_tmp[0]); /*  y is an NxM Matrix Ptr */
    1623             : #endif 
    1624             :     { /*  stage1 A,B,C   */
    1625             : 
    1626           0 :         ind_saveB = -1;
    1627           0 :         min_mse_saveBCA = M * 32.0*32.0;
    1628           0 :         st1_mode = snsQuantScfEncLRSt1ABC(
    1629             :             env, L_index, &min_mse_saveBCA, &ind_saveB, st1_vectors, pitch_rx, ltpf_rx);
    1630             : 
    1631           0 :         if (ind_saveB < 0 || ind_saveB > 169)
    1632             :         {
    1633           0 :             assert(ind_saveB >= 0 && ind_saveB <= 169); /* idxB always needed in case stage2 is  activated  */
    1634             :         }
    1635             : 
    1636           0 :         if (st1_mode == 0)
    1637             :         {
    1638           0 :             envelope_bits = 9;
    1639           0 :             memcpy(st1_vector, st1_vectorA, sizeof(LC3_FLOAT)*M);
    1640           0 :             assert(L_index[0] >= 510 && L_index[0] <= 511);
    1641             :         }
    1642             : 
    1643           0 :         if (st1_mode == 1)
    1644             :         {
    1645           0 :             envelope_bits = 10;
    1646           0 :             memcpy(st1_vector, st1_vectorB, sizeof(LC3_FLOAT)*M);
    1647           0 :             assert(L_index[0] >= 0 && L_index[0] <= 169);
    1648             :         }
    1649             : 
    1650           0 :         if (st1_mode == 2)
    1651             :         {
    1652           0 :             envelope_bits = 10;
    1653           0 :             memcpy(st1_vector, st1_vectorC, sizeof(LC3_FLOAT)*M);
    1654           0 :             assert(L_index[0] >= 170 && L_index[0] < 2 * 170);
    1655             :         }
    1656             : 
    1657           0 :         L_index[1] = -910; /* aux */
    1658           0 :         L_index[2] = -envelope_bits; /* signal shape  */
    1659             : 
    1660             :     }
    1661             :     /* only run stage 2 when necessary  */
    1662             : 
    1663             :     {  
    1664             :         LC3_FLOAT  mse_lim_smooth;
    1665           0 :         mse_lim_smooth = (5.41);   /*    1.75 SD */
    1666             : 
    1667           0 :         mse_st1B_st2 = 2.0* min_mse_saveBCA + 1.0;   /*  indicate that st1B+st2 is not used by setting a higher MSE than st1BCA  */
    1668             : 
    1669           0 :         if (min_mse_saveBCA > mse_lim_smooth)
    1670             :         {
    1671             :             /* run  and evaluate STAGE 2,  using vector B as  stage 1 */
    1672           0 :             for (i = 0; i < M; i++)
    1673             :             {
    1674           0 :                 pvq_target_pre[i] = env[i] - st1_vectorB[i];
    1675             :             }
    1676             : 
    1677           0 :             dct2_apply(&dct2structSNS, pvq_target_pre, pvq_target);
    1678             : 
    1679           0 :             pvq_target[0] = 0.0;  /* DC always zero  */
    1680             : 
    1681           0 :             fix_shape_idx = -1;
    1682           0 :             pvq_fess_enc_search(pvq_target, y, &fix_shape_idx);  /* best shape search  splitLF, full, best_fess_env      */
    1683             : 
    1684           0 :             assert(y[0][0] == 0 && y[1][0] == 0 && y[2][0] == 0);
    1685           0 :             lrsns_quant_shape_gain(pvq_target, y, &gain_idx, &shape, stage2_en1_norm_pre_sub, &scfq_gain, 2 + 1);
    1686             : 
    1687           0 :             if (shape == 2)
    1688             :             {
    1689           0 :                 shape = 2 + fix_shape_idx;
    1690             :             }
    1691             : 
    1692             :             /*   check if MSE after stage 2 is better already here in dct domain, avoid unnecessary IDCT-II calls  */
    1693           0 :             envq_st1B_st2[0] = 0;
    1694           0 :             for (i = 1; i < M; i++)
    1695             :             {
    1696           0 :                 envq_st1B_st2[i] = (stage2_en1_norm_pre_sub[i] * scfq_gain);
    1697             :             }
    1698             : 
    1699           0 :             mse_st1B_st2_dct_domain = calc_mse(pvq_target, envq_st1B_st2, 1.0f, M);
    1700             : 
    1701           0 :             if (min_mse_saveBCA < mse_st1B_st2_dct_domain)
    1702             :             {
    1703             :                 /* no need for an IDCT as stage2 was worse than only stage1  */
    1704           0 :                 mse_st1B_st2 = mse_st1B_st2_dct_domain;
    1705             :             }
    1706             :             else
    1707             :             {
    1708             :                 /* Inverse transform  */
    1709           0 :                 idct_II(stage2_en1_norm_pre_sub, stage2_en1_norm_sub, M);
    1710             : 
    1711           0 :                 for (i = 0; i < M; i++)
    1712             :                 {
    1713           0 :                     envq_st1B_st2[i] = st1_vectorB[i] + (stage2_en1_norm_sub[i] * scfq_gain);
    1714             :                 }
    1715           0 :                 mse_st1B_st2 = calc_mse(env, envq_st1B_st2, 1.0f, M);
    1716             :             }
    1717             :         }
    1718             :     } /*end of stage2 search */
    1719             : 
    1720             :     /* post-evaluate if one of (st1B, st1C, st1A) was actually better than st1B+stage2 */
    1721           0 :     if (mse_st1B_st2 < min_mse_saveBCA)
    1722             :     {  /*   use stage1B + st2  at  29b/30b bits total */
    1723           0 :         L_index[0] = ind_saveB;
    1724           0 :         L_index[1] = 2930;         /* later stage2    aux  value  LS_splitLF or LS_full or s0,   put here  as a 0 or 1 */
    1725           0 :         L_index[2] = shape;        /* 0=splitLF, 1=full,  ( 2=fixEnv0, 3=fixEnv1, 4: fixEnv2, 5: fixEnv3 )  */
    1726           0 :         L_index[3] = gain_idx;     /*  gain_idx  with a shape dependent number of  levels  (4  or 8  levels  ) */
    1727             : 
    1728           0 :         memcpy(envq, envq_st1B_st2, sizeof(LC3_FLOAT)*M);
    1729           0 :         memcpy(st1_vector, st1_vectorB, sizeof(LC3_FLOAT)*M); /* save final  st1B result,  st1 in combination with stage 2, for verification   */
    1730           0 :         envelope_bits = 29;  /* 'LR_splitLF' */
    1731           0 :         if (shape > 0)
    1732             :         {
    1733           0 :             envelope_bits += 1; /*30 'LR_full/LR_fixenv' */
    1734             :         }
    1735             : 
    1736             :         {
    1737             :             /* DBG check values  */
    1738           0 :             assert(shape >= 0);
    1739           0 :             assert(envelope_bits >= 29);
    1740           0 :             assert(L_index[0] <= 170);  /*only B allowed */
    1741           0 :             assert(L_index[1] >= 0);
    1742             : 
    1743           0 :             assert(gain_idx >= 0); /*index*/
    1744           0 :             assert(scfq_gain > 0.0); /* value */
    1745             :         }
    1746             :     }
    1747             :     else
    1748             :     {   /* stick to stage1(best of BCA)   at  9 or 10  bits */
    1749           0 :         assert(L_index[1] < 0 && L_index[0] >= 0 && L_index[0] < 512);
    1750           0 :         envelope_bits = ((L_index[0] >= 510) ? 9 : 10);
    1751           0 :         shape = -envelope_bits; /* signal an invalid shape number to enc-entropy */
    1752             : 
    1753           0 :         memcpy(envq, st1_vector, M * sizeof(LC3_FLOAT)); /* output */
    1754           0 :         memset(stage2_en1_norm_sub, 0, M * sizeof(*stage2_en1_norm_sub));
    1755           0 :         scfq_gain = 0.0f;
    1756           0 :         gain_idx = -1;   /* L_index sentinel */
    1757           0 :         L_index[2] = shape;
    1758             :     }
    1759             : 
    1760             :     /******************************************************************/
    1761             :     /*  signal to enc_entropy for LRSNS semi-fractional multiplexing  */
    1762             :     /******************************************************************/
    1763             :     /* integer multiplexing   29/30 bit modes into intermediate  unmuxed integer indeces  0...7  */
    1764             :     /* a bit of fractional multiplexing  for these  indeces  0...7  is done later,  in function enc_entropy()  */
    1765           0 :     if (shape >= 0)
    1766             :     {  /* stage 2 multiplexing manipulations */
    1767             :     
    1768             : 
    1769           0 :         if (shape == 0)
    1770             :         {   /*  splitLF   */
    1771           0 :             LC3_INT32  n5k = 0;
    1772           0 :             for (i = 0; i < 5; i++)
    1773             :             {
    1774           0 :                 n5k += abs(y[shape][1 + i]);
    1775             :             }
    1776             : 
    1777           0 :             if (n5k == 6)
    1778             :             {
    1779           0 :                 MPVQ_enum(5, &(y[shape][1]), &(L_index[4]), &LS_tmp_ind); /*  P(N=5,K=6) (10)=10 bit L_index    */
    1780           0 :                 L_index[1] = LS_tmp_ind;     /* set the aux bit for the  splitLF path, plant the first LS as aux */
    1781           0 :                 assert((L_index[4] >= 0) && (L_index[4] < (SNSLR_NPVQ_L5K6 >> 1)));
    1782             : 
    1783           0 :                 MPVQ_enum(8, &(y[shape][1 + 5]), &(L_index[5]), &LS_tmp_ind);
    1784           0 :                 L_index[5] = (L_index[5] << 1) + LS_tmp_ind; /* A full PVQ 7 bit index for the  P(N=8,K=2) B config*/
    1785           0 :                 assert((L_index[5] >= 0) && (L_index[5] < (1 << 7)));
    1786             :             }
    1787             :             else
    1788             :             {
    1789           0 :                 MPVQ_enum(5, &(y[shape][1]), &(L_index[4]), &LS_tmp_ind);  /*  PVQ(N=5,K=8) (12.x   in total, i.e.  LS+ 11.x )    */
    1790           0 :                 L_index[1] = LS_tmp_ind;      /* aux bit for the  splitLF path  ,  plant the first LS as aux  */
    1791           0 :                 assert((L_index[4] >= 0) && (L_index[4] < (SNSLR_NPVQ_L5K8 >> 1)));
    1792           0 :                 L_index[5] = -8; /* signal LF PVQ(5,8)  and  zeroed HF(10,0) */
    1793             :             }
    1794             :         }
    1795           0 :         if (shape == 1)
    1796             :         {   /*  full (15,5) ,  LS kept separated  */
    1797             :             /* indicate a stage2 path in the 9 bit stage1 index   */
    1798           0 :             MPVQ_enum(15, &(y[shape][1]), &(L_index[4]), &LS_tmp_ind);   /*  mPVQ 16.66 bits in index[4], and LS 1 bit in index[1] */
    1799           0 :             L_index[1] = LS_tmp_ind;   /*aux bit location,  0 or 1 , we plant the LS there  */
    1800           0 :             assert((L_index[4] >= 0) && (L_index[4] < (SNSLR_NPVQ_L15K5 >> 1)));
    1801             :         }
    1802           0 :         if (shape >= 2 && shape <= 5)
    1803             :         {
    1804             :             /* fixEnv0, fixEnv1, fixEnv2, fixEnv3 */
    1805             :             /* send the fixed env subshape mode to enc_entropy  */
    1806           0 :             L_index[4] = (shape - 2); /* env shape, 0-->"1" , 1--> "env1"  */   /* L_index[2] has original shape 0...5 */
    1807             : 
    1808           0 :             shape_local = 2;     /*a single y shape vector for all fixed env */
    1809             : 
    1810           0 :             fix_shift_ind = 0;
    1811           0 :             while (y[shape_local][1 + fix_shift_ind] == 0)
    1812             :             {
    1813           0 :                 fix_shift_ind += 1;
    1814             :             }
    1815           0 :             fix_shift_bits = 2;
    1816             : 
    1817           0 :             assert(fix_shift_ind < (1 << fix_shift_bits));
    1818             : 
    1819           0 :             L_index[1] = (y[shape_local][1 + fix_shift_ind /* + 0*/] < 0);     /* aux_bit : 0 (or 1)    , will indicate the  s0 sign in the FESS fix shape */
    1820             : 
    1821             : 
    1822           0 :             fix_end_sign = 12;
    1823           0 :             if (shape == 5) 
    1824             :             {
    1825           0 :                 assert(L_index[4] == 3);
    1826           0 :                 fix_end_sign = (fix_end_sign - 2);  /* shape 4 has 2 bits shift and a total of 10 signs =2^10*2^2 = 2^12 = 4096 */
    1827             :             }
    1828             : 
    1829           0 :             L_index[5] = fix_shift_ind; /* the two shift bits will be pushed up to b11,b12 , for 11 signs s1-s11  */
    1830             : 
    1831           0 :             for (int sign_ind = 1; sign_ind < fix_end_sign; sign_ind++)  /* push the remaining  sequential signs s1-s11(or s1-s9),  into a single idx */
    1832             :             {  /* s1 is in the MSB, and s11 is in the lsb*/
    1833           0 :                 L_index[5] = L_index[5] << 1;
    1834           0 :                 if (y[shape_local][1 + fix_shift_ind + sign_ind] < 0) /*"1" means negative, "0" means positive */
    1835             :                 {
    1836           0 :                     L_index[5] += 1;
    1837             :                 }
    1838             :             }
    1839           0 :             assert(L_index[5] >= 0 && L_index[5] < (1 << (fix_shift_bits + (fix_end_sign - 1))));
    1840             :         }
    1841             :     } /* end of stage2 premultiplexing  */
    1842             : 
    1843             :     {
    1844           0 :         assert(envelope_bits == 9 || envelope_bits == 10 || envelope_bits == 29 || envelope_bits == 30);
    1845             :     }
    1846             : 
    1847           0 :     return envelope_bits;
    1848             : }
    1849             : 
    1850           0 : void FESSdeenum(LC3_UINT8 dim_in,    /* i :  dimension of vec_out     */
    1851             :     LC3_UINT8 n_env,     /* i :  number of envelopes    */
    1852             :     LC3_UINT8 n_shift,   /* i :  number shifts        */
    1853             :     LC3_UINT8 n_signs,   /* i :  number signs          */
    1854             :     LC3_INT32 env_ind,   /*  i:indx */
    1855             :     LC3_INT32 shift_ind, /*  i:indx */
    1856             :     LC3_INT32 sign_ind,  /*  i:indx */
    1857             :     LC3_INT32* vec_out /* o :  FESS  integer  pulse train  */)
    1858             : {
    1859             : 
    1860             :         LC3_INT32 i;
    1861             :     LC3_INT32  sign_val;
    1862             : 
    1863           0 :     assert(n_env >= 1 && n_env <= 4);
    1864           0 :     assert(env_ind >= 0 && env_ind < n_env);
    1865           0 :     assert(shift_ind >= 0 && shift_ind < n_shift);
    1866             : 
    1867             :     UNUSED(n_env);
    1868             :     UNUSED(n_shift);
    1869           0 :     memset(vec_out, 0, sizeof(*vec_out)*dim_in);
    1870             : 
    1871           0 :     for (i = (shift_ind + n_signs - 1); i >= shift_ind; i--)
    1872             :     {
    1873             :         /* low numbered coeff  signs are in the msb's */
    1874             :         /* high  numbered coeff  signs are in the lsb's */
    1875           0 :         assert(i < dim_in);
    1876           0 :         sign_val = 1 - 2 * (sign_ind & 0x01);
    1877           0 :         sign_ind = (sign_ind >> 1);   
    1878           0 :         vec_out[i] = sign_val * env_ptrs[env_ind][i];    /* vec_out[i] = sign_val * amps[env_ind*(M - 1) + i]; */
    1879             :     }
    1880           0 : }
    1881             : 
    1882           0 : void snsQuantScfDecLR(LC3_INT32* sns_vq_idx, LC3_FLOAT* scf_q, LC3_INT32 pitch_rx, LC3_INT32 ltpf_rx)
    1883             : {
    1884             :     LC3_INT32   i;
    1885             :     LC3_INT32 mPVQ_ind;         /* can be 16-17 bits */
    1886             :     LC3_INT16   shape_idx, gain_idx, cb_idx, aux_idx, LS_ind;
    1887             :     LC3_INT16   env_ind, shift_ind, sign_ind, n_signs;
    1888             : 
    1889             :     LC3_INT32 Y_shape_j[M];
    1890             :     LC3_FLOAT Xq_shape_j[M], Xq_shape_j_idct[M], sum;
    1891             :     const LC3_FLOAT *cb;
    1892             :     const LC3_FLOAT *gainTab;
    1893             :     LC3_FLOAT st1_scf_q[M];  
    1894           0 :     LC3_INT16 CBCmeanp_ind = pitch_rx; /* 0 or 1 */
    1895             :     const LC3_FLOAT *mean_cb;
    1896           0 :     LC3_INT16 sign_mask = 0x07ff;
    1897             : 
    1898             : 
    1899             : #ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY
    1900             :     UNUSED(ltpf_rx);
    1901             : #endif 
    1902             : 
    1903           0 :     sum = 0;
    1904           0 :     memset(Y_shape_j, 0, sizeof(LC3_INT32) * M);
    1905             : 
    1906           0 :     gainTab = &(lrsns_gains_Q11[0][0]);  /* gcc warning  init   */
    1907           0 :     gain_idx = 0;                     /* gcc  warning init   */
    1908             : 
    1909           0 :     cb_idx = sns_vq_idx[0];
    1910           0 :     aux_idx = sns_vq_idx[1];
    1911           0 :     shape_idx = sns_vq_idx[2];  /* analysis order shape idx  -9,-10,    0,1,  2,3,4,5 */
    1912           0 :     gain_idx = sns_vq_idx[3];   /* stage 2 gain */
    1913             : 
    1914             :    /* Stage1 cand   */
    1915           0 :     if (shape_idx == -9)
    1916             :     {
    1917             :         /* minminal   2*16 SNS codebook, no DC */
    1918           0 :         cb = lrsns_st1A_topTab_1bitNoDC;
    1919           0 :         memcpy(scf_q, &(cb[cb_idx * M]), sizeof(LC3_FLOAT) * M);
    1920             :     }
    1921           0 :     else if (shape_idx == -10)
    1922             :     {    /* 0..339 */ /* stage 1 only, transmitted  in 9+1= 10 bits */
    1923           0 :         if (cb_idx < 170)
    1924             :         {  /*Stage 1B   */
    1925           0 :             snslr_st1B_vector_dec(cb_idx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, lrsns_st1B_merged170orderSortedSegmCum, lrsns_st1B_merged170orderSort12bitIdx, scf_q);
    1926           0 :             snslr_remove_st1_DC_fQ11(scf_q, M);
    1927             :         }
    1928             :         else
    1929             :         {
    1930           0 :             cb_idx -= 170;
    1931             :             /*  Stage 1C  harm outlier  CB  with a  pitch dependent mean   */
    1932             :             /*  Q11 values , so that BASOP and float  always becomes BE in synthesis*/
    1933           0 :             assert(cb_idx >= 0 && cb_idx < 170);
    1934           0 :             snslr_st1C_vector_dec(cb_idx, lrsns_st1C_Both_Word8, lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1],
    1935             :                 M, 170, scf_q
    1936             :             );
    1937             : 
    1938             : 
    1939             :             /* cbC add harmonic mean , based on pitch_info availability */
    1940           0 :             pitch_rx = sns_vq_idx[3];    /* LTP active flag directly from dec_entropy */
    1941             : #ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY
    1942             :             ltpf_rx = 0;                               /* CB_C has no dependency on LTPF active flag */
    1943             : #else 
    1944           0 :             ltpf_rx = sns_vq_idx[4];   /* LTPF active flag LTP active flag directly from dec_entropy */
    1945             : #endif 
    1946           0 :             CBCmeanp_ind = pitch_rx; /* 0 or 1 */
    1947             : #ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY
    1948           0 :             if (pitch_rx != 0 && ltpf_rx != 0)
    1949             :             {
    1950           0 :                 CBCmeanp_ind = CBCmeanp_ind + 1;  /* high corr ltpf_rx is also active */
    1951             :             }
    1952             : #endif
    1953             : 
    1954           0 :             mean_cb = lrsns_st1CTrainedMapMeans[CBCmeanp_ind]; /* point to pitch dependent mean */
    1955           0 :             for (i = 0; i < M; i++)
    1956             :             {
    1957           0 :                 scf_q[i] += mean_cb[i];
    1958             :             }
    1959             :             /* remove_DC()  call is not required for section  C  */
    1960             :             /* a very small DC can still exist though,  due to Q7+Q4 quantization of values */
    1961             :         }
    1962             :     }
    1963             :     else
    1964             :     {     /* 0...169 */   /* st1B*   used with a stage 2  shape submode  */
    1965           0 :         assert(shape_idx >= 0);
    1966           0 :         snslr_st1B_vector_dec(cb_idx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, lrsns_st1B_merged170orderSortedSegmCum, lrsns_st1B_merged170orderSort12bitIdx, scf_q);
    1967           0 :         snslr_remove_st1_DC_fQ11(scf_q, M);      /* DC needs removal for st1 part B */
    1968             :     }
    1969           0 :     memcpy(st1_scf_q, scf_q, sizeof(LC3_FLOAT) * M); /* keep track of stage 1 contribution */
    1970             : 
    1971           0 :     if (shape_idx >= 0) /* stage 2 shapes 0,1,  2,3,4,5   ( negative idx used for stage1 only   */
    1972             :     {
    1973             :         /* Stage 2 SNS VQ decoding */
    1974             :         /* Decode shape_j */
    1975           0 :         Y_shape_j[0] = 0;   /* no DCT-II DC-coeff decoded */
    1976             : 
    1977           0 :         switch (shape_idx)
    1978             :         {
    1979           0 :         case 0:  /* splitLF 29 bits total  */
    1980           0 :             LS_ind = aux_idx;
    1981           0 :             mPVQ_ind = sns_vq_idx[4];  /* mPVQ(5,6) or mPVQ(5,8) */
    1982             : 
    1983           0 :             if (sns_vq_idx[5] >= 0)
    1984             :             {
    1985           0 :                 MPVQdeenum(5, 6, LS_ind, mPVQ_ind, &Y_shape_j[1]);
    1986           0 :                 LS_ind = sns_vq_idx[5] & 0x1;
    1987           0 :                 mPVQ_ind = sns_vq_idx[5] >> 1;
    1988           0 :                 MPVQdeenum(8, 2, LS_ind, mPVQ_ind, &Y_shape_j[1 + 5]);
    1989             :             }
    1990             :             else
    1991             :             {
    1992           0 :                 MPVQdeenum(5, 8, LS_ind, mPVQ_ind, &Y_shape_j[1]);
    1993             :             }
    1994           0 :             gainTab = &(lrsns_gains_Q11[0][0]);/* 4 levels in 2 bits  */
    1995             : 
    1996           0 :             break;
    1997           0 :         case 1: /* full  30 bits total */
    1998           0 :             LS_ind = aux_idx;
    1999           0 :             mPVQ_ind = sns_vq_idx[4];
    2000           0 :             MPVQdeenum(15, 5, LS_ind, mPVQ_ind, &Y_shape_j[1]);
    2001           0 :             gainTab = &(lrsns_gains_Q11[1][0]); /* 8 levels in 3 bits  */
    2002             : 
    2003           0 :             break;
    2004           0 :         case 2: /* fix env 0  ,  init_bell      12 signs  */
    2005             :         case 3: /* fix env 1  ,  decay 24-->13  12 signs */
    2006             :         case 4: /* fix env 2  ,  start bell      12 signs */
    2007             :         case 5: /* fix env 3  ,  early bell     10 signs  */
    2008           0 :             LS_ind = aux_idx; /* s0 */
    2009           0 :             env_ind = sns_vq_idx[4];
    2010           0 :             assert(env_ind == (shape_idx - 2));
    2011             : 
    2012           0 :             n_signs = 12; /* including s0 */
    2013           0 :             if (env_ind == 3) {
    2014           0 :                 n_signs -= 2;
    2015             :             }
    2016           0 :             sign_mask = (sign_mask >> (12 - n_signs));
    2017             : 
    2018           0 :             shift_ind = sns_vq_idx[5] >> (n_signs - 1);
    2019           0 :             sign_ind = sns_vq_idx[5] & sign_mask;
    2020             : 
    2021             :             /* put s0 , right next to s1 , to make the sign decoding loop easier */
    2022           0 :             sign_ind = (sign_ind)+(LS_ind << (n_signs - 1));   /* s0 put as MSB at 12th position  2^11 , lsb at 2^0 */
    2023             : 
    2024             :             /*FixEnvShiftSigns deenumeration */
    2025           0 :             FESSdeenum(15, 4, 4, n_signs, env_ind, shift_ind, sign_ind, &Y_shape_j[1]);    /*30b    ,   4xenv,4xshifts, 10 or12 signs, over 15 positions,*/
    2026           0 :             gainTab = &(lrsns_gains_Q11[2][0]);; /* 8 levels in 3 bits  */
    2027             :             /* fix_envshift_nb = env_ind * 4 + shift_ind; */          /* index for fast normalization lookup */
    2028           0 :             break;
    2029           0 :         default:
    2030             : 
    2031           0 :             break;
    2032             :         }
    2033             : 
    2034             :         /* Unit energy normalization of the received shape */
    2035           0 :         for (i = 0; i < M; i++)
    2036             :         {
    2037           0 :             sum += (Y_shape_j[i] * Y_shape_j[i]);
    2038             :         }
    2039             : 
    2040           0 :         sum = 1.0 / LC3_SQRT(sum);   /* all shapes will have tabled inv_sqrt() divisions as factors in BASOP */
    2041             : 
    2042           0 :         for (i = 0; i < M; i++)
    2043             :         {
    2044           0 :             Xq_shape_j[i] = Y_shape_j[i] * sum;
    2045             :         }
    2046             : 
    2047             :         /* Reconstruction of the quantized SNS scale factors */
    2048           0 :         idct_II(Xq_shape_j, Xq_shape_j_idct, M);
    2049           0 :         for (i = 0; i < M; i++) {
    2050           0 :             scf_q[i] += Xq_shape_j_idct[i] * gainTab[gain_idx];
    2051             :         }
    2052             :     }
    2053             :     else
    2054             :     {  /* -9, -10 */
    2055             :       /* LRSNS stage 1 variations  only */
    2056           0 :         memcpy(scf_q, st1_scf_q, sizeof(LC3_FLOAT) * M);
    2057             :     }
    2058           0 : }
    2059             :  
    2060             : /* LRSNS integer precision based function needed in both encoder and decoder */
    2061           0 : LC3_FLOAT snslr_remove_st1_DC_fQ11(LC3_FLOAT *scfq, LC3_INT32  len)
    2062             : {
    2063             :     LC3_INT32  i; /*Counter*/
    2064             :     LC3_INT32  L_dcQ11;
    2065           0 :     LC3_FLOAT  f_dcQ11 = 0.0;
    2066           0 :     L_dcQ11 = 0L;
    2067             :     
    2068           0 :     for (i = 0; i < len; i++) {
    2069           0 :         L_dcQ11 += (LC3_INT32)(scfq[i] * 2048.0f);     /* BE simulation of DC Q11 summation of truncated values in BASOP, preferably  BE in synthesis in FLP/BASOP decoder  */
    2070             :     }
    2071             : 
    2072           0 :     assert(len == M);
    2073             :     {
    2074           0 :         L_dcQ11 = L_dcQ11 >> 4;         /* make the average in integer domain ,  no rounding applied before shift,   on purpose */
    2075           0 :         f_dcQ11 = ((LC3_FLOAT)L_dcQ11) *(1.0f / 2048.0f);  /*  now a Q11 value to match the overall generic Q11 BASOP scaling of stage1 variables  */
    2076             :     }
    2077             : 
    2078           0 :     for (i = 0; i < len; i++)
    2079             :     {
    2080           0 :         scfq[i] -= f_dcQ11;  /* result update */
    2081             :     }
    2082           0 :     return f_dcQ11;  /* output used for encoder side  mse update*/
    2083             : }
    2084             : 
    2085             : #endif

Generated by: LCOV version 1.14