LCOV - code coverage report
Current view: top level - lib_com - frame_ener_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 89 110 80.9 %
Date: 2025-08-23 01:22:27 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <stdint.h>
      38             : #include "options.h"
      39             : #include <math.h>
      40             : #include "cnst.h"
      41             : #include "prot_fx.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : /*----------------------------------------------------------------------------------*
      45             :  * fer_energy()
      46             :  *
      47             :  * Estimation of pitch-synchronous (voiced sounds) or half-frame energy
      48             :  *----------------------------------------------------------------------------------*/
      49             : 
      50        8327 : void fer_energy_fx(
      51             :     const Word16 L_frame, /* i  : frame length                                      */
      52             :     const Word16 clas,    /* i  : frame classification                              */
      53             :     const Word32 *synth,  /* i  : synthesized speech at Fs = 12k8 Hz     Q(q_synth) */
      54             :     const Word16 q_synth, /* i  : synthesized speech at Fs = 12k8 Hz                */
      55             :     const Word16 pitch,   /* i  : pitch period                           Q0         */
      56             :     Word32 *enr,          /* o  : pitch-synchronous or half_frame energy Q0         */
      57             :     const Word16 offset   /* i  : speech pointer offset (0 or L_frame)              */
      58             : )
      59             : {
      60             :     Word16 len, shift, exp;
      61             :     const Word32 *pt_synth;
      62             :     Word16 enr_tmp, i;
      63             :     Word64 W_tmp;
      64             : 
      65        8327 :     test();
      66        8327 :     test();
      67        8327 :     IF( EQ_16( clas, VOICED_CLAS ) || EQ_16( clas, ONSET ) || EQ_16( clas, SIN_ONSET ) ) /* Voiced or Onset current frame */
      68             :     {
      69           0 :         len = ( pitch ); /* pitch value */
      70           0 :         move16();
      71             : 
      72           0 :         pt_synth = synth;
      73           0 :         IF( offset != 0 )
      74             :         {
      75           0 :             pt_synth = synth + sub( L_frame, len );
      76             :         }
      77             : 
      78           0 :         emaximum_32fx( q_synth, pt_synth, len, enr ); /* pitch synchronous E */
      79             :     }
      80             :     ELSE
      81             :     {
      82        8327 :         pt_synth = synth;
      83        8327 :         IF( offset != 0 )
      84             :         {
      85        8327 :             pt_synth = synth + shr( L_frame, 1 );
      86             :         }
      87             : 
      88        8327 :         W_tmp = 0;
      89        8327 :         move64();
      90     3513447 :         FOR( i = 0; i < L_frame / 2; i++ )
      91             :         {
      92     3505120 :             W_tmp = W_add( W_tmp, W_mult0_32_32( pt_synth[i], pt_synth[i] ) ); // Q = q_synth * 2
      93             :         }
      94        8327 :         shift = W_norm( W_tmp );
      95        8327 :         W_tmp = W_shl( W_tmp, shift ); // Q = q_synth * 2 + shift
      96        8327 :         *enr = W_extract_h( W_tmp );   // Q = q_synth * 2 + shift - 32
      97        8327 :         move32();
      98             : 
      99        8327 :         enr_tmp = BASOP_Util_Divide3216_Scale( *enr, shr( L_frame, 1 ) /*Q0*/, &exp );
     100        8327 :         *enr = L_shr( L_deposit_l( enr_tmp ), sub( sub( sub( shift, 32 ), exp ), 1 ) ); /*Q0*/
     101        8327 :         move32();
     102             :     }
     103        8327 :     return;
     104             : }
     105             : 
     106             : /*----------------------------------------------------------------------------------*
     107             :  * frame_ener()
     108             :  *
     109             :  * Estimation of pitch-synchronous (voiced) or mean half-frame (unvoiced) energy
     110             :  *----------------------------------------------------------------------------------*/
     111      239901 : Word16 frame_ener_fx(
     112             :     const Word16 L_frame, /* i  : length of the frame                            */
     113             :     const Word16 clas,    /* i  : frame classification                           */
     114             :     const Word16 *synth,  /* i  : synthesized speech at Fs = 12k8 Hz       Q_new */
     115             :     const Word16 pitch,   /* i  : pitch period                             Q0    */
     116             :     Word32 *enr_q,        /* o  : pitch-synchronous or half_frame energy   Q0    */
     117             :     const Word16 offset,  /* i  : speech pointer offset (0 or L_FRAME)           */
     118             :     const Word16 Q_new,   /* i  : Scaling factor                                 */
     119             :     Word16 shift,         /* i  : Shift need to obtain 12 bits vectors           */
     120             :     const Word16 enc      /* i  : Encoder/decoder                                */
     121             : )
     122             : {
     123             :     Word16 len, exp_enrq, exp_tmp, pos;
     124             :     Word16 i;
     125             :     const Word16 *pt_synth;
     126             :     Word32 Ltmp;
     127             : 
     128      239901 :     exp_enrq = 0;
     129      239901 :     move16();
     130      239901 :     test();
     131      239901 :     test();
     132      239901 :     IF( ( EQ_16( clas, VOICED_CLAS ) ) || ( EQ_16( clas, ONSET ) ) || ( EQ_16( clas, SIN_ONSET ) ) ) /* current frame is voiced */
     133             :     {
     134             :         /* current frame is voiced */
     135       91377 :         len = pitch;
     136       91377 :         move16(); /* pitch value at the end of frame */
     137       91377 :         pt_synth = synth;
     138       91377 :         if ( offset != 0 )
     139             :         {
     140       90409 :             pt_synth = synth + sub( L_frame, len );
     141             :         }
     142       91377 :         emaximum_fx( Q_new, pt_synth, len, enr_q );
     143       91377 :         IF( enc != 0 )
     144             :         {
     145           0 :             exp_enrq = norm_l( *enr_q );
     146           0 :             *enr_q = L_shl( *enr_q, exp_enrq );
     147           0 :             move32();
     148           0 :             exp_enrq = sub( exp_enrq, 2 );
     149             :         }
     150             :     }
     151             :     ELSE
     152             :     {
     153             :         /* current frame is unvoiced */
     154             :         Word16 L_frame2, exp2, enr_q_tmp;
     155             : 
     156      148524 :         L_frame2 = shr( L_frame, 1 );
     157      148524 :         pos = 0;
     158      148524 :         move16();
     159             : 
     160      148524 :         if ( offset != 0 )
     161             :         {
     162      148144 :             pos = sub( L_frame, L_frame2 );
     163             :         }
     164      148524 :         Ltmp = L_mult_sat( synth[pos], synth[pos] ); /*2 * Qnew + 1*/
     165    21452768 :         FOR( i = 1; i < L_frame2; i++ )
     166             :         {
     167    21304244 :             Ltmp = L_mac_sat( Ltmp, synth[pos + i], synth[pos + i] ); /*2 * Qnew + 1*/
     168             :         }
     169      148524 :         test();
     170      148524 :         IF( EQ_32( Ltmp, MAX_32 ) || enc != 0 )
     171             :         {
     172             :             /* scale down when overflow occurs */
     173         315 :             *enr_q = Energy_scale( synth + pos, L_frame2, shift, &exp_enrq );
     174         315 :             move32();
     175             :         }
     176             :         ELSE
     177             :         {
     178      148209 :             shift = 0;
     179      148209 :             move16();
     180             :             /* Normalize acc in Q31 (energy already calculated) */
     181      148209 :             pos = norm_l( Ltmp );
     182      148209 :             Ltmp = L_shl( Ltmp, pos );
     183      148209 :             exp_enrq = sub( 30, pos ); /* exponent = 0..30 */
     184      148209 :             *enr_q = Ltmp;
     185      148209 :             move32();
     186             :         }
     187             : 
     188             :         /* enr2 = 1.0f/L_FRAME2 * dot_product(synth, synth, L_FRAME2) */
     189      148524 :         exp_enrq = sub( exp_enrq, shl( shift, 1 ) );
     190             : 
     191      148524 :         IF( enc != 0 )
     192             :         {
     193           0 :             assert( L_frame == 256 || L_frame == 320 );
     194             : 
     195           0 :             exp_tmp = add( shl( Q_new, 1 ), -2 + 7 ); /*  L_subfr == L_SUBFR */
     196           0 :             exp_enrq = sub( exp_enrq, exp_tmp );
     197           0 :             exp_enrq = sub( 31, exp_enrq );
     198             : 
     199           0 :             IF( EQ_16( L_frame, 320 ) )
     200             :             {
     201           0 :                 *enr_q = Mult_32_16( *enr_q, 26214 ); /*x 0.8 to get /160*/
     202           0 :                 move32();
     203           0 :                 i = norm_l( *enr_q );
     204           0 :                 *enr_q = L_shl( *enr_q, i );
     205           0 :                 move32();
     206           0 :                 exp_enrq = add( i, exp_enrq );
     207             :             }
     208             :         }
     209             :         ELSE
     210             :         {
     211      148524 :             exp_enrq = sub( exp_enrq, add( Q_new, Q_new ) );
     212      148524 :             enr_q_tmp /*Q30 exp2+exp_enrq*/ = BASOP_Util_Divide3216_Scale( *enr_q /*Q31*/, L_frame2 /*Q0*/, &exp2 );
     213      148524 :             *enr_q = L_shr( L_deposit_l( enr_q_tmp ), sub( 30, add( exp2, exp_enrq ) ) ); /*Q0*/
     214      148524 :             move32();
     215      148524 :             *enr_q = L_add( *enr_q, 1 );
     216      148524 :             move32();
     217      148524 :             exp_enrq = 0;
     218      148524 :             move16();
     219             :         }
     220             :     }
     221             : 
     222      239901 :     return exp_enrq;
     223             : }
     224             : 
     225             : /*------------------------------------------------------------------------*
     226             :  * frame_energy()
     227             :  *
     228             :  * Compute pitch-synchronous energy at the frame end
     229             :  *------------------------------------------------------------------------*/
     230      125624 : Word16 frame_energy_fx( /* o  : Frame energy in                               Q8 */
     231             :                         Word16 L_frame,
     232             :                         const Word16 *pitch,    /* i  : pitch values for each subframe                Q6 */
     233             :                         const Word16 *speech,   /* i  : pointer to speech signal for E computation  Q_syn*/
     234             :                         const Word16 lp_speech, /* i  : long term active speech energy average      Q8   */
     235             :                         Word16 *frame_ener,     /* o  : pitch-synchronous energy at frame end       Q8   */
     236             :                         const Word16 Q_syn      /* i  : Synthesis scaling                                */
     237             : )
     238             : {
     239             :     Word32 Ltmp;
     240             :     const Word16 *pt1;
     241             :     Word16 tmp16, exp1, exp2, tmp1, tmp2;
     242             :     Word16 len, enern;
     243             : #ifndef ISSUE_1836_replace_overflow_libcom
     244             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     245             :     Flag Overflow = 0;
     246             :     move32();
     247             : #endif
     248             : #endif
     249             : 
     250             : 
     251             :     /* len = (0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f) */
     252             : #ifdef ISSUE_1836_replace_overflow_libcom
     253      125624 :     len = mult_r( add_sat( pitch[2], pitch[3] ), 256 );
     254             : #else
     255             :     len = mult_r( add_o( pitch[2], pitch[3], &Overflow ), 256 );
     256             : #endif
     257             : 
     258      125624 :     if ( LT_16( len, L_SUBFR ) )
     259             :     {
     260       31167 :         len = shl( len, 1 );
     261             :     }
     262      125624 :     pt1 = speech + sub( L_frame, len );
     263             : 
     264             :     /* *frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len) */
     265             : 
     266      125624 :     tmp1 = norm_s( len );
     267      125624 :     tmp2 = shl( len, tmp1 );
     268      125624 :     tmp1 = sub( 15, tmp1 );
     269             : 
     270      125624 :     Ltmp = Dot_productSq16HQ( 0, pt1, len, &exp1 );
     271      125624 :     exp1 = sub( exp1, shl( Q_syn, 1 ) );
     272      125624 :     exp1 = sub( exp1, 1 ); /* compensation of leftshift caused by mac operation in dot_productSq16HQ */
     273      125624 :     tmp16 = BASOP_Util_Divide3216_Scale( Ltmp, len, &exp2 );
     274             : 
     275      125624 :     exp1 = add( exp1, exp2 );
     276      125624 :     exp1 = add( exp1, 1 ); /* compensate result of division Q-1 */
     277             : 
     278             : 
     279      125624 :     tmp2 = norm_s( tmp16 );
     280      125624 :     Ltmp = L_shl( L_deposit_h( tmp16 ), tmp2 ); /*Q16, (exp1-tmp2)  =  Q31, exp1-tmp2+15*/
     281             : 
     282      125624 :     Ltmp = BASOP_Util_Log2( Ltmp ); /*Q(31-6) = Q25*/
     283      125624 :     exp1 = sub( 15 + exp1, tmp2 );
     284             : 
     285             :     /*add ld(2^exp1)=exp1 but check format, first*/
     286      125624 :     tmp16 = sub( sub( 15, norm_s( exp1 ) ), 5 ); /*factor to shift Ltmp and exp1 with (shr) to avoid overflows when adding*/
     287             : #ifdef ISSUE_1836_replace_overflow_libcom
     288      125624 :     Ltmp = L_shr_sat( Ltmp, tmp16 ); /*Q25, tmp16*/
     289             : #else
     290             :     Ltmp = L_shr_o( Ltmp, tmp16, &Overflow );                               /*Q25, tmp16*/
     291             : #endif
     292      125624 :     exp2 = shr( exp1, tmp16 ); /*Q0 , tmp16*/
     293             : #ifdef ISSUE_1836_replace_overflow_libcom
     294      125624 :     Ltmp = L_add_sat( Ltmp, L_shl( L_deposit_l( exp2 ), 25 ) ); /*Q25, tmp16, normalized*/
     295             : #else
     296             :     Ltmp = L_add_o( Ltmp, L_shl( L_deposit_l( exp2 ), 25 ), &Overflow );    /*Q25, tmp16, normalized*/
     297             : #endif
     298             : 
     299             :     /*make 10*log10 out of log2*/
     300      125624 :     Ltmp = Mpy_32_16_1( Ltmp, LG10 ); /*Q25,tmp16 * Q13 = Q23, tmp16*/
     301             : #ifdef ISSUE_1836_replace_overflow_libcom
     302      125624 :     *frame_ener = extract_h( L_shl_sat( Ltmp, add( tmp16, 1 ) ) ); /*Q8*/
     303      125624 :     move16();
     304      125624 :     enern = sub_sat( *frame_ener, lp_speech ); /*Q8*/
     305             : #else
     306             :     *frame_ener = extract_h( L_shl_o( Ltmp, add( tmp16, 1 ), &Overflow ) ); /*Q8*/
     307             :     move16();
     308             :     enern = sub_o( *frame_ener, lp_speech, &Overflow ); /*Q8*/
     309             : #endif
     310      125624 :     return enern;
     311             : }

Generated by: LCOV version 1.14