LCOV - code coverage report
Current view: top level - lib_enc - hvq_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 2ac0e6bcc2725ab07bd14076a8fbdebaaf98bf20 Lines: 101 196 51.5 %
Date: 2025-11-08 23:21:44 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h" /* Compilation switches                   */
       7             : #include "cnst.h"
       8             : //#include "prot_fx.h"
       9             : #include "rom_com.h"
      10             : #include "prot_fx.h"     /* Function prototypes                    */
      11             : #include "prot_fx_enc.h" /* Function prototypes                    */
      12             : 
      13             : #define HVQ_ENC_NOISE_DELTA ( (Word16) 3277 ) /* 0.1 in Q15 */
      14             : 
      15             : static Word16 quant_lc_fx( const Word16, Word16 * );
      16             : 
      17             : 
      18             : /*--------------------------------------------------------------------------*
      19             :  * hvq_enc_fx()
      20             :  *
      21             :  * Harmonic VQ encoder
      22             :  *--------------------------------------------------------------------------*/
      23        1350 : Word16 hvq_enc_ivas_fx(                          /*o  : Consumed bits                            */
      24             :                         Encoder_State *st_fx,    /*i/o: encoder state structure                  */
      25             :                         const Word32 core_brate, /*i  : Total bit rate                           */
      26             :                         const Word16 hvq_bits,   /*i  : HVQ bit budget                           */
      27             :                         const Word16 Npeaks,     /*i  : Number of peaks                          */
      28             :                         const Word16 *ynrm,      /* i  : Envelope coefficients                   */
      29             :                         Word16 *R,               /* i/o: Bit allocation/updated bit allocation   */
      30             :                         Word16 *peaks,           /* i  : Peak pos. / Encoded peak pos.           */
      31             :                         Word32 *nf_gains,        /* i/o: Noise fill gains / Quant. nf gains   Q12*/
      32             :                         Word16 *noise_level,     /* o  : Quantized noise level                Q15*/
      33             :                         const Word32 *pe_gains,  /* i  : Peak gains                              */
      34             :                         const Word32 *coefs,     /* i  : spectrum coefficients in Q12            */
      35             :                         Word32 *coefs_out        /* o  : encoded spectrum coefficients in Q12    */
      36             : )
      37             : {
      38             :     const Word32 *pCoefs;
      39             :     Word16 bin_th, j, i, n;
      40             :     Word16 nf_cnt;
      41             :     Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS];
      42             :     Word16 q_noise_level[HVQ_BWE_NOISE_BANDS];
      43             :     Word32 d, nf_mean;
      44             :     Word32 nf, pe, pe_mean;
      45             :     Word16 bits_used, nBits;
      46             :     Word16 lb_nfpe;
      47             :     UWord16 dontCare;
      48             :     Word32 acc, numerator, denominator;
      49             :     Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3;
      50             :     Word16 manPeMean, manNfMean, manNfpe, man;
      51             :     Word16 tmp16, adjust;
      52             : 
      53        1350 :     bits_used = 0;
      54        1350 :     move16();
      55             : 
      56        1350 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
      57             :     {
      58         795 :         bin_th = HVQ_THRES_BIN_24k;
      59         795 :         move16();
      60         795 :         n = ( L_FRAME32k - HVQ_THRES_BIN_24k ) / HVQ_BWE_NOISE_BANDS;
      61         795 :         move16();
      62             :     }
      63             :     ELSE
      64             :     {
      65         555 :         bin_th = HVQ_THRES_BIN_32k;
      66         555 :         move16();
      67         555 :         n = ( L_FRAME32k - HVQ_THRES_BIN_32k ) / HVQ_BWE_NOISE_BANDS;
      68         555 :         move16();
      69             :     }
      70             : 
      71        1350 :     nf = 800 * 4096L; /* Q12 */
      72        1350 :     move32();
      73        1350 :     pe = 800 * 4096L; /* Q12 */
      74        1350 :     move32();
      75        1350 :     pCoefs = &coefs[bin_th];
      76             : 
      77             :     /* Find HB noise level */
      78        4050 :     FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ )
      79             :     {
      80        2700 :         nf_cnt = 0;
      81        2700 :         move16();
      82        2700 :         nf_mean = L_deposit_l( 0 );
      83        2700 :         pe_mean = L_deposit_l( 0 );
      84      511020 :         FOR( j = 0; j < n; j++ )
      85             :         {
      86      508320 :             d = L_abs( *pCoefs++ ); /* Q12 */
      87             : 
      88      508320 :             IF( GT_32( d, pe ) )
      89             :             {
      90             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
      91       29006 :                 acc = L_sub( pe, d );
      92       29006 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
      93       29006 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
      94             :             }
      95             :             ELSE
      96             :             {
      97             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
      98      479314 :                 acc = L_sub( pe, d );
      99      479314 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     100      479314 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     101             : 
     102      479314 :                 IF( GT_32( d, nf ) )
     103             :                 {
     104      359806 :                     acc = L_sub( nf, d );
     105      359806 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     106      359806 :                     nf = L_add( acc, d ); /* in Q12 and always positive */
     107             :                 }
     108             :                 ELSE
     109             :                 {
     110      119508 :                     acc = L_sub( nf, d );
     111      119508 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     112      119508 :                     nf = L_add( acc, d ); /* in Q12 always positive */
     113             :                 }
     114      479314 :                 nf_mean = L_add( nf_mean, nf ); /* in Q12 and always positive */
     115      479314 :                 nf_cnt = add( nf_cnt, 1 );      /* Q0 */
     116             :             }
     117             : 
     118      508320 :             pe_mean = L_add_sat( pe_mean, pe ); /* in Q12 and always positive */
     119             :         }
     120             : 
     121        2700 :         IF( pe_mean > 0 )
     122             :         {
     123        2700 :             expPeMean = norm_l( pe_mean );                        /* exponent */
     124        2700 :             manPeMean = extract_h( L_shl( pe_mean, expPeMean ) ); /* mantissa */
     125        2700 :             expNfMean = norm_l( nf_mean );                        /* exponent */
     126        2700 :             manNfMean = extract_h( L_shl( nf_mean, expNfMean ) ); /* mantissa */
     127             : 
     128        2700 :             numerator = L_mult0( manNfMean, n );
     129        2700 :             IF( nf_cnt > 0 )
     130             :             {
     131        2700 :                 denominator = L_mult0( manPeMean, nf_cnt ); /* in Q15 */
     132             :             }
     133             :             ELSE
     134             :             {
     135           0 :                 denominator = L_mult0( manPeMean, 1 ); /* in Q15 */
     136             :             }
     137        2700 :             manNfpe = ratio( numerator, denominator, &expo ); /* manNfpe in Q14 */
     138        2700 :             expNfpe = add( sub( expNfMean, expPeMean ), expo );
     139             : 
     140        2700 :             tmp16 = mult_r( manNfpe, manNfpe );             /* in Q(14+14+1-16) = Q13 */
     141        2700 :             tmp16 = mult_r( tmp16, manNfpe );               /* in Q(13+14+1-16) = Q12 */
     142        2700 :             acc = L_mult( tmp16, HVQ_NFPE_FACTOR_CUBE_FX ); /* in Q(12+6+1) = Q19 */
     143        2700 :             expNfpe3 = extract_l( L_mult0( expNfpe, 3 ) );  /* Cube operation */
     144             :             /* Number of bits required to adjust to Q15 */
     145        2700 :             adjust = add( 19 - ( 15 + 16 ), expNfpe3 );             /* +16 is due to the following extract_h(). */
     146        2700 :             noise_level[i] = extract_h( L_shr_sat( acc, adjust ) ); /* noise_level[] in Q15 */
     147        2700 :             move16();
     148        2700 :             q_noise_level_idx[i] = quant_lc_fx( noise_level[i], &q_noise_level[i] );
     149        2700 :             move16();
     150             :         }
     151             :         ELSE
     152             :         {
     153           0 :             q_noise_level_idx[i] = 0;
     154           0 :             move16();
     155           0 :             q_noise_level[i] = 0;
     156           0 :             move16();
     157             :         }
     158        2700 :         push_indice( st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 );
     159        2700 :         bits_used = add( bits_used, 2 );
     160             : 
     161        2700 :         noise_level[i] = q_noise_level[i]; /* in Q15 */
     162        2700 :         move16();
     163             :     }
     164             : 
     165        4050 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     166             :     {
     167        2700 :         IF( pe_gains[i] != 0 )
     168             :         {
     169             :             /* Neither pe_gains[] nor nf_gains[] is zero. */
     170        2700 :             man = ratio( nf_gains[i], pe_gains[i], &expo );    /* man in Q14 */
     171        2700 :             tmp16 = mult_r( man, man );                        /* in Q(14+14+1-16) = Q13 */
     172        2700 :             tmp16 = mult_r( tmp16, man );                      /* in Q(13+14+1-16) = Q12 */
     173        2700 :             acc = L_mult( tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX ); /* in Q(12+9+1) = Q22 */
     174        2700 :             expo3 = extract_l( L_mult0( expo, 3 ) );           /* Cube operation. */
     175             :             /* Number of bits required to adjust to Q15 */
     176        2700 :             adjust = add( 22 - ( 15 + 16 ), expo3 );         /* +16 is due to the following extract_h(). */
     177        2700 :             lb_nfpe = extract_h( L_shr_sat( acc, adjust ) ); /* noise_level[] in Q15 */
     178        2700 :             IF( GT_16( lb_nfpe, 16384 ) )                    /* in Q15 */
     179             :             {
     180         137 :                 lb_nfpe = 16384;
     181         137 :                 move16();
     182             :             }
     183        2700 :             Mpy_32_16_ss( nf_gains[i], shl_sat( lb_nfpe, 1 ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */
     184             :         }
     185             :         ELSE
     186             :         {
     187           0 :             nf_gains[i] = 0;
     188           0 :             move16();
     189             :         }
     190             :     }
     191        1350 :     nBits = peak_vq_enc_ivas_fx( st_fx->hBstr, st_fx->bwidth, coefs, coefs_out, core_brate, sub( hvq_bits, bits_used ),
     192             :                                  Npeaks, ynrm, R, peaks, &nf_gains[0] );
     193        1350 :     bits_used = add( bits_used, nBits );
     194        1350 :     return bits_used;
     195             : }
     196             : 
     197           0 : Word16 hvq_enc_fx(                          /*o  : Consumed bits                            */
     198             :                    Encoder_State *st_fx,    /*i/o: encoder state structure                  */
     199             :                    const Word32 core_brate, /*i  : Total bit rate                           */
     200             :                    const Word16 hvq_bits,   /*i  : HVQ bit budget                           */
     201             :                    const Word16 Npeaks,     /*i  : Number of peaks                          */
     202             :                    const Word16 *ynrm,      /* i  : Envelope coefficients                   */
     203             :                    Word16 *R,               /* i/o: Bit allocation/updated bit allocation   */
     204             :                    Word16 *peaks,           /* i  : Peak pos. / Encoded peak pos.           */
     205             :                    Word32 *nf_gains,        /* i/o: Noise fill gains / Quant. nf gains      */
     206             :                    Word16 *noise_level,     /* o  : Quantized noise level                   */
     207             :                    const Word32 *pe_gains,  /* i  : Peak gains                              */
     208             :                    const Word32 *coefs,     /* i  : spectrum coefficients in Q12            */
     209             :                    Word32 *coefs_out        /* o  : encoded spectrum coefficients in Q12    */
     210             : )
     211             : {
     212             :     const Word32 *pCoefs;
     213             :     Word16 bin_th, j, i, n;
     214             :     Word16 nf_cnt;
     215             :     Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS];
     216             :     Word16 q_noise_level[HVQ_BWE_NOISE_BANDS];
     217             :     Word32 d, nf_mean;
     218             :     Word32 nf, pe, pe_mean;
     219             :     Word16 bits_used, nBits;
     220             :     Word16 lb_nfpe;
     221             :     UWord16 dontCare;
     222             :     Word32 acc, numerator, denominator;
     223             :     Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3;
     224             :     Word16 manPeMean, manNfMean, manNfpe, man;
     225             :     Word16 tmp16, adjust;
     226             : 
     227           0 :     bits_used = 0;
     228           0 :     move16();
     229             : 
     230           0 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
     231             :     {
     232           0 :         bin_th = HVQ_THRES_BIN_24k;
     233           0 :         move16();
     234           0 :         n = ( L_FRAME32k - HVQ_THRES_BIN_24k ) / HVQ_BWE_NOISE_BANDS;
     235           0 :         move16();
     236             :     }
     237             :     ELSE
     238             :     {
     239           0 :         bin_th = HVQ_THRES_BIN_32k;
     240           0 :         move16();
     241           0 :         n = ( L_FRAME32k - HVQ_THRES_BIN_32k ) / HVQ_BWE_NOISE_BANDS;
     242           0 :         move16();
     243             :     }
     244             : 
     245           0 :     nf = 800 * 4096L; /* Q12 */
     246           0 :     move32();
     247           0 :     pe = 800 * 4096L; /* Q12 */
     248           0 :     move32();
     249           0 :     pCoefs = &coefs[bin_th];
     250             : 
     251             :     /* Find HB noise level */
     252           0 :     FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ )
     253             :     {
     254           0 :         nf_cnt = 0;
     255           0 :         move16();
     256           0 :         nf_mean = L_deposit_l( 0 );
     257           0 :         pe_mean = L_deposit_l( 0 );
     258           0 :         FOR( j = 0; j < n; j++ )
     259             :         {
     260           0 :             d = L_abs( *pCoefs++ ); /* Q12 */
     261             : 
     262           0 :             IF( GT_32( d, pe ) )
     263             :             {
     264             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
     265           0 :                 acc = L_sub( pe, d );
     266           0 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     267           0 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     268             :             }
     269             :             ELSE
     270             :             {
     271             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
     272           0 :                 acc = L_sub( pe, d );
     273           0 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     274           0 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     275             : 
     276           0 :                 IF( GT_32( d, nf ) )
     277             :                 {
     278           0 :                     acc = L_sub( nf, d );
     279           0 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     280           0 :                     nf = L_add( acc, d ); /* in Q12 and always positive */
     281             :                 }
     282             :                 ELSE
     283             :                 {
     284           0 :                     acc = L_sub( nf, d );
     285           0 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     286           0 :                     nf = L_add( acc, d ); /* in Q12 always positive */
     287             :                 }
     288           0 :                 nf_mean = L_add( nf_mean, nf ); /* in Q12 and always positive */
     289           0 :                 nf_cnt = add( nf_cnt, 1 );      /* Q0 */
     290             :             }
     291             : 
     292           0 :             pe_mean = L_add_sat( pe_mean, pe ); /* in Q12 and always positive */
     293             :         }
     294             : 
     295           0 :         IF( pe_mean > 0 )
     296             :         {
     297           0 :             expPeMean = norm_l( pe_mean );                        /* exponent */
     298           0 :             manPeMean = extract_h( L_shl( pe_mean, expPeMean ) ); /* mantissa */
     299           0 :             expNfMean = norm_l( nf_mean );                        /* exponent */
     300           0 :             manNfMean = extract_h( L_shl( nf_mean, expNfMean ) ); /* mantissa */
     301             : 
     302           0 :             numerator = L_mult0( manNfMean, n );
     303           0 :             IF( nf_cnt > 0 )
     304             :             {
     305           0 :                 denominator = L_mult0( manPeMean, nf_cnt ); /* in Q15 */
     306             :             }
     307             :             ELSE
     308             :             {
     309           0 :                 denominator = L_mult0( manPeMean, 1 ); /* in Q15 */
     310             :             }
     311           0 :             manNfpe = ratio( numerator, denominator, &expo ); /* manNfpe in Q14 */
     312           0 :             expNfpe = add( sub( expNfMean, expPeMean ), expo );
     313             : 
     314           0 :             tmp16 = mult_r( manNfpe, manNfpe );             /* in Q(14+14+1-16) = Q13 */
     315           0 :             tmp16 = mult_r( tmp16, manNfpe );               /* in Q(13+14+1-16) = Q12 */
     316           0 :             acc = L_mult( tmp16, HVQ_NFPE_FACTOR_CUBE_FX ); /* in Q(12+6+1) = Q19 */
     317           0 :             expNfpe3 = extract_l( L_mult0( expNfpe, 3 ) );  /* Cube operation */
     318             :             /* Number of bits required to adjust to Q15 */
     319           0 :             adjust = add( 19 - ( 15 + 16 ), expNfpe3 );             /* +16 is due to the following extract_h(). */
     320           0 :             noise_level[i] = extract_h( L_shr_sat( acc, adjust ) ); /* noise_level[] in Q15 */
     321           0 :             move16();
     322           0 :             q_noise_level_idx[i] = quant_lc_fx( noise_level[i], &q_noise_level[i] );
     323           0 :             move16();
     324             :         }
     325             :         ELSE
     326             :         {
     327           0 :             q_noise_level_idx[i] = 0;
     328           0 :             move16();
     329           0 :             q_noise_level[i] = 0;
     330           0 :             move16();
     331             :         }
     332           0 :         push_indice( st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 );
     333           0 :         bits_used = add( bits_used, 2 );
     334             : 
     335           0 :         noise_level[i] = q_noise_level[i]; /* in Q15 */
     336           0 :         move16();
     337             :     }
     338             : 
     339           0 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     340             :     {
     341           0 :         IF( pe_gains[i] != 0 )
     342             :         {
     343             :             /* Neither pe_gains[] nor nf_gains[] is zero. */
     344           0 :             man = ratio( nf_gains[i], pe_gains[i], &expo );    /* man in Q14 */
     345           0 :             tmp16 = mult_r( man, man );                        /* in Q(14+14+1-16) = Q13 */
     346           0 :             tmp16 = mult_r( tmp16, man );                      /* in Q(13+14+1-16) = Q12 */
     347           0 :             acc = L_mult( tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX ); /* in Q(12+9+1) = Q22 */
     348           0 :             expo3 = extract_l( L_mult0( expo, 3 ) );           /* Cube operation. */
     349             :             /* Number of bits required to adjust to Q15 */
     350           0 :             adjust = add( 22 - ( 15 + 16 ), expo3 );         /* +16 is due to the following extract_h(). */
     351           0 :             lb_nfpe = extract_h( L_shr_sat( acc, adjust ) ); /* noise_level[] in Q15 */
     352           0 :             IF( lb_nfpe > 16384 )                            /* in Q15 */
     353             :             {
     354           0 :                 lb_nfpe = 16384;
     355           0 :                 move16();
     356             :             }
     357           0 :             Mpy_32_16_ss( nf_gains[i], shl_sat( lb_nfpe, 1 ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */
     358             :         }
     359             :         ELSE
     360             :         {
     361           0 :             nf_gains[i] = 0;
     362           0 :             move16();
     363             :         }
     364             :     }
     365           0 :     nBits = peak_vq_enc_fx( st_fx->hBstr, st_fx->bwidth, coefs, coefs_out, core_brate, sub( hvq_bits, bits_used ),
     366             :                             Npeaks, ynrm, R, peaks, &nf_gains[0] );
     367           0 :     move16();
     368           0 :     bits_used = add( bits_used, nBits );
     369           0 :     return bits_used;
     370             : }
     371             : 
     372             : /*-----------------------------------------------------------------------------
     373             :  * quant()
     374             :  *
     375             :  * Quantize the noise to one of the levels in {0, 0.1, 0.2, 0.3}
     376             :  *----------------------------------------------------------------------------*/
     377        2700 : static Word16 quant_lc_fx( const Word16 x, Word16 *qx )
     378             : {
     379             :     Word16 indx;
     380             : 
     381        2700 :     IF( LT_16( x, HVQ_ENC_NOISE_DELTA / 2 ) )
     382             :     {
     383        2011 :         indx = 0;
     384        2011 :         move16();
     385        2011 :         *qx = 0;
     386        2011 :         move16();
     387             :     }
     388         689 :     ELSE IF( LT_16( x, 3 * HVQ_ENC_NOISE_DELTA / 2 ) )
     389             :     {
     390         226 :         indx = 1;
     391         226 :         move16();
     392         226 :         *qx = HVQ_ENC_NOISE_DELTA;
     393         226 :         move16();
     394             :     }
     395         463 :     ELSE IF( LT_16( x, 5 * HVQ_ENC_NOISE_DELTA / 2 ) )
     396             :     {
     397         137 :         indx = 2;
     398         137 :         move16();
     399         137 :         *qx = 2 * HVQ_ENC_NOISE_DELTA;
     400         137 :         move16();
     401             :     }
     402             :     ELSE
     403             :     {
     404         326 :         indx = 3;
     405         326 :         move16();
     406         326 :         *qx = 3 * HVQ_ENC_NOISE_DELTA;
     407         326 :         move16();
     408             :     }
     409             : 
     410        2700 :     return indx;
     411             : }

Generated by: LCOV version 1.14