LCOV - code coverage report
Current view: top level - lib_enc - detect_transient_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 43b7b28dcb1471ff5d355252c4b8f37ee7ecc268 Lines: 107 166 64.5 %
Date: 2025-11-02 02:02:47 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.452 Aug 12, 2021. Version 16.3.0
      35             :   ====================================================================================*/
      36             : #include <stdint.h>
      37             : #include "options.h"     /* Compilation switches                   */
      38             : #include "cnst.h"        /* Common constants                       */
      39             : #include "rom_com.h"     /* Static table prototypes                */
      40             : #include "prot_fx.h"     /* Function prototypes                    */
      41             : #include "prot_fx_enc.h" /* Function prototypes                    */
      42             : 
      43             : /*--------------------------------------------------------------------------*/
      44             : /*  Function  hp_filter                                                     */
      45             : /*  ~~~~~~~~~~~~~~~~~~~~                                                    */
      46             : /*                                                                          */
      47             : /*  High pass filter                                                        */
      48             : /*--------------------------------------------------------------------------*/
      49             : /*  float      x      (i)    in Q_new input to filter                       */
      50             : /*  float      y      (o)    in Q_new +2 output of filter                   */
      51             : /*  float      *oldy  (i/o)  previous output of filter                                          */
      52             : /*  float      *oldx  (i/o)  in Q_memx previous input of filter             */
      53             : /*  short      L      (i)    in Q_memx +2  length (32 or 48 kHz)            */
      54             : /*--------------------------------------------------------------------------*/
      55             : 
      56       20619 : static void hp_filter_fx(
      57             :     const Word16 *x, /*Q_new */
      58             :     Word16 *y,       /*Q_new */
      59             :     Word16 *oldy,    /*Q_new */
      60             :     Word16 *oldx,    /*Q_new */
      61             :     const Word16 L /*Q0*/ )
      62             : {
      63             :     Word16 i;
      64             :     Word32 L_tmp;
      65             : 
      66             :     /*y[0] = 0.4931f * *oldy + 0.7466f*(x[0] - *oldx); */
      67       20619 :     L_tmp = L_mult( sub_sat( x[0], *oldx ), 24465 /*0.7466f in Q15*/ ); /*Q_new+16 */
      68       20619 :     L_tmp = L_mac_sat( L_tmp, *oldy, 16158 /*0.4931f in Q15*/ );        /*Q_new+16 */
      69       20619 :     y[0] = round_fx_sat( L_tmp );                                       /*Q_new */
      70    11924160 :     FOR( i = 1; i < L; i++ )
      71             :     {
      72             :         /*y[i] = 0.4931f*y[i-1] + 0.7466f*(x[i] - x[i-1]); */
      73    11903541 :         L_tmp = L_mult( sub_sat( x[i], x[i - 1] ), 24465 /*0.7466f in Q15*/ ); /*Q_new+16 */
      74    11903541 :         L_tmp = L_mac_sat( L_tmp, y[i - 1], 16158 /*0.4931f in Q15*/ );        /*Q_new+16 */
      75    11903541 :         y[i] = round_fx_sat( L_tmp );                                          /*Q_new */
      76             :     }
      77             : 
      78       20619 :     *oldx = x[L - 1];
      79       20619 :     move16(); /*Q_new */
      80       20619 :     *oldy = y[L - 1];
      81       20619 :     move16(); /*Q_new */
      82             : 
      83       20619 :     return;
      84             : }
      85             : 
      86             : 
      87             : /*--------------------------------------------------------------------------*/
      88             : /*  Function  detect_transient                                              */
      89             : /*  ~~~~~~~~~~~~~~~~~~~~~~~~~~                                              */
      90             : /*                                                                          */
      91             : /*  Detect if the signal is a transient                                     */
      92             : /*--------------------------------------------------------------------------*/
      93             : /*  float          in[]    (i)    input signal                        Q_new */
      94             : /*  Encoder_State *st      (i/o)  state of coder                            */
      95             : /*  short          L       (i)    length (32 or 48 kHz)                     */
      96             : /*--------------------------------------------------------------------------*/
      97             : /*  short       return     (o)   result of transient check                  */
      98             : /*--------------------------------------------------------------------------*/
      99             : 
     100       20619 : Word16 detect_transient_fx(
     101             :     const Word16 *in_fx, /*Q_new */
     102             :     const Word16 L,      /*Q0*/
     103             :     Word16 Q_new,
     104             :     Encoder_State *st_fx )
     105             : {
     106             :     Word32 Energy, L_tmp;
     107             :     Word32 EnergyLT;
     108             :     Word16 i, blk;
     109             :     Word16 IsTransient;
     110             :     Word16 out_filt_fx[L_FRAME48k];
     111       20619 :     Word16 position = 0;
     112             :     Word16 thr;
     113             :     Word32 L_tmp2;
     114             :     Word16 shift;
     115       20619 :     Word32 Energy_fx, E_in_fx = 0, E_out_fx = 0, Energy_in_fx[5] = { 0, 0, 0, 0, 0 }; /* Energy_fx can be replaced by Energy */
     116             :     Word32 E_low_fx, E_high_fx;
     117       20619 :     Word16 temp16, Thres_fx = 0;
     118             :     Word16 exp;
     119             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     120       20619 :     Flag Overflow = 0;
     121       20619 :     move32();
     122             : #endif
     123             : 
     124       20619 :     shift = 0;
     125       20619 :     move16();
     126             : 
     127       20619 :     IsTransient = 0;
     128       20619 :     move16();
     129       20619 :     IF( NE_16( st_fx->last_extl, st_fx->extl ) )
     130             :     {
     131        2293 :         st_fx->TransientHangOver = 0;
     132        2293 :         move16();
     133        2293 :         st_fx->old_hpfilt_in_fx = 0;
     134        2293 :         move16();
     135        2293 :         st_fx->old_hpfilt_out_fx = 0;
     136        2293 :         move16();
     137             :     }
     138             : 
     139             :     /* High pass filter */
     140       20619 :     hp_filter_fx( in_fx, out_filt_fx, &( st_fx->old_hpfilt_in_fx ), &( st_fx->old_hpfilt_out_fx ), L );
     141             : 
     142             :     /* Long term energy */
     143       20619 :     test();
     144       20619 :     test();
     145       20619 :     test();
     146       20619 :     IF( NE_16( st_fx->last_extl, st_fx->extl ) || ( EQ_16( st_fx->last_extl, st_fx->extl ) && NE_16( st_fx->last_core, st_fx->core ) ) || EQ_16( st_fx->last_codec_mode, MODE2 ) )
     147             :     {
     148             :         /*EnergyLT = EPSILON_FX; */
     149        9969 :         EnergyLT = L_deposit_l( 0 );
     150     1981329 :         FOR( i = 0; i < L / 4; i++ )
     151             :         {
     152             :             /*EnergyLT += out_filt[i] * out_filt[i]; */
     153     1971360 :             EnergyLT = L_mac0_sat( EnergyLT, out_filt_fx[i], out_filt_fx[i] ); /*2Q_new */
     154             :         }
     155             :     }
     156             :     ELSE
     157             :     {
     158       10650 :         EnergyLT = L_add( st_fx->EnergyLT_fx, 0 ); /*2Q_new */
     159             :     }
     160       20619 :     IF( EQ_16( L, L_FRAME8k ) )
     161             :     {
     162           0 :         Energy_in_fx[0] = st_fx->Energy_Old_fx; /*Q0*/
     163           0 :         move32();
     164             :         /* Compute block energy */
     165           0 :         FOR( blk = 0; blk < 4; blk++ )
     166             :         {
     167           0 :             Energy_fx = L_deposit_l( 0 );
     168           0 :             Energy_in_fx[blk + 1] = L_deposit_l( 0 );
     169           0 :             FOR( i = 0; i < L / 4; i++ )
     170             :             {
     171           0 :                 temp16 = extract_l( L_shr( out_filt_fx[i + blk * ( L / 4 )], 12 ) );
     172           0 :                 Energy_fx = L_add_sat( Energy_fx, L_mult0( temp16, temp16 ) );
     173           0 :                 temp16 = shr( in_fx[i + blk * ( L / 4 )], Q_new );                                     /*Q0*/
     174           0 :                 Energy_in_fx[blk + 1] = L_add_sat( Energy_in_fx[blk + 1], L_mult0( temp16, temp16 ) ); /*Q0*/
     175           0 :                 move32();
     176             :             }
     177             : 
     178           0 :             E_in_fx = L_add_sat( E_in_fx, Energy_in_fx[blk + 1] ); /*Q0*/
     179           0 :             E_out_fx = L_add_sat( E_out_fx, Energy_fx );           /*Q0*/
     180             : 
     181           0 :             Thres_fx = 2185; /*1 /15     Q15*/
     182           0 :             move16();
     183           0 :             IF( GT_32( Mult_32_16( Energy_fx, 5461 ), EnergyLT ) )
     184             :             {
     185           0 :                 IsTransient = 1;
     186           0 :                 move16();
     187           0 :                 position = blk;
     188           0 :                 move16();
     189             :             }
     190             : 
     191           0 :             EnergyLT = L_add( Mult_32_16( EnergyLT, 24576 /*Q15*/ ), Mult_32_16( Energy_fx, 8192 /*Q15*/ ) ); /*2Q_new*/
     192             :         }
     193             :     }
     194             :     ELSE
     195             :     {
     196             :         /* Compute block energy */
     197      103095 :         FOR( blk = 0; blk < 4; blk++ )
     198             :         {
     199       82476 :             L_tmp = L_deposit_l( 0 );
     200     6044556 :             FOR( i = 0; i < L / 8; i++ )
     201             :             {
     202             :                 /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
     203     5962080 :                 L_tmp = L_mac0_sat( L_tmp, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )] ); /*2Q_new */
     204             :             }
     205       82476 :             L_tmp2 = L_deposit_l( 0 );
     206     6044556 :             FOR( ; i < L / 4; i++ )
     207             :             {
     208             :                 /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
     209     5962080 :                 L_tmp2 = L_mac0_sat( L_tmp2, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )] ); /*2Q_new */
     210             :             }
     211       82476 :             Overflow = 0;
     212       82476 :             move16();
     213       82476 :             Energy = L_add_o( L_tmp, L_tmp2, &Overflow ); /*2Q_new */
     214       82476 :             shift = 0;
     215       82476 :             if ( Overflow != 0 )
     216             :             {
     217         459 :                 shift = 1;
     218         459 :                 move16();
     219             :             }
     220       82476 :             Energy = L_add_sat( L_shr( L_tmp, shift ), L_shr( L_tmp2, shift ) ); /*2Q_new - shift*/
     221       82476 :             test();
     222       82476 :             IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) )
     223             :             {
     224             :                 /*Calculate shift to get to Q0*/
     225       46852 :                 test();
     226       46852 :                 test();
     227       46852 :                 IF( ( GT_32( Mult_32_16( Energy, shl( 2427, shift ) ), EnergyLT ) ) || ( GT_32( Mult_32_16( Energy, shl( 3277, shift ) ), EnergyLT ) && EQ_16( st_fx->core, ACELP_CORE ) && EQ_16( st_fx->coder_type, INACTIVE ) ) )
     228             :                 {
     229         415 :                     IsTransient = 1;
     230         415 :                     move16();
     231         415 :                     position = blk;
     232         415 :                     move16();
     233             :                 }
     234             :             }
     235             :             ELSE
     236             :             {
     237       35624 :                 test();
     238       35624 :                 IF( LE_32( st_fx->total_brate, HQ_16k40 ) && EQ_16( st_fx->bwidth, SWB ) )
     239             :                 {
     240         156 :                     thr = 2427;
     241         156 :                     move16();
     242             :                 }
     243             :                 ELSE
     244             :                 {
     245       35468 :                     thr = 5461;
     246       35468 :                     move16();
     247             :                 }
     248       35624 :                 thr = shl( thr, shift );
     249             :                 /*if(Energy > L_shr(Mult_32_16(EnergyLT,22624),shift_cnt))                           //getting in Q0   32*16 = Q_inp1+Q_inp2+1-16 */
     250       35624 :                 IF( GT_32( Mult_32_16( Energy, thr ), EnergyLT ) )
     251             :                 /*if(Energy > 6.0f * EnergyLT)  */
     252             :                 {
     253         342 :                     IsTransient = 1;
     254         342 :                     move16();
     255         342 :                     position = blk;
     256         342 :                     move16();
     257             :                 }
     258             :             }
     259             :             /*EnergyLT = 0.75f*EnergyLT + 0.25f*Energy;                          */
     260             :             /*0.75f*EnergyLT in Q0                         //0.25f*Energy in Q0                  */
     261       82476 :             EnergyLT = L_add_sat( Mult_32_16( EnergyLT, 24576 /*0.75f in Q15*/ ), Mult_32_16( Energy, shl( 8192 /*0.25 in Q15*/, shift ) ) ); /*2Q_new */
     262             :         }
     263             :     }
     264       20619 :     st_fx->EnergyLT_fx = EnergyLT;
     265       20619 :     move32();
     266             : 
     267       20619 :     test();
     268       20619 :     test();
     269       20619 :     test();
     270       20619 :     test();
     271       20619 :     test();
     272       40134 :     if ( ( NE_16( st_fx->last_extl, SWB_BWE ) && NE_16( st_fx->last_extl, SWB_TBE ) && EQ_16( st_fx->extl, SWB_BWE ) ) ||
     273       34501 :          ( NE_16( st_fx->last_extl, FB_BWE ) && NE_16( st_fx->last_extl, FB_TBE ) && EQ_16( st_fx->extl, FB_BWE ) ) )
     274             :     {
     275        1181 :         IsTransient = 0;
     276        1181 :         move16();
     277             :     }
     278             : 
     279       20619 :     test();
     280       20619 :     IF( IsTransient && L == L_FRAME8k )
     281             :     {
     282           0 :         blk = 0;
     283           0 :         move16();
     284           0 :         E_low_fx = L_deposit_l( 0 );
     285           0 :         FOR( i = 0; i < position + 1; i++ )
     286             :         {
     287             :             /*blk++;     */
     288           0 :             blk = add( blk, 1 );
     289           0 :             E_low_fx = L_add_sat( E_low_fx, Energy_in_fx[i] ); /*Q0*/
     290             :         }
     291             : 
     292           0 :         exp = norm_s( blk );
     293           0 :         temp16 = div_s( 16384, shl( blk, exp ) ); /* 15 + 14 - exp; */
     294           0 :         exp = 15 + 14 - exp;
     295           0 :         temp16 = shl( temp16, sub( 15, exp ) );
     296           0 :         E_low_fx = Mult_32_16( E_low_fx, temp16 );
     297             : 
     298           0 :         blk = 0;
     299           0 :         move16();
     300           0 :         E_high_fx = L_deposit_l( 0 );
     301           0 :         FOR( i = position + 1; i < 5; i++ )
     302             :         {
     303             :             /*blk++; */
     304           0 :             blk = add( blk, 1 );
     305           0 :             E_high_fx = L_add_sat( E_high_fx, Energy_in_fx[i] ); /*Q0*/
     306             :         }
     307             : 
     308           0 :         exp = norm_s( blk );
     309           0 :         temp16 = div_s( 16384, shl( blk, exp ) ); /* 15 + 14 - exp; */
     310           0 :         exp = 15 + 14 - exp;
     311           0 :         temp16 = shl( temp16, 15 - exp );
     312           0 :         E_high_fx = Mult_32_16( E_high_fx, temp16 );
     313             : 
     314           0 :         test();
     315           0 :         test();
     316           0 :         IF( LT_32( L_shr( E_high_fx, 1 ), E_low_fx ) && GT_32( E_high_fx, Mult_32_16( E_low_fx, 22938 /*0.7 in Q15*/ ) ) && GT_32( Mult_32_16( E_in_fx, Thres_fx ), E_out_fx ) )
     317             :         {
     318           0 :             IsTransient = 0;
     319           0 :             move16();
     320             :         }
     321             :     }
     322       20619 :     IF( EQ_32( st_fx->core_brate, ACELP_24k40 ) )
     323             :     {
     324          78 :         test();
     325          78 :         IF( NE_16( st_fx->last_core, HQ_CORE ) || NE_32( st_fx->last_core_brate, ACELP_24k40 ) )
     326             :         {
     327          78 :             st_fx->TransientHangOver = 0;
     328          78 :             move16();
     329          78 :             IsTransient = 0;
     330          78 :             move16();
     331             :         }
     332             :         ELSE
     333             :         {
     334           0 :             IF( IsTransient )
     335             :             {
     336           0 :                 if ( EQ_16( position, 3 ) )
     337             :                 {
     338             :                     /* Set Hangover */
     339           0 :                     st_fx->TransientHangOver = 1;
     340           0 :                     move16();
     341             :                 }
     342             :             }
     343             :             ELSE
     344             :             {
     345           0 :                 IF( st_fx->TransientHangOver )
     346             :                 {
     347           0 :                     st_fx->TransientHangOver = 0;
     348           0 :                     move16();
     349           0 :                     IsTransient = 1;
     350           0 :                     move16();
     351             :                 }
     352             :             }
     353             :         }
     354             :     }
     355             :     ELSE
     356             :     {
     357       20541 :         IF( IsTransient )
     358             :         {
     359         420 :             st_fx->TransientHangOver = 1;
     360         420 :             move16();
     361             :         }
     362             :         ELSE
     363             :         {
     364       20121 :             IF( st_fx->TransientHangOver )
     365             :             {
     366         300 :                 st_fx->TransientHangOver = 0;
     367         300 :                 move16();
     368         300 :                 IsTransient = 1;
     369         300 :                 move16();
     370             :             }
     371             :         }
     372             :     }
     373             : 
     374       20619 :     if ( EQ_16( L, L_FRAME8k ) )
     375             :     {
     376           0 :         st_fx->Energy_Old_fx = Energy_in_fx[4]; /*Q0*/
     377           0 :         move32();
     378             :     }
     379             : 
     380       20619 :     return IsTransient;
     381             : }

Generated by: LCOV version 1.14