LCOV - code coverage report
Current view: top level - lib_com - est_tilt_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 124 129 96.1 %
Date: 2025-05-03 01:55:50 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include "options.h" /* Compilation switches                   */
       6             : #include "cnst.h"    /* Common constants                       */
       7             : #include "prot_fx.h" /* Function prototypes                    */
       8             : #include "stl.h"
       9             : #include "basop_util.h"
      10             : 
      11             : 
      12             : /*======================================================================*/
      13             : /* FUNCTION : est_tilt_fx()                                                                                             */
      14             : /*-----------------------------------------------------------------------*/
      15             : /* PURPOSE :  Estimate spectral tilt based on the relative E of adaptive */
      16             : /* and innovative excitations                                            */
      17             : /*                                                                       */
      18             : /*-----------------------------------------------------------------------*/
      19             : /*  INPUT ARGUMENTS :                                                                                                    */
      20             : /* _ (Word16 *) exc :  adaptive excitation vector      Q0                */
      21             : /* _ (Word16) gain_pit : adaptive gain                 Q14               */
      22             : /* _ (Word16 *) code : algebraic exctitation vector    Q12               */
      23             : /* _ (Word32) gain_code :  algebraic code gain         Q16               */
      24             : /* _ (Word16) Q_exc : Scaling factor of excitation     Q0                */
      25             : /*-----------------------------------------------------------------------*/
      26             : /* OUTPUT ARGUMENTS :                                                    */
      27             : /* _ (Word16 *) voice_fac :   voicing factor          Q15                */
      28             : /*-----------------------------------------------------------------------*/
      29             : /* INPUT OUTPUT ARGUMENTS                                                */
      30             : /*-----------------------------------------------------------------------*/
      31             : 
      32             : /*-----------------------------------------------------------------------*/
      33             : /* RETURN ARGUMENTS :                                                    */
      34             : /* _ (Word16) tolt_code :  tilt of the code           Q15                */
      35             : /*=======================================================================*/
      36         559 : Word16 est_tilt_fx(                         /* o  : tilt of the code              Q15      */
      37             :                     const Word16 *exc,      /* i  : adaptive excitation vector      Qx  */
      38             :                     const Word16 gain_pit,  /* i  : adaptive gain                   Q14 */
      39             :                     const Word16 *code,     /* i  : algebraic excitation vector    Q9  */
      40             :                     const Word32 gain_code, /* i  : algebraic code gain             Q16 */
      41             :                     Word16 *voice_fac,      /* o  : voicing factor                  Q15 */
      42             :                     const Word16 Q_exc      /* i  : Scaling factor of excitation    Q0  */
      43             : )
      44             : {
      45             :     Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
      46             :     Word32 L_tmp;
      47             :     Word16 tilt_code;
      48             : 
      49         559 :     ener1 = extract_h( Dot_product12( exc, exc, L_SUBFR, &exp1 ) );
      50         559 :     exp1 = sub( exp1, add( Q_exc, Q_exc ) );
      51         559 :     L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
      52         559 :     exp = norm_l( L_tmp );
      53         559 :     tmp = extract_h( L_shl( L_tmp, exp ) );
      54         559 :     ener1 = mult( ener1, tmp );
      55         559 :     exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9   */
      56             : 
      57         559 :     ener2 = extract_h( Dot_product12( code, code, L_SUBFR, &exp2 ) );
      58             : 
      59         559 :     exp = norm_l( gain_code );
      60         559 :     tmp = extract_h( L_shl( gain_code, exp ) );
      61         559 :     tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
      62         559 :     ener2 = mult( ener2, tmp );
      63         559 :     exp2 = sub( exp2, add( exp, exp ) );
      64             : 
      65         559 :     i = sub( exp1, exp2 );
      66             :     BASOP_SATURATE_WARNING_OFF_EVS
      67         559 :     ener1 = shr_sat( ener1, sub( 1, s_min( i, 0 ) ) );
      68         559 :     ener2 = shr_sat( ener2, add( s_max( 0, i ), 1 ) );
      69             :     BASOP_SATURATE_WARNING_ON_EVS
      70         559 :     tmp = sub( ener1, ener2 );
      71         559 :     ener1 = add( add( ener1, ener2 ), 1 );
      72             : 
      73             :     /* find voice factor (1=voiced, -1=unvoiced) */
      74         559 :     exp = div_s( abs_s( tmp ), ener1 );
      75         559 :     if ( tmp < 0 )
      76             :     {
      77         309 :         exp = negate( exp );
      78             :     }
      79         559 :     *voice_fac = exp;
      80         559 :     move16();
      81             : 
      82             :     /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
      83             : 
      84             :     /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
      85         559 :     tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ ); /*Q15 */
      86             : 
      87         559 :     return tilt_code;
      88             : }
      89             : 
      90             : /*======================================================================*/
      91             : /* FUNCTION : est_tilt_ivas_fx()                                                                                                */
      92             : /*-----------------------------------------------------------------------*/
      93             : /* PURPOSE :  Estimate spectral tilt based on the relative E of adaptive */
      94             : /* and innovative excitations                                            */
      95             : /*                                                                       */
      96             : /*-----------------------------------------------------------------------*/
      97             : /*  INPUT ARGUMENTS :                                                                                                    */
      98             : /* _ (Word16 *) exc :  adaptive excitation vector      Q0                */
      99             : /* _ (Word16) gain_pit : adaptive gain                 Q14               */
     100             : /* _ (Word16 *) code : algebraic exctitation vector    Q12               */
     101             : /* _ (Word32) gain_code :  algebraic code gain         Q16               */
     102             : /* _ (Word16) Q_exc : Scaling factor of excitation     Q0                */
     103             : /*-----------------------------------------------------------------------*/
     104             : /* OUTPUT ARGUMENTS :                                                    */
     105             : /* _ (Word16 *) voice_fac :   voicing factor          Q15                */
     106             : /*-----------------------------------------------------------------------*/
     107             : /* INPUT OUTPUT ARGUMENTS                                                */
     108             : /*-----------------------------------------------------------------------*/
     109             : 
     110             : /*-----------------------------------------------------------------------*/
     111             : /* RETURN ARGUMENTS :                                                    */
     112             : /* _ (Word16) tolt_code :  tilt of the code           Q15                */
     113             : /*=======================================================================*/
     114             : 
     115             : /* o  : tilt of the code Q15 */
     116     1150836 : Word16 est_tilt_ivas_fx(
     117             :     const Word16 *exc,      /* i  : adaptive excitation vector      Qx  */
     118             :     const Word16 gain_pit,  /* i  : adaptive gain                   Q14 */
     119             :     const Word16 *code,     /* i  : algebraic excitation vector    Q9  */
     120             :     const Word32 gain_code, /* i  : algebraic code gain             Q16 */
     121             :     Word16 *voice_fac,      /* o  : voicing factor                  Q15 */
     122             :     const Word16 Q_exc,     /* i  : Scaling factor of excitation    Q0  */
     123             :     const Word16 L_subfr,   /* i  : Sub frame length                    */
     124             :     const Word16 flag_tilt  /* i  : flag for special tilt        */
     125             : )
     126             : {
     127             :     Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
     128             :     Word32 L_tmp;
     129             :     Word16 tilt_code;
     130             : 
     131     1150836 :     ener1 = extract_h( Dot_product12( exc, exc, L_subfr, &exp1 ) );
     132     1150836 :     exp1 = sub( exp1, add( Q_exc, Q_exc ) );
     133     1150836 :     L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
     134     1150836 :     exp = norm_l( L_tmp );
     135     1150836 :     tmp = extract_h( L_shl( L_tmp, exp ) );
     136     1150836 :     ener1 = mult( ener1, tmp );
     137     1150836 :     exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9   */
     138             : 
     139     1150836 :     ener2 = extract_h( Dot_product12( code, code, L_subfr, &exp2 ) );
     140             : 
     141     1150836 :     exp = norm_l( gain_code );
     142     1150836 :     tmp = extract_h( L_shl( gain_code, exp ) );
     143     1150836 :     tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
     144     1150836 :     ener2 = mult( ener2, tmp );
     145     1150836 :     exp2 = sub( exp2, add( exp, exp ) );
     146             : 
     147     1150836 :     i = sub( exp1, exp2 );
     148             :     BASOP_SATURATE_WARNING_OFF_EVS
     149     1150836 :     ener1 = shr_sat( ener1, sub( 1, s_min( i, 0 ) ) );
     150     1150836 :     ener2 = shr_sat( ener2, add( s_max( 0, i ), 1 ) );
     151             :     BASOP_SATURATE_WARNING_ON_EVS
     152     1150836 :     tmp = sub( ener1, ener2 );
     153     1150836 :     ener1 = add( add( ener1, ener2 ), 1 );
     154             : 
     155             :     /* find voice factor (1=voiced, -1=unvoiced) */
     156     1150836 :     exp = div_s( abs_s( tmp ), ener1 );
     157     1150836 :     IF( tmp < 0 )
     158             :     {
     159      811336 :         exp = negate( exp );
     160             :     }
     161     1150836 :     *voice_fac = exp;
     162     1150836 :     move16();
     163             : 
     164     1150836 :     IF( flag_tilt == 0 )
     165             :     {
     166             :         /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
     167             : 
     168             :         /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
     169     1150836 :         tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ ); /*Q15 */
     170             :     }
     171           0 :     ELSE IF( EQ_16( flag_tilt, 1 ) )
     172             :     {
     173             :         /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
     174             :         // tilt_code = (float)(0.25f + (*voice_fac + 1.0f) * 0.125f);
     175           0 :         tilt_code = mac_r( 12288L /*0.375.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 4096 /*0.125.Q15*/ ); /*Q15 */
     176             :     }
     177             :     ELSE
     178             :     {
     179             :         /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
     180             :         // tilt_code = (float)(0.28f + (*voice_fac + 1.0f) * 0.14f);
     181           0 :         tilt_code = mac_r( 13763L /*0.42.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 4588 /*0.14.Q15*/ ); /*Q15 */
     182             :     }
     183             : 
     184     1150836 :     return tilt_code;
     185             : }
     186             : 
     187             : /*-------------------------------------------------------------------*
     188             :  * Est_tilt2:
     189             :  *
     190             :  * Estimate spectral tilt based on the relative E of adaptive
     191             :  * and innovative excitations
     192             :  *-------------------------------------------------------------------*/
     193        6376 : Word16 Est_tilt2(                         /* o  : tilt of the code                    */
     194             :                   const Word16 *exc,      /* i  : adaptive excitation vector      Qx  */
     195             :                   const Word16 gain_pit,  /* i  : adaptive gain                   Q14 */
     196             :                   const Word16 *code,     /* i  : algebraic exctitation vector    Q9  */
     197             :                   const Word32 gain_code, /* i  : algebraic code gain             Q16 */
     198             :                   Word16 *voice_fac,      /* o  : voicing factor                  Q15 */
     199             :                   const Word16 Q_exc      /* i  : Scaling factor of excitation    Q0  */
     200             : )
     201             : {
     202             :     Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
     203             :     Word32 L_tmp;
     204             :     Word16 tilt_code;
     205             : 
     206             :     /* Scale exc to avoid overflow */
     207        6376 :     ener1 = extract_h( Energy_scale( exc, L_SUBFR, Q_exc, &exp1 ) );
     208             : 
     209        6376 :     exp1 = sub( exp1, add( Q_exc, Q_exc ) );
     210        6376 :     L_tmp = L_mult( gain_pit, gain_pit ); /* energy of pitch excitation */
     211        6376 :     exp = norm_l( L_tmp );
     212        6376 :     tmp = extract_h( L_shl( L_tmp, exp ) );
     213        6376 :     ener1 = mult( ener1, tmp );
     214        6376 :     exp1 = sub( sub( exp1, exp ), 10 ); /* 10 -> gain_pit Q14 to Q9   */
     215             : 
     216        6376 :     ener2 = extract_h( Dot_product12( code, code, L_SUBFR, &exp2 ) );
     217             : 
     218        6376 :     exp = norm_l( gain_code );
     219        6376 :     tmp = extract_h( L_shl( gain_code, exp ) );
     220        6376 :     tmp = mult( tmp, tmp ); /* energy of innovative code excitation */
     221        6376 :     ener2 = mult( ener2, tmp );
     222        6376 :     exp2 = sub( exp2, add( exp, exp ) );
     223             : 
     224        6376 :     i = sub( exp1, exp2 );
     225        6376 :     ener1 = shr( ener1, sub( 1, s_min( i, 0 ) ) );
     226        6376 :     ener2 = shr( ener2, add( s_max( 0, i ), 1 ) );
     227             : 
     228        6376 :     tmp = sub( ener1, ener2 );
     229        6376 :     ener1 = add( add( ener1, ener2 ), 1 );
     230             : 
     231             :     /* find voice factor (1=voiced, -1=unvoiced) */
     232        6376 :     exp = div_s( abs_s( tmp ), ener1 );
     233        6376 :     IF( tmp < 0 )
     234             :     {
     235        2584 :         exp = negate( exp );
     236             :     }
     237        6376 :     *voice_fac = exp;
     238        6376 :     move16();
     239             : 
     240             :     /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
     241             : 
     242             :     /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
     243        6376 :     tilt_code = mac_r( 8192L /*0.25.Q15*/ * 65536 /*1.Q16*/ - 0x8000 /*1.Q15*/, *voice_fac, 8192 /*0.25.Q15*/ );
     244             : 
     245        6376 :     return tilt_code;
     246             : }
     247             : 
     248             : /*---------------------------------------------------------*
     249             :  * Find voice factor and tilt code                         *
     250             :  *---------------------------------------------------------*/
     251       14070 : void E_UTIL_voice_factor( Word16 *exc,       /* i  : pointer to the excitation frame   Q_new */
     252             :                           Word16 i_subfr,    /* i  : subframe index                          */
     253             :                           Word16 *code,      /* i  : innovative codebook                  Q9 */
     254             :                           Word16 gain_pit,   /* i  : adaptive codebook gain             1Q14 */
     255             :                           Word32 gain_code,  /* i  : innovative cb. gain               15Q16 */
     256             :                           Word16 *voice_fac, /* o  : subframe voicing estimation         Q15 */
     257             :                           Word16 *tilt_code, /* o  : tilt factor                         Q15 */
     258             :                           Word16 L_subfr,    /* i  : subframe length                         */
     259             :                           Word16 flag_tilt,  /* i  : Flag for triggering new voice factor tilt*/
     260             :                           Word16 Q_new,      /* i  : excitation buffer format                 */
     261             :                           Word16 shift       /* i  : scaling to get 12bit                     */
     262             : )
     263             : {
     264             :     Word16 i, e, e2, stmp, exp_ener, fac;
     265             :     Word32 ener, tmp, num;
     266             :     Word64 ener_64;
     267             : 
     268             :     BASOP_SATURATE_ERROR_ON_EVS;
     269             : 
     270             : 
     271       14070 :     IF( shift != 0 )
     272             :     {
     273        1865 :         fac = shl( 0x4000 /*1.Q14*/, add( 1, shift ) );
     274             :         /* energy of pitch excitation */
     275        1865 :         stmp = mult_r( exc[0 + i_subfr], fac ); /* remove fac bits */
     276        1865 :         ener_64 = W_mult0_16_16( stmp, stmp );
     277      119360 :         FOR( i = 1; i < L_subfr; i++ )
     278             :         {
     279      117495 :             stmp = mult_r( exc[i + i_subfr], fac ); /* remove fac bits */
     280      117495 :             ener_64 = W_mac0_16_16( ener_64, stmp, stmp );
     281             :         }
     282             :     }
     283             :     ELSE
     284             :     {
     285       12205 :         ener_64 = W_mult0_16_16( exc[0 + i_subfr], exc[0 + i_subfr] );
     286      781120 :         FOR( i = 1; i < L_subfr; i++ )
     287             :         {
     288      768915 :             ener_64 = W_mac0_16_16( ener_64, exc[i + i_subfr], exc[i + i_subfr] ); /* Q_new -> exponent = (15-Q_new)*2+1  */
     289             :         }
     290             :     }
     291       14070 :     ener = W_sat_l( ener_64 );
     292             : 
     293             : 
     294             :     /* exponent of ener: (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) */
     295       14070 :     exp_ener = norm_l( ener );
     296       14070 :     if ( ener == 0 )
     297             :     {
     298        8014 :         exp_ener = 31;
     299        8014 :         move16();
     300             :     }
     301       14070 :     ener = L_shl( ener, exp_ener );
     302       14070 :     e2 = norm_s( gain_pit );
     303       14070 :     gain_pit = shl( gain_pit, e2 );
     304       14070 :     ener = Mpy_32_16_1( ener, mult_r( gain_pit, gain_pit ) );
     305             : 
     306             : 
     307             :     /* energy of innovative code excitation */
     308       14070 :     tmp = L_deposit_l( 1 );
     309             : 
     310      914550 :     FOR( i = 0; i < L_subfr; i++ )
     311             :     {
     312      900480 :         tmp = L_mac0( tmp, code[i], code[i] ); /* 6Q9 -> 13Q18 */
     313             :     }
     314             :     /* exponent of tmp: 2*(15-9)+1+2*(15-e))  */
     315       14070 :     e = norm_l( gain_code );
     316       14070 :     gain_code = L_shl( gain_code, e );
     317       14070 :     tmp = Mpy_32_32( tmp, Mpy_32_32( gain_code, gain_code ) );
     318             : 
     319             :     /* find voice factor (1=voiced, -1=unvoiced) */
     320             :     /*i = (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) - (2*(15-9)+1 + 2*(15-e));*/
     321       14070 :     i = sub( sub( sub( sub( sub( 33, add( shift, shift ) ), add( Q_new, Q_new ) ), exp_ener ), add( e2, e2 ) ), sub( 43, add( e, e ) ) );
     322       14070 :     IF( i >= 0 )
     323             :     {
     324           0 :         ener = L_shr( ener, 1 );
     325           0 :         tmp = L_shr_sat( tmp, add( 1, i ) );
     326             :     }
     327             :     ELSE
     328             :     {
     329       14070 :         tmp = L_shr( tmp, 1 );
     330             :         BASOP_SATURATE_WARNING_OFF_EVS
     331       14070 :         ener = L_shr_sat( ener, sub( 1, i ) );
     332             :         BASOP_SATURATE_WARNING_ON_EVS
     333             :     }
     334             : 
     335       14070 :     *voice_fac = 0;
     336       14070 :     move16();
     337       14070 :     num = L_sub( ener, tmp );
     338       14070 :     IF( num != 0 )
     339             :     {
     340             :         BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturating the voice factor because if has a limited range by definition. */
     341       14070 :             *voice_fac = divide3232( num, L_add( ener, tmp ) );
     342       14070 :         move16();
     343             :         BASOP_SATURATE_WARNING_ON_EVS
     344             :     }
     345             : 
     346             :     /* find tilt of code for next subframe */
     347       14070 :     IF( flag_tilt == 0 )
     348             :     {
     349             :         /*Between 0 (=unvoiced) and 0.5 (=voiced)*/
     350        2672 :         move16();
     351        2672 :         *tilt_code = add( 8192 /*0.25f Q15*/, mult_r( 8192 /*0.25f Q15*/, *voice_fac ) );
     352             :     }
     353       11398 :     ELSE IF( EQ_16( flag_tilt, 1 ) )
     354             :     {
     355             :         /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
     356        5028 :         move16();
     357        5028 :         *tilt_code = add( mult_r( 4096 /*0.125f Q15*/, *voice_fac ), 12288 /*0.125f+0.25f Q15*/ );
     358             :     }
     359             :     ELSE
     360             :     {
     361             :         /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
     362        6370 :         move16();
     363        6370 :         *tilt_code = add( mult_r( 4588 /*0.14f Q15*/, *voice_fac ), 13763 /*0.14f+0.28f Q15*/ );
     364             :     }
     365             :     BASOP_SATURATE_ERROR_OFF_EVS;
     366       14070 : }

Generated by: LCOV version 1.14