LCOV - code coverage report
Current view: top level - lib_lc3plus - dec_entropy.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 156 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.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 "functions.h"
      11             : 
      12             : static Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits);
      13             : 
      14             : static Word16 ac_dec_split_st2VQ_CW(                     /* local BER flag */
      15             :                                     const Word32 L_cwRx, /* max 25 bits */
      16             :                                     const Word32 L_szA, const Word32 L_szB, Word32 *L_cwA, Word32 *L_cwB,
      17             :                                     Word16 *submodeLSB);
      18             : 
      19           0 : void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits,
      20             :                               Word16 L_spec, Word16 fs_idx, Word16 BW_cutoff_bits, Word16 *tns_numfilters,
      21             :                               Word16 *lsbMode, Word16 *lastnz, Word16 *bfi, Word16 *tns_order, Word16 *fac_ns_idx,
      22             :                               Word16 *gg_idx, Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx,
      23             :                               Word16 frame_dms)
      24             : {
      25             :     Dyn_Mem_Deluxe_In(
      26             :         Word16  L, submodeLSB;
      27             :         Word32  tmp32, tmp32lim;
      28             :         Word16  gain_e, gain, submodeMSB, BER_detect;
      29             :         Word32 n;
      30             :         UWord8 *ptr;
      31             :     );
      32             : 
      33           0 :     ptr        = bytes;
      34           0 :     *bp_side   = shr_pos(sub(nbbits, 1), 3);
      35           0 :     *mask_side = shl(1, sub(8, sub(nbbits, shl_pos(*bp_side, 3))));
      36             : 
      37             :     /* Cutoff-detection */
      38           0 :     IF (BW_cutoff_bits > 0)
      39             :     {
      40           0 :         *BW_cutoff_idx = read_indice(ptr, bp_side, mask_side, BW_cutoff_bits);
      41             :         /* check for bitflips */
      42           0 :         IF (sub(fs_idx, *BW_cutoff_idx) < 0)
      43             :         {
      44           0 :             *BW_cutoff_idx = fs_idx;
      45           0 :             *bfi           = 1;  move16();
      46             :             Dyn_Mem_Deluxe_Out();
      47           0 :             return;
      48             :         }
      49             :     }
      50             :     ELSE
      51             :     {
      52           0 :         *BW_cutoff_idx = fs_idx;
      53             :     }
      54             : 
      55             :     /* Number of TNS filters */
      56           0 :     IF (sub(*BW_cutoff_idx, 3) >= 0 && frame_dms >= 50)
      57             :     {
      58           0 :         *tns_numfilters = 2;  move16();
      59             :     }
      60             :     ELSE
      61             :     {
      62           0 :         *tns_numfilters = 1;  move16();
      63             :     }
      64             : 
      65             :     /* Decode number of ntuples */
      66           0 :     L       = sub(14, norm_s(negate(L_spec)));
      67           0 :     n       = read_indice(ptr, bp_side, mask_side, L);
      68           0 :     n       = add(n, 1);
      69           0 :     *lastnz = shl_pos(n, 1);
      70           0 :     IF (sub(*lastnz, L_spec) > 0)
      71             :     {
      72           0 :         *bfi = 1;  move16();
      73             :         Dyn_Mem_Deluxe_Out();
      74           0 :         return;
      75             :     }
      76             : 
      77             :     /* Mode bit */
      78           0 :     *lsbMode = read_bit(ptr, bp_side, mask_side);
      79             : 
      80             :     /* Decode global-gain */
      81           0 :     *gg_idx = read_indice(ptr, bp_side, mask_side, 8);  move16();
      82           0 :     tmp32  = L_shl_pos(L_mult0(*gg_idx, 0x797D), 7);  /* 6Q25; 0x797D -> log2(10)/28 (Q18) */
      83           0 :     gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); /* get exponent */
      84           0 :     gain   = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); 
      85           0 :     assert(gain >= 0); /* JSv, check if shr_pos(gain,1)  is more appropriate) */
      86           0 :     gain   = shr_r(gain, 1);
      87           0 :     gain_e = add(gain_e, 1);
      88             : 
      89             :     /* Decode TNS on/off flag */
      90           0 :     tns_order[1] = 0; move16(); /* fix problem with uninitialized memory */
      91           0 :     FOR (n = 0; n < *tns_numfilters; n++)
      92             :     {
      93           0 :         tns_order[n] = read_bit(ptr, bp_side, mask_side);  move16();
      94             :     }
      95             : 
      96             :     /* LTPF on/off */
      97             : #ifdef ENABLE_HR_MODE
      98           0 :     ltpf_idx[0] = read_bit(ptr, bp_side, mask_side);  move16();
      99             : #else
     100             :     ltpf_idx[0] = read_indice(ptr, bp_side, mask_side, 1);  move16();
     101             : #endif
     102             : 
     103             :     /* Decode SNS VQ parameters - 1st stage (10 bits) */
     104             : #ifdef ENABLE_HR_MODE
     105           0 :     L = read_indice(ptr, bp_side, mask_side, 5 + 5);
     106           0 :     L_scf_idx[0] = L_deposit_l(s_and(L, 0x1F)); /* stage1 LF  5  bits */
     107           0 :     L_scf_idx[1] = L_deposit_l(shr_pos(L, 5)); /* stage1 HF  5 bits  */
     108             : #else
     109             :     L_scf_idx[0] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 5)); /* stage1 LF  5  bits */
     110             :     L_scf_idx[1] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 5)); /* stage1 HF  5 bits  */
     111             : #endif
     112             : 
     113             :     /* Decode SNS VQ parameters - 2nd stage side-info (3-4 bits) */
     114           0 :     submodeMSB   = read_bit(ptr, bp_side, mask_side); /* submodeMSB 1 bit */
     115           0 :     L_scf_idx[2] = L_deposit_l(shl_pos(submodeMSB, 1));
     116           0 :     ASSERT(sns_gainMSBbits[L_scf_idx[2]] > 0);
     117           0 :     L_scf_idx[3] = L_deposit_l(
     118           0 :         read_indice(ptr, bp_side, mask_side, sns_gainMSBbits[L_scf_idx[2]])); /* gains or gain MSBs  1-2 bits  */
     119           0 :     L_scf_idx[4] = read_bit(ptr, bp_side, mask_side);                         /*  shape LS 1 bit */
     120             : 
     121             :     /* Decode SNS VQ parameters - 2nd stage data (24-25 bits) */
     122           0 :     IF (submodeMSB == 0)
     123             :     { /* shape_j = 0, or 1  */
     124             :         /* regular mode A,B indexes integer multiplexed, total 24.x bits  MPVQ codeword section A and  codeword for
     125             :          * section B */
     126             :         /* regular mode  mode shape  index   total  24.9999 bits    MPVQ codeword  */
     127           0 :         tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 13));
     128           0 :         tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 13));  move16(); /*for ber state   */
     129             :         BER_detect =
     130           0 :             ac_dec_split_st2VQ_CW(       /* local BER flag */
     131             :                                   tmp32, /* L_cwRx  max 25 bits */
     132           0 :                                   sns_MPVQ_Sz[0][0], UL_addNsD(sns_MPVQ_Sz[0][1], sns_MPVQ_Sz[1][1]), /* 12+2 = 14 */
     133             :                                   (&L_scf_idx[5]),                                                    /* shape A */
     134             :                                   (&L_scf_idx[6]), /* shape B or  gain LSB */
     135             :                                   &submodeLSB      /* total submode update below  */
     136             :             );
     137           0 :         IF (submodeLSB != 0)
     138             :         { /* add gainLSB bit */
     139           0 :             L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_scf_idx[6]);
     140           0 :             L_scf_idx[6] = -2L;
     141             :         }
     142             :     }
     143             :     ELSE
     144             :     { /* shape_j = 2 or 3  */
     145           0 :         ASSERT(submodeMSB == 1);
     146             :         /* outlier mode shape  index   total  23.8536 +  19.5637 (19.5637 < (log2(2.^24 -2.^23.8537))    bits    MPVQ
     147             :          * codeword  */
     148           0 :         tmp32        = L_deposit_l(read_indice(ptr, bp_side, mask_side, 12));
     149           0 :         tmp32        = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 12));
     150           0 :         L_scf_idx[5] = tmp32;  move32(); /*shape outl_near or outl_far */
     151           0 :         submodeLSB = 0;  move16();
     152           0 :         BER_detect = 0;  move16();
     153           0 :         tmp32lim = L_add(sns_MPVQ_Sz[2][0], L_shl_pos(sns_MPVQ_Sz[3][0], 1));
     154           0 :         IF (L_sub(tmp32, tmp32lim) >= 0)
     155             :         {
     156           0 :             BER_detect = 1;  move16();
     157             :         }
     158             :         ELSE
     159             :         {
     160           0 :             tmp32 = L_sub(tmp32, sns_MPVQ_Sz[2][0]); /*  a potential high index is computed */
     161           0 :             IF (tmp32 >= 0)
     162             :             {
     163           0 :                 submodeLSB = 1;  move16();
     164           0 :                 ASSERT(tmp32 >= 0 && tmp32 < (Word32)(2 * sns_MPVQ_Sz[3][0]));
     165           0 :                 L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_and(tmp32, 0x1)); /* add LSB_gain bit to gain MSBs */
     166           0 :                 L_scf_idx[5] = L_shr_pos(tmp32, 1); /* MPVQ index with offset and gainLSB removed */
     167           0 :                 L_scf_idx[6] = -2L;  move32();
     168             :             }
     169             :             ELSE
     170             :             {
     171           0 :                 L_scf_idx[6] = -1L;  move32();
     172             :             }
     173             :         }
     174             :     }
     175           0 :     L_scf_idx[2] =
     176           0 :         L_add(L_scf_idx[2], L_deposit_l(submodeLSB)); /* decoder internal signal shape_j = submode 0..3 to VQ */
     177             : 
     178           0 :     IF (BER_detect > 0)
     179             :     {
     180           0 :         *bfi = 1;  move16();
     181             :         Dyn_Mem_Deluxe_Out();
     182           0 :         return;
     183             :     }
     184             : 
     185             :     /* LTPF data */
     186           0 :     IF (ltpf_idx[0] != 0)
     187             :     {
     188             : #ifdef ENABLE_HR_MODE
     189           0 :         L = read_indice(ptr, bp_side, mask_side, 1+9);          move16();
     190           0 :         ltpf_idx[1] = s_and(L, 1);                              move16();
     191           0 :         ltpf_idx[2] = shr_pos(L, 1);                            move16();
     192             : #else
     193             :         ltpf_idx[1] = read_indice(ptr, bp_side, mask_side, 1);  move16();
     194             :         ltpf_idx[2] = read_indice(ptr, bp_side, mask_side, 9);  move16();
     195             : 
     196             : #endif
     197             :     }
     198             :     ELSE
     199             :     {
     200           0 :         ltpf_idx[1] = 0;  move16();
     201           0 :         ltpf_idx[2] = 0;  move16();
     202             :     }
     203             : 
     204             :     /* Decode noise-fac */
     205           0 :     *fac_ns_idx = read_indice(ptr, bp_side, mask_side, 3);  move16();
     206             : 
     207             :     Dyn_Mem_Deluxe_Out();
     208             : }
     209             : 
     210             : #ifdef ENABLE_PADDING
     211           0 : int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled,
     212             :                    Word16 *total_padding, Word16 *np_zero)
     213             : {
     214             :     Word16 lastnz_threshold;
     215             :     Word16 padding_len_bits, padding_len;
     216             : 
     217             :     Word16 bp_side;
     218           0 :     Word16 nbbytes = shr(nbbits,3);
     219             : 
     220             :     Word16  mask_side;
     221           0 :     UWord8 *ptr = bytes;
     222             : 
     223             :     Word16 lastnz;
     224           0 :     Word16 nbits = sub(14, norm_s(negate(L_spec)));
     225           0 :     if (sub(nbbits, nbits) < 0)
     226             :     {
     227           0 :         return 1;
     228             :     }
     229           0 :     *np_zero     = 0;
     230             : 
     231           0 :     *total_padding = 0;
     232             : 
     233           0 :     bp_side   = shr_pos(sub(nbbits, 1), 3);
     234           0 :     mask_side = shl(1, sub(8, sub(nbbits, shl_pos(bp_side, 3))));
     235             : 
     236           0 :     test();
     237           0 :     IF (sub(bp_side, 19) < 0 || sub(bp_side, LC3PLUS_MAX_BYTES ) >= 0) {
     238           0 :         return 1;
     239             :     }
     240             : 
     241           0 :     ptr = bytes;
     242             : 
     243           0 :     IF (BW_cutoff_bits > 0)
     244             :     {
     245           0 :         read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits);
     246           0 :         move16();
     247             :     }
     248             : 
     249           0 :     lastnz = read_indice(ptr, &bp_side, &mask_side, nbits);
     250           0 :     move16();
     251             : 
     252           0 :     lastnz_threshold = sub(shl(1, nbits), 2);
     253             : 
     254           0 :     WHILE (lastnz == lastnz_threshold)
     255             :     {
     256           0 :         padding_len_bits = sub(sub(12, nbits), BW_cutoff_bits);
     257             : 
     258             :         /*Read padding length*/
     259           0 :         padding_len = read_indice(ptr, &bp_side, &mask_side, padding_len_bits);
     260           0 :         move16();
     261             : 
     262             :         /* Read 4 reserved bits */
     263           0 :         read_indice(ptr, &bp_side, &mask_side, 4);
     264           0 :         move16();
     265             : 
     266           0 :         IF (ep_enabled == 0)
     267             :         {
     268             :             /* Discard padding length bytes */
     269           0 :             bp_side        = sub(bp_side, padding_len);
     270           0 :             *total_padding = add(add(*total_padding, padding_len), 2); move16();
     271             :         }
     272             :         ELSE
     273             :         {
     274           0 :             *total_padding = add(*total_padding, 2); move16();
     275           0 :             *np_zero       = add(*np_zero, padding_len); move16();
     276             :         }
     277             :         
     278             :         /* test if we have less than 20 bytes left; if so frame is broken */
     279           0 :         IF (sub(sub(nbbytes,add(*total_padding,*np_zero)),20) < 0) {
     280           0 :             return 1;
     281             :         }
     282             : 
     283             :         /* Read bandwidth bits */
     284           0 :         IF (BW_cutoff_bits > 0)
     285             :         {
     286           0 :             read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits);
     287           0 :             move16();
     288             :         }
     289             : 
     290           0 :         lastnz = read_indice(ptr, &bp_side, &mask_side, nbits);
     291           0 :         move16();
     292             :     }
     293             : 
     294           0 :     IF (ep_enabled != 0)
     295             :     {
     296           0 :         *total_padding = add(*total_padding, *np_zero); move16();
     297             :     }
     298           0 :     return 0;
     299             : }
     300             : #endif
     301             : 
     302           0 : static __forceinline Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits)
     303             : {
     304             :     Dyn_Mem_Deluxe_In(
     305             :         Word16  indice, bit;
     306             :         Counter i;
     307             :     );
     308             : 
     309           0 :     indice = read_bit(ptr, bp, mask);
     310             : 
     311           0 :     FOR (i = 1; i < numbits; i++)
     312             :     {
     313           0 :         bit    = read_bit(ptr, bp, mask);
     314           0 :         indice = add(indice, lshl_pos(bit, i));
     315             :     }
     316             : 
     317             :     Dyn_Mem_Deluxe_Out();
     318           0 :     return indice;
     319             : }
     320             : 
     321           0 : static __forceinline Word16 ac_dec_split_st2VQ_CW(                     /* local BER flag */
     322             :                                                   const Word32 L_cwRx, /* max 25 bits */
     323             :                                                   const Word32 L_szA, const Word32 L_szB, Word32 *L_cwA, Word32 *L_cwB,
     324             :                                                   Word16 *submodeLSB)
     325             : {
     326             :     /* demultiplex:  L_cwRx =   L_cwB(21.z bits) * L_szA(3.y bits)   + L_cwA(21.x bits)); */
     327             :     Word16  start, fin, ind;
     328             :     Word32  L_tmp, L_max_size;
     329             :     Counter i;
     330             : 
     331           0 :     L_max_size = (Word32)UL_Mpy_32_32((UWord32)L_szB, (UWord32)L_szA); /*  may be tabled  */
     332             : 
     333             :     /* section B  ind larger than 13  out of the possible  14 =   0..13  */
     334           0 :     IF (L_sub(L_cwRx, L_max_size) >= 0)
     335             :     {
     336           0 :         *L_cwA      = L_deposit_l(0);
     337           0 :         *L_cwB      = L_deposit_l(0);
     338           0 :         *submodeLSB = 0;  move16();
     339           0 :         return (Word16)1; /* set berFlag and exit */
     340             :     }
     341             : 
     342             :     /*initial binary split of cw,  select top or low half */
     343           0 :     start = 0;  move16();
     344             : 
     345           0 :     ASSERT((L_szB & 0x1L) == 0); /* this middle split only works if  L_szB is even  */
     346           0 :     if (L_sub(L_cwRx, L_shr_pos(L_max_size, 1)) >= 0)
     347             :     {
     348           0 :         start = L_shr_pos(L_szB, 1); /* top half start index */
     349             :     }
     350             : 
     351             :     /*linear loop over a low  or a  high section */
     352           0 :     ind = start;  move16();
     353           0 :     L_tmp = L_negate(L_cwRx); /* search from negative side */
     354             : 
     355           0 :     L_tmp = L_add(L_tmp, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)start), (UWord32)L_szA));
     356             :     /* start is 0 or 7 */ /*non-fractional mult is   (int)start * L_szA */
     357             : 
     358             :     /* a short linear run  over  ceil(szB/2) =  7   values  */
     359             : 
     360           0 :     fin = add(start, shr_pos(L_szB, 1));
     361           0 :     FOR (i = start; i < fin; i++)
     362             :     {
     363           0 :         ind   = add(ind, 1);
     364           0 :         L_tmp = L_add(L_tmp, L_szA);
     365           0 :         if (L_tmp > 0)
     366             :         {
     367           0 :             ind = sub(ind, 1); /* passed criteria point, keep index    */
     368             :         }
     369             :     }
     370             : 
     371           0 :     *L_cwB = L_deposit_l(ind);
     372           0 :     *L_cwA = L_sub(L_cwRx, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)ind),
     373             :                                                 (UWord32)L_szA)); /* non-fractional mult;   (int)ind * L_szA */
     374             : 
     375           0 :     ASSERT(*L_cwA >= 0 && *L_cwA < L_szA);
     376           0 :     ASSERT(*L_cwB >= 0 && *L_cwB < L_szB);
     377             : 
     378           0 :     *submodeLSB = 0;
     379           0 :     *L_cwB      = L_sub(*L_cwB, 2);
     380           0 :     if (*L_cwB < 0)
     381             :     {
     382           0 :         *submodeLSB = 1;  move16();
     383             :     }
     384           0 :     *L_cwB = L_mac0(*L_cwB, 2, *submodeLSB); /* add back gain ind if needed */
     385             : 
     386           0 :     return 0; /* no BER */
     387             : }

Generated by: LCOV version 1.14