LCOV - code coverage report
Current view: top level - lib_enc - hvq_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 103 200 51.5 %
Date: 2025-05-03 01:55:50 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        1463 : 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             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      53        1463 :     Flag Overflow = 0;
      54        1463 :     move32();
      55             : #endif
      56        1463 :     bits_used = 0;
      57        1463 :     move16();
      58             : 
      59        1463 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
      60             :     {
      61         849 :         bin_th = HVQ_THRES_BIN_24k;
      62         849 :         move16();
      63         849 :         n = ( L_FRAME32k - HVQ_THRES_BIN_24k ) / HVQ_BWE_NOISE_BANDS;
      64         849 :         move16();
      65             :     }
      66             :     ELSE
      67             :     {
      68         614 :         bin_th = HVQ_THRES_BIN_32k;
      69         614 :         move16();
      70         614 :         n = ( L_FRAME32k - HVQ_THRES_BIN_32k ) / HVQ_BWE_NOISE_BANDS;
      71         614 :         move16();
      72             :     }
      73             : 
      74        1463 :     nf = 800 * 4096L; /* Q12 */
      75        1463 :     move32();
      76        1463 :     pe = 800 * 4096L; /* Q12 */
      77        1463 :     move32();
      78        1463 :     pCoefs = &coefs[bin_th];
      79             : 
      80             :     /* Find HB noise level */
      81        4389 :     FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ )
      82             :     {
      83        2926 :         nf_cnt = 0;
      84        2926 :         move16();
      85        2926 :         nf_mean = L_deposit_l( 0 );
      86        2926 :         pe_mean = L_deposit_l( 0 );
      87      552590 :         FOR( j = 0; j < n; j++ )
      88             :         {
      89      549664 :             d = L_abs( *pCoefs++ ); /* Q12 */
      90             : 
      91      549664 :             IF( GT_32( d, pe ) )
      92             :             {
      93             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
      94       30913 :                 acc = L_sub( pe, d );
      95       30913 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
      96       30913 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
      97             :             }
      98             :             ELSE
      99             :             {
     100             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
     101      518751 :                 acc = L_sub( pe, d );
     102      518751 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     103      518751 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     104             : 
     105      518751 :                 IF( GT_32( d, nf ) )
     106             :                 {
     107      387583 :                     acc = L_sub( nf, d );
     108      387583 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     109      387583 :                     nf = L_add( acc, d ); /* in Q12 and always positive */
     110             :                 }
     111             :                 ELSE
     112             :                 {
     113      131168 :                     acc = L_sub( nf, d );
     114      131168 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     115      131168 :                     nf = L_add( acc, d ); /* in Q12 always positive */
     116             :                 }
     117      518751 :                 nf_mean = L_add( nf_mean, nf ); /* in Q12 and always positive */
     118      518751 :                 nf_cnt = add( nf_cnt, 1 );      /* Q0 */
     119             :             }
     120             : 
     121      549664 :             pe_mean = L_add_o( pe_mean, pe, &Overflow ); /* in Q12 and always positive */
     122             :         }
     123             : 
     124        2926 :         IF( pe_mean > 0 )
     125             :         {
     126        2926 :             expPeMean = norm_l( pe_mean );                        /* exponent */
     127        2926 :             manPeMean = extract_h( L_shl( pe_mean, expPeMean ) ); /* mantissa */
     128        2926 :             expNfMean = norm_l( nf_mean );                        /* exponent */
     129        2926 :             manNfMean = extract_h( L_shl( nf_mean, expNfMean ) ); /* mantissa */
     130             : 
     131        2926 :             numerator = L_mult0( manNfMean, n );
     132        2926 :             IF( nf_cnt > 0 )
     133             :             {
     134        2926 :                 denominator = L_mult0( manPeMean, nf_cnt ); /* in Q15 */
     135             :             }
     136             :             ELSE
     137             :             {
     138           0 :                 denominator = L_mult0( manPeMean, 1 ); /* in Q15 */
     139             :             }
     140        2926 :             manNfpe = ratio( numerator, denominator, &expo ); /* manNfpe in Q14 */
     141        2926 :             expNfpe = add( sub( expNfMean, expPeMean ), expo );
     142             : 
     143        2926 :             tmp16 = mult_r( manNfpe, manNfpe );             /* in Q(14+14+1-16) = Q13 */
     144        2926 :             tmp16 = mult_r( tmp16, manNfpe );               /* in Q(13+14+1-16) = Q12 */
     145        2926 :             acc = L_mult( tmp16, HVQ_NFPE_FACTOR_CUBE_FX ); /* in Q(12+6+1) = Q19 */
     146        2926 :             expNfpe3 = extract_l( L_mult0( expNfpe, 3 ) );  /* Cube operation */
     147             :             /* Number of bits required to adjust to Q15 */
     148        2926 :             adjust = add( 19 - ( 15 + 16 ), expNfpe3 );                      /* +16 is due to the following extract_h(). */
     149        2926 :             noise_level[i] = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */
     150        2926 :             move16();
     151        2926 :             q_noise_level_idx[i] = quant_lc_fx( noise_level[i], &q_noise_level[i] );
     152        2926 :             move16();
     153             :         }
     154             :         ELSE
     155             :         {
     156           0 :             q_noise_level_idx[i] = 0;
     157           0 :             move16();
     158           0 :             q_noise_level[i] = 0;
     159           0 :             move16();
     160             :         }
     161        2926 :         push_indice( st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 );
     162        2926 :         bits_used = add( bits_used, 2 );
     163             : 
     164        2926 :         noise_level[i] = q_noise_level[i]; /* in Q15 */
     165        2926 :         move16();
     166             :     }
     167             : 
     168        4389 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     169             :     {
     170        2926 :         IF( pe_gains[i] != 0 )
     171             :         {
     172             :             /* Neither pe_gains[] nor nf_gains[] is zero. */
     173        2926 :             man = ratio( nf_gains[i], pe_gains[i], &expo );    /* man in Q14 */
     174        2926 :             tmp16 = mult_r( man, man );                        /* in Q(14+14+1-16) = Q13 */
     175        2926 :             tmp16 = mult_r( tmp16, man );                      /* in Q(13+14+1-16) = Q12 */
     176        2926 :             acc = L_mult( tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX ); /* in Q(12+9+1) = Q22 */
     177        2926 :             expo3 = extract_l( L_mult0( expo, 3 ) );           /* Cube operation. */
     178             :             /* Number of bits required to adjust to Q15 */
     179        2926 :             adjust = add( 22 - ( 15 + 16 ), expo3 );                  /* +16 is due to the following extract_h(). */
     180        2926 :             lb_nfpe = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */
     181        2926 :             IF( GT_16( lb_nfpe, 16384 ) )                             /* in Q15 */
     182             :             {
     183         141 :                 lb_nfpe = 16384;
     184         141 :                 move16();
     185             :             }
     186        2926 :             Mpy_32_16_ss( nf_gains[i], shl_o( lb_nfpe, 1, &Overflow ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */
     187             :         }
     188             :         ELSE
     189             :         {
     190           0 :             nf_gains[i] = 0;
     191           0 :             move16();
     192             :         }
     193             :     }
     194        1463 :     nBits = peak_vq_enc_ivas_fx( st_fx->hBstr, st_fx->bwidth, coefs, coefs_out, core_brate, sub( hvq_bits, bits_used ),
     195             :                                  Npeaks, ynrm, R, peaks, &nf_gains[0] );
     196        1463 :     bits_used = add( bits_used, nBits );
     197        1463 :     return bits_used;
     198             : }
     199             : 
     200           0 : Word16 hvq_enc_fx(                          /*o  : Consumed bits                            */
     201             :                    Encoder_State *st_fx,    /*i/o: encoder state structure                  */
     202             :                    const Word32 core_brate, /*i  : Total bit rate                           */
     203             :                    const Word16 hvq_bits,   /*i  : HVQ bit budget                           */
     204             :                    const Word16 Npeaks,     /*i  : Number of peaks                          */
     205             :                    const Word16 *ynrm,      /* i  : Envelope coefficients                   */
     206             :                    Word16 *R,               /* i/o: Bit allocation/updated bit allocation   */
     207             :                    Word16 *peaks,           /* i  : Peak pos. / Encoded peak pos.           */
     208             :                    Word32 *nf_gains,        /* i/o: Noise fill gains / Quant. nf gains      */
     209             :                    Word16 *noise_level,     /* o  : Quantized noise level                   */
     210             :                    const Word32 *pe_gains,  /* i  : Peak gains                              */
     211             :                    const Word32 *coefs,     /* i  : spectrum coefficients in Q12            */
     212             :                    Word32 *coefs_out        /* o  : encoded spectrum coefficients in Q12    */
     213             : )
     214             : {
     215             :     const Word32 *pCoefs;
     216             :     Word16 bin_th, j, i, n;
     217             :     Word16 nf_cnt;
     218             :     Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS];
     219             :     Word16 q_noise_level[HVQ_BWE_NOISE_BANDS];
     220             :     Word32 d, nf_mean;
     221             :     Word32 nf, pe, pe_mean;
     222             :     Word16 bits_used, nBits;
     223             :     Word16 lb_nfpe;
     224             :     UWord16 dontCare;
     225             :     Word32 acc, numerator, denominator;
     226             :     Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3;
     227             :     Word16 manPeMean, manNfMean, manNfpe, man;
     228             :     Word16 tmp16, adjust;
     229             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     230           0 :     Flag Overflow = 0;
     231           0 :     move32();
     232             : #endif
     233           0 :     bits_used = 0;
     234           0 :     move16();
     235             : 
     236           0 :     IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) )
     237             :     {
     238           0 :         bin_th = HVQ_THRES_BIN_24k;
     239           0 :         move16();
     240           0 :         n = ( L_FRAME32k - HVQ_THRES_BIN_24k ) / HVQ_BWE_NOISE_BANDS;
     241           0 :         move16();
     242             :     }
     243             :     ELSE
     244             :     {
     245           0 :         bin_th = HVQ_THRES_BIN_32k;
     246           0 :         move16();
     247           0 :         n = ( L_FRAME32k - HVQ_THRES_BIN_32k ) / HVQ_BWE_NOISE_BANDS;
     248           0 :         move16();
     249             :     }
     250             : 
     251           0 :     nf = 800 * 4096L; /* Q12 */
     252           0 :     move32();
     253           0 :     pe = 800 * 4096L; /* Q12 */
     254           0 :     move32();
     255           0 :     pCoefs = &coefs[bin_th];
     256             : 
     257             :     /* Find HB noise level */
     258           0 :     FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ )
     259             :     {
     260           0 :         nf_cnt = 0;
     261           0 :         move16();
     262           0 :         nf_mean = L_deposit_l( 0 );
     263           0 :         pe_mean = L_deposit_l( 0 );
     264           0 :         FOR( j = 0; j < n; j++ )
     265             :         {
     266           0 :             d = L_abs( *pCoefs++ ); /* Q12 */
     267             : 
     268           0 :             IF( GT_32( d, pe ) )
     269             :             {
     270             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
     271           0 :                 acc = L_sub( pe, d );
     272           0 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     273           0 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     274             :             }
     275             :             ELSE
     276             :             {
     277             :                 /* W*pe + (1 - W)*d = (pe - d)*W + d */
     278           0 :                 acc = L_sub( pe, d );
     279           0 :                 Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     280           0 :                 pe = L_add( acc, d ); /* in Q12 and always positive */
     281             : 
     282           0 :                 IF( GT_32( d, nf ) )
     283             :                 {
     284           0 :                     acc = L_sub( nf, d );
     285           0 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare );
     286           0 :                     nf = L_add( acc, d ); /* in Q12 and always positive */
     287             :                 }
     288             :                 ELSE
     289             :                 {
     290           0 :                     acc = L_sub( nf, d );
     291           0 :                     Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare );
     292           0 :                     nf = L_add( acc, d ); /* in Q12 always positive */
     293             :                 }
     294           0 :                 nf_mean = L_add( nf_mean, nf ); /* in Q12 and always positive */
     295           0 :                 nf_cnt = add( nf_cnt, 1 );      /* Q0 */
     296             :             }
     297             : 
     298           0 :             pe_mean = L_add_o( pe_mean, pe, &Overflow ); /* in Q12 and always positive */
     299             :         }
     300             : 
     301           0 :         IF( pe_mean > 0 )
     302             :         {
     303           0 :             expPeMean = norm_l( pe_mean );                        /* exponent */
     304           0 :             manPeMean = extract_h( L_shl( pe_mean, expPeMean ) ); /* mantissa */
     305           0 :             expNfMean = norm_l( nf_mean );                        /* exponent */
     306           0 :             manNfMean = extract_h( L_shl( nf_mean, expNfMean ) ); /* mantissa */
     307             : 
     308           0 :             numerator = L_mult0( manNfMean, n );
     309           0 :             IF( nf_cnt > 0 )
     310             :             {
     311           0 :                 denominator = L_mult0( manPeMean, nf_cnt ); /* in Q15 */
     312             :             }
     313             :             ELSE
     314             :             {
     315           0 :                 denominator = L_mult0( manPeMean, 1 ); /* in Q15 */
     316             :             }
     317           0 :             manNfpe = ratio( numerator, denominator, &expo ); /* manNfpe in Q14 */
     318           0 :             expNfpe = add( sub( expNfMean, expPeMean ), expo );
     319             : 
     320           0 :             tmp16 = mult_r( manNfpe, manNfpe );             /* in Q(14+14+1-16) = Q13 */
     321           0 :             tmp16 = mult_r( tmp16, manNfpe );               /* in Q(13+14+1-16) = Q12 */
     322           0 :             acc = L_mult( tmp16, HVQ_NFPE_FACTOR_CUBE_FX ); /* in Q(12+6+1) = Q19 */
     323           0 :             expNfpe3 = extract_l( L_mult0( expNfpe, 3 ) );  /* Cube operation */
     324             :             /* Number of bits required to adjust to Q15 */
     325           0 :             adjust = add( 19 - ( 15 + 16 ), expNfpe3 );                      /* +16 is due to the following extract_h(). */
     326           0 :             noise_level[i] = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */
     327           0 :             move16();
     328           0 :             q_noise_level_idx[i] = quant_lc_fx( noise_level[i], &q_noise_level[i] );
     329           0 :             move16();
     330             :         }
     331             :         ELSE
     332             :         {
     333           0 :             q_noise_level_idx[i] = 0;
     334           0 :             move16();
     335           0 :             q_noise_level[i] = 0;
     336           0 :             move16();
     337             :         }
     338           0 :         push_indice( st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 );
     339           0 :         bits_used = add( bits_used, 2 );
     340             : 
     341           0 :         noise_level[i] = q_noise_level[i]; /* in Q15 */
     342           0 :         move16();
     343             :     }
     344             : 
     345           0 :     FOR( i = 0; i < HVQ_NF_GROUPS; i++ )
     346             :     {
     347           0 :         IF( pe_gains[i] != 0 )
     348             :         {
     349             :             /* Neither pe_gains[] nor nf_gains[] is zero. */
     350           0 :             man = ratio( nf_gains[i], pe_gains[i], &expo );    /* man in Q14 */
     351           0 :             tmp16 = mult_r( man, man );                        /* in Q(14+14+1-16) = Q13 */
     352           0 :             tmp16 = mult_r( tmp16, man );                      /* in Q(13+14+1-16) = Q12 */
     353           0 :             acc = L_mult( tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX ); /* in Q(12+9+1) = Q22 */
     354           0 :             expo3 = extract_l( L_mult0( expo, 3 ) );           /* Cube operation. */
     355             :             /* Number of bits required to adjust to Q15 */
     356           0 :             adjust = add( 22 - ( 15 + 16 ), expo3 );                  /* +16 is due to the following extract_h(). */
     357           0 :             lb_nfpe = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */
     358           0 :             IF( lb_nfpe > 16384 )                                     /* in Q15 */
     359             :             {
     360           0 :                 lb_nfpe = 16384;
     361           0 :                 move16();
     362             :             }
     363           0 :             Mpy_32_16_ss( nf_gains[i], shl_o( lb_nfpe, 1, &Overflow ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */
     364             :         }
     365             :         ELSE
     366             :         {
     367           0 :             nf_gains[i] = 0;
     368           0 :             move16();
     369             :         }
     370             :     }
     371           0 :     nBits = peak_vq_enc_fx( st_fx->hBstr, st_fx->bwidth, coefs, coefs_out, core_brate, sub( hvq_bits, bits_used ),
     372             :                             Npeaks, ynrm, R, peaks, &nf_gains[0] );
     373           0 :     move16();
     374           0 :     bits_used = add( bits_used, nBits );
     375           0 :     return bits_used;
     376             : }
     377             : 
     378             : /*-----------------------------------------------------------------------------
     379             :  * quant()
     380             :  *
     381             :  * Quantize the noise to one of the levels in {0, 0.1, 0.2, 0.3}
     382             :  *----------------------------------------------------------------------------*/
     383        2926 : static Word16 quant_lc_fx( const Word16 x, Word16 *qx )
     384             : {
     385             :     Word16 indx;
     386             : 
     387        2926 :     IF( LT_16( x, HVQ_ENC_NOISE_DELTA / 2 ) )
     388             :     {
     389        2255 :         indx = 0;
     390        2255 :         move16();
     391        2255 :         *qx = 0;
     392        2255 :         move16();
     393             :     }
     394         671 :     ELSE IF( LT_16( x, 3 * HVQ_ENC_NOISE_DELTA / 2 ) )
     395             :     {
     396         226 :         indx = 1;
     397         226 :         move16();
     398         226 :         *qx = HVQ_ENC_NOISE_DELTA;
     399         226 :         move16();
     400             :     }
     401         445 :     ELSE IF( LT_16( x, 5 * HVQ_ENC_NOISE_DELTA / 2 ) )
     402             :     {
     403         145 :         indx = 2;
     404         145 :         move16();
     405         145 :         *qx = 2 * HVQ_ENC_NOISE_DELTA;
     406         145 :         move16();
     407             :     }
     408             :     ELSE
     409             :     {
     410         300 :         indx = 3;
     411         300 :         move16();
     412         300 :         *qx = 3 * HVQ_ENC_NOISE_DELTA;
     413         300 :         move16();
     414             :     }
     415             : 
     416        2926 :     return indx;
     417             : }

Generated by: LCOV version 1.14