LCOV - code coverage report
Current view: top level - lib_com - gs_preech_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 23 103 22.3 %
Date: 2025-05-03 01:55:50 Functions: 2 2 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 "rom_com.h"
      42             : #include "prot_fx.h"
      43             : #include "wmc_auto.h"
      44             : 
      45             : /*-------------------------------------------------------------------*
      46             :  * Local constants
      47             :  *-------------------------------------------------------------------*/
      48             : 
      49             : #define ATT_LENGHT16k 80
      50             : 
      51             : #define ATT_LENGHT  64
      52             : #define ATT_SEG_LEN ( L_FRAME / ATT_LENGHT )
      53             : 
      54       20567 : void pre_echo_att_fx(
      55             :     Word32 *Last_frame_ener_fx,      /* i/o: Energy of the last frame         2*Q_new+1*/
      56             :     Word16 *exc_fx,                  /* i/o: Excitation of the current frame  Q_new*/
      57             :     const Word16 gsc_attack_flag_fx, /* i  : flag signalling attack encoded by AC mode (GSC)    Q0*/
      58             :     const Word16 Q_new,
      59             :     const Word16 last_coder_type, /* i  : Last coding mode              Q0*/
      60             :     const Word16 L_frame          /* i  : Frame length                  Q0*/
      61             : )
      62             : {
      63             :     Word32 etmp_fx;
      64       20567 :     Word32 finc_fx[ATT_LENGHT16k] = { 0 };
      65       20567 :     move16();
      66             :     Word16 ratio_fx;
      67             :     Word16 attack_pos_fx, i;
      68             :     Word32 L_tmp, L_tmp1;
      69             :     Word16 tmp, n1, n2, exp, frac1, frac2;
      70             :     Word32 etmp1_fx;
      71             :     Word16 att_len;
      72             : 
      73       20567 :     test();
      74       20567 :     IF( gsc_attack_flag_fx > 0 && EQ_16( last_coder_type, AUDIO ) ) /*gsc_attack_flag_fx does not get set for all the test cases */
      75             :     {
      76             :         /*-------------------------------------------------------------------------*
      77             :          * Find where the onset (attack) occurs by computing the energy per section
      78             :          * The inverse weighting aims to favor the first maxima in case of
      79             :          * gradual onset
      80             :          *-------------------------------------------------------------------------*/
      81           0 :         att_len = ATT_LENGHT; /* Q0 */
      82           0 :         move16();
      83           0 :         if ( EQ_16( L_frame, L_FRAME16k ) )
      84             :         {
      85           0 :             att_len = ATT_LENGHT16k; /* Q0 */
      86           0 :             move16();
      87             :         }
      88           0 :         FOR( i = 0; i < att_len; i++ )
      89             :         {
      90           0 :             L_tmp = sum2_fx( &exc_fx[i * 4], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/
      91           0 :             tmp = div_s( sub( att_len, i ), att_len );      /*Q15 */
      92           0 :             L_tmp = Mult_32_16( L_tmp, tmp );               /*2*Q_new+1 */
      93           0 :             finc_fx[i] = L_tmp;
      94           0 :             move32(); /*2*Q_new+1 */
      95             :         }
      96             : 
      97           0 :         attack_pos_fx = maximum_32_fx( finc_fx, att_len, &etmp_fx );
      98             : 
      99             :         /* Scaled the maximum energy and allowed 6 dB increase*/
     100           0 :         etmp_fx = L_shr( etmp_fx, add( 2 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */
     101           0 :         etmp1_fx = etmp_fx;
     102           0 :         move32();
     103           0 :         *Last_frame_ener_fx = L_shl_sat( *Last_frame_ener_fx, 2 );
     104           0 :         move32(); /*2*Q_new+1 */
     105             : 
     106             :         /* If the maximum normalized energy > last frame energy + 6dB */
     107           0 :         test();
     108           0 :         IF( GT_32( etmp_fx, *Last_frame_ener_fx ) && attack_pos_fx > 0 )
     109             :         {
     110             :             /* Find the average energy before the attack */
     111           0 :             L_tmp = sum32_fx( finc_fx, attack_pos_fx );                  /*Q1 */
     112           0 :             L_tmp1 = L_shr( L_mult( attack_pos_fx, attack_pos_fx ), 1 ); /*Q0 */
     113           0 :             tmp = round_fx( Isqrt( L_tmp1 ) );                           /*Q15 */
     114           0 :             L_tmp = L_shr( L_tmp, 2 );                                   /*Q1 ; ATT_SEG_LEN=4 */
     115           0 :             etmp_fx = Mult_32_16( L_tmp, tmp );                          /*Q1 */
     116             : 
     117           0 :             etmp_fx = L_shr( etmp_fx, add( 1 - 4, shl( Q_new, 1 ) ) ); /* makes etmp i nQ4 as *Last_frame_ener_fx */
     118             :                                                                        /* Find the correction factor and apply it before the attack */
     119             :                                                                        /*   ratio = (float)sqrt(*Last_frame_ener/etmp);*/
     120             :                                                                        /*         = isqrt(etmp/(*Last_frame_ener))                      */
     121           0 :             etmp_fx = L_max( etmp_fx, 1 );
     122           0 :             *Last_frame_ener_fx = L_max( *Last_frame_ener_fx, 1 );
     123           0 :             move32();
     124           0 :             n1 = norm_l( etmp_fx );
     125           0 :             n2 = norm_l( *Last_frame_ener_fx );
     126             : 
     127           0 :             n1 = sub( n1, 1 );
     128           0 :             exp = sub( n1, n2 );
     129             : 
     130           0 :             frac1 = round_fx( L_shl( etmp_fx, n1 ) );
     131           0 :             frac2 = round_fx_sat( L_shl_sat( *Last_frame_ener_fx, n2 ) );
     132           0 :             L_tmp = L_mult0( 128, div_s( frac1, frac2 ) ); /* s = gain_out / gain_in */
     133           0 :             L_tmp = L_shr( L_tmp, exp );                   /* add exponent */
     134             : 
     135           0 :             L_tmp = Isqrt( L_tmp );
     136           0 :             ratio_fx = round_fx( L_shl( L_tmp, 9 ) ); /* Q13 */
     137             : 
     138             :             /* Pre-echo atttenuation should never increase the energy */
     139           0 :             ratio_fx = s_min( ratio_fx, 8192 /* 1 in Q13 */ ); /* Q13 */
     140           0 :             FOR( i = 0; i < attack_pos_fx * ATT_SEG_LEN; i++ )
     141             :             {
     142             :                 /*exc_fx[i] *= ratio_fx;*/
     143           0 :                 exc_fx[i] = round_fx( L_shl( L_mac( -8192, exc_fx[i], ratio_fx ), 2 ) );
     144           0 :                 move16();
     145             :             }
     146             :         }
     147           0 :         *Last_frame_ener_fx = etmp1_fx; /*2*Q_new+1*/
     148           0 :         move32();
     149             :     }
     150             :     ELSE
     151             :     {
     152             :         /*-------------------------------------------------------*
     153             :          * In normal cases, just compute the energy of the frame
     154             :          *-------------------------------------------------------*/
     155             : 
     156       20567 :         etmp_fx = sum2_fx( exc_fx, L_frame );                          /*2*Q_new+1 */
     157       20567 :         etmp_fx = L_shr( etmp_fx, add( 8 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_L_FRAME = 1/256 -> Q4*/
     158       20567 :         *Last_frame_ener_fx = etmp_fx;
     159       20567 :         move32(); /*2*Q_new+1*/
     160             :     }
     161             : 
     162       20567 :     return;
     163             : }
     164             : 
     165             : 
     166       22696 : void pre_echo_att_ivas_fx(
     167             :     Word32 *Last_frame_ener_fx,      /* i/o: Energy of the last frame         2*Q_new+1*/
     168             :     Word16 *exc_fx,                  /* i/o: Excitation of the current frame  Q_new*/
     169             :     const Word16 gsc_attack_flag_fx, /* i  : flag signalling attack encoded by AC mode (GSC)    Q0*/
     170             :     const Word16 Q_new,
     171             :     const Word16 last_coder_type, /* i  : Last coding mode                              Q0*/
     172             :     const Word16 L_frame          /* i  : Frame length                                  Q0*/
     173             : )
     174             : {
     175             :     Word32 etmp_fx;
     176       22696 :     Word32 finc_fx[ATT_LENGHT16k] = { 0 };
     177       22696 :     move16();
     178             :     Word16 ratio_fx;
     179             :     Word16 attack_pos_fx, i;
     180             :     Word32 L_tmp;
     181             :     Word16 tmp, tmp_e;
     182             :     Word32 etmp1_fx;
     183             :     Word16 etmp_e;
     184             :     Word16 att_len;
     185             : 
     186       22696 :     test();
     187       22696 :     IF( gsc_attack_flag_fx > 0 && EQ_16( last_coder_type, AUDIO ) ) /*gsc_attack_flag_fx does not get set for all the test cases */
     188             :     {
     189             :         /*-------------------------------------------------------------------------*
     190             :          * Find where the onset (attack) occurs by computing the energy per section
     191             :          * The inverse weighting aims to favor the first maxima in case of
     192             :          * gradual onset
     193             :          *-------------------------------------------------------------------------*/
     194           0 :         att_len = ATT_LENGHT; /* Q0 */
     195           0 :         move16();
     196           0 :         if ( EQ_16( L_frame, L_FRAME16k ) )
     197             :         {
     198           0 :             att_len = ATT_LENGHT16k; /* Q0 */
     199           0 :             move16();
     200             :         }
     201           0 :         FOR( i = 0; i < att_len; i++ )
     202             :         {
     203           0 :             L_tmp = sum2_fx( &exc_fx[i * 4], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/
     204           0 :             tmp = div_s( sub( att_len, i ), att_len );      /*Q15 */
     205           0 :             L_tmp = Mult_32_16( L_tmp, tmp );               /*2*Q_new+1 */
     206           0 :             finc_fx[i] = L_tmp;
     207           0 :             move32(); /*2*Q_new+1 */
     208             :         }
     209             : 
     210           0 :         attack_pos_fx = maximum_32_fx( finc_fx, att_len, &etmp_fx );
     211             : 
     212             :         /* Scaled the maximum energy and allowed 6 dB increase*/
     213           0 :         etmp_fx = L_shr( etmp_fx, add( 2 + 1 - 4, shl( Q_new, 1 ) ) ); /*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */
     214           0 :         etmp1_fx = etmp_fx;
     215           0 :         move32();
     216           0 :         *Last_frame_ener_fx = L_shl_sat( *Last_frame_ener_fx, 2 );
     217           0 :         move32(); /*2*Q_new+1 */
     218             : 
     219             :         /* If the maximum normalized energy > last frame energy + 6dB */
     220           0 :         test();
     221           0 :         IF( GT_32( etmp_fx, *Last_frame_ener_fx ) && attack_pos_fx > 0 )
     222             :         {
     223             :             /* Find the average energy before the attack */
     224           0 :             etmp_fx = sum32_fx( finc_fx, attack_pos_fx );
     225           0 :             etmp_e = sub( 31, add( shl( Q_new, 1 ), 1 ) );
     226           0 :             etmp_fx = L_add( etmp_fx, L_shr( 21474836 /*0.01 in Q31*/, etmp_e ) ); /* etmp = etmp + 0.01;   (exp = etmp_e) */
     227           0 :             etmp_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( etmp_fx, L_mult0( attack_pos_fx, ATT_SEG_LEN ), &tmp_e ) );
     228           0 :             tmp_e = add( tmp_e, sub( etmp_e, 31 ) );
     229           0 :             etmp_e = tmp_e;
     230           0 :             move16();
     231             : 
     232             :             /* Find the correction factor and apply it before the attack */
     233           0 :             tmp = BASOP_Util_Divide3232_Scale( *Last_frame_ener_fx, etmp_fx, &tmp_e ); /* numerator Q = 2 * Q_new + 1;  denominator Q = 31 - tmp_e */
     234           0 :             tmp_e = add( tmp_e, sub( sub( 31, etmp_e ), add( shl( Q_new, 1 ), 1 ) ) ); /* tmp_e = tmp_e + (31 - tmp_e) - (2 * Q_new + 1) */
     235           0 :             tmp = Sqrt16( tmp, &tmp_e );
     236           0 :             ratio_fx = shr_sat( tmp, sub( 2, tmp_e ) ); /* Q13 */
     237             : 
     238             :             /* Pre-echo atttenuation should never increase the energy */
     239           0 :             ratio_fx = s_min( ratio_fx, 8192 /* 1 in Q13 */ ); /* Q13 */
     240           0 :             FOR( i = 0; i < attack_pos_fx * ATT_SEG_LEN; i++ )
     241             :             {
     242             :                 /*exc_fx[i] *= ratio_fx;*/
     243           0 :                 exc_fx[i] = round_fx( L_shl( L_mac( -8192, exc_fx[i], ratio_fx ), 2 ) );
     244           0 :                 move16();
     245             :             }
     246             :         }
     247           0 :         *Last_frame_ener_fx = etmp1_fx; /* 2 * Q_new + 1 */
     248           0 :         move32();
     249             :     }
     250             :     ELSE
     251             :     {
     252             :         /*-------------------------------------------------------*
     253             :          * In normal cases, just compute the energy of the frame
     254             :          *-------------------------------------------------------*/
     255       22696 :         Word16 exp_etmp = sub( 15, Q_new );
     256       22696 :         etmp_fx = sum2_16_exp_fx( exc_fx, L_frame, &exp_etmp, 7 ); /* Q = 31-exp_etmp */
     257             : 
     258       22696 :         etmp_fx = L_shr( etmp_fx, 8 ); /*31-exp_etmp//INV_L_FRAME = 1/256*/
     259             : 
     260       22696 :         IF( EQ_16( L_frame, L_FRAME16k ) )
     261             :         {
     262        2650 :             etmp_fx = Mpy_32_16_1( etmp_fx, 26214 /* 0.8 in Q15 */ ); /*31 - exp_etmp*/
     263             :         }
     264       22696 :         *Last_frame_ener_fx = L_shl( etmp_fx, sub( shl( Q_new, 1 ), sub( 30 /*31-1*/, exp_etmp ) ) ); /*2*Q_new+1*/
     265       22696 :         move32();                                                                                     /*2*Q_new+1*/
     266             :     }
     267             : 
     268       22696 :     return;
     269             : }

Generated by: LCOV version 1.14