LCOV - code coverage report
Current view: top level - lib_enc - detect_transient_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 107 166 64.5 %
Date: 2025-09-14 03:13:15 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       20607 : 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             : #ifndef ISSUE_1867_replace_overflow_libenc
      66             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      67             :     Flag Overflow = 0;
      68             :     move32();
      69             : #endif
      70             : #endif
      71             : 
      72             : 
      73             :     /*y[0] = 0.4931f * *oldy + 0.7466f*(x[0] - *oldx); */
      74             : #ifdef ISSUE_1867_replace_overflow_libenc
      75       20607 :     L_tmp = L_mult( sub_sat( x[0], *oldx ), 24465 /*0.7466f in Q15*/ ); /*Q_new+16 */
      76             : #else
      77             :     L_tmp = L_mult( sub_o( x[0], *oldx, &Overflow ), 24465 /*0.7466f in Q15*/ );        /*Q_new+16 */
      78             : #endif
      79       20607 :     L_tmp = L_mac_sat( L_tmp, *oldy, 16158 /*0.4931f in Q15*/ ); /*Q_new+16 */
      80       20607 :     y[0] = round_fx_sat( L_tmp );                                /*Q_new */
      81    11920320 :     FOR( i = 1; i < L; i++ )
      82             :     {
      83             :         /*y[i] = 0.4931f*y[i-1] + 0.7466f*(x[i] - x[i-1]); */
      84             : #ifdef ISSUE_1867_replace_overflow_libenc
      85    11899713 :         L_tmp = L_mult( sub_sat( x[i], x[i - 1] ), 24465 /*0.7466f in Q15*/ ); /*Q_new+16 */
      86    11899713 :         L_tmp = L_mac_sat( L_tmp, y[i - 1], 16158 /*0.4931f in Q15*/ );        /*Q_new+16 */
      87    11899713 :         y[i] = round_fx_sat( L_tmp );                                          /*Q_new */
      88             : #else
      89             :         L_tmp = L_mult( sub_o( x[i], x[i - 1], &Overflow ), 24465 /*0.7466f in Q15*/ ); /*Q_new+16 */
      90             :         L_tmp = L_mac_o( L_tmp, y[i - 1], 16158 /*0.4931f in Q15*/, &Overflow );        /*Q_new+16 */
      91             :         y[i] = round_fx_o( L_tmp, &Overflow );                                          /*Q_new */
      92             : #endif
      93             :     }
      94             : 
      95       20607 :     *oldx = x[L - 1];
      96       20607 :     move16(); /*Q_new */
      97       20607 :     *oldy = y[L - 1];
      98       20607 :     move16(); /*Q_new */
      99       20607 : }
     100             : /*--------------------------------------------------------------------------*/
     101             : /*  Function  detect_transient                                              */
     102             : /*  ~~~~~~~~~~~~~~~~~~~~~~~~~~                                              */
     103             : /*                                                                          */
     104             : /*  Detect if the signal is a transient                                     */
     105             : /*--------------------------------------------------------------------------*/
     106             : /*  float          in[]    (i)    input signal                        Q_new */
     107             : /*  Encoder_State *st      (i/o)  state of coder                            */
     108             : /*  short          L       (i)    length (32 or 48 kHz)                     */
     109             : /*--------------------------------------------------------------------------*/
     110             : /*  short       return     (o)   result of transient check                  */
     111             : /*--------------------------------------------------------------------------*/
     112             : 
     113       20607 : Word16 detect_transient_fx(
     114             :     const Word16 *in_fx, /*Q_new */
     115             :     const Word16 L,      /*Q0*/
     116             :     Word16 Q_new,
     117             :     Encoder_State *st_fx )
     118             : {
     119             :     Word32 Energy, L_tmp;
     120             :     Word32 EnergyLT;
     121             :     Word16 i, blk;
     122             :     Word16 IsTransient;
     123             :     Word16 out_filt_fx[L_FRAME48k];
     124       20607 :     Word16 position = 0;
     125             :     Word16 thr;
     126             :     Word32 L_tmp2;
     127             :     Word16 shift;
     128       20607 :     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 */
     129             :     Word32 E_low_fx, E_high_fx;
     130       20607 :     Word16 temp16, Thres_fx = 0;
     131             :     Word16 exp;
     132             : #ifdef ISSUE_1867_replace_overflow_libenc
     133             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     134       20607 :     Flag Overflow = 0;
     135       20607 :     move32();
     136             : #endif
     137             : #endif
     138             : 
     139       20607 :     shift = 0;
     140       20607 :     move16();
     141             : 
     142       20607 :     IsTransient = 0;
     143       20607 :     move16();
     144       20607 :     IF( NE_16( st_fx->last_extl, st_fx->extl ) )
     145             :     {
     146        2291 :         st_fx->TransientHangOver = 0;
     147        2291 :         move16();
     148        2291 :         st_fx->old_hpfilt_in_fx = 0;
     149        2291 :         move16();
     150        2291 :         st_fx->old_hpfilt_out_fx = 0;
     151        2291 :         move16();
     152             :     }
     153             : 
     154             :     /* High pass filter */
     155       20607 :     hp_filter_fx( in_fx, out_filt_fx, &( st_fx->old_hpfilt_in_fx ), &( st_fx->old_hpfilt_out_fx ), L );
     156             : 
     157             :     /* Long term energy */
     158       20607 :     test();
     159       20607 :     test();
     160       20607 :     test();
     161       20607 :     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 ) )
     162             :     {
     163             :         /*EnergyLT = EPSILON_FX; */
     164        9967 :         EnergyLT = L_deposit_l( 0 );
     165     1981167 :         FOR( i = 0; i < L / 4; i++ )
     166             :         {
     167             :             /*EnergyLT += out_filt[i] * out_filt[i]; */
     168             : #ifdef ISSUE_1867_replace_overflow_libenc
     169     1971200 :             EnergyLT = L_mac0_sat( EnergyLT, out_filt_fx[i], out_filt_fx[i] ); /*2Q_new */
     170             : #else
     171             :             EnergyLT = L_mac0_o( EnergyLT, out_filt_fx[i], out_filt_fx[i], &Overflow ); /*2Q_new */
     172             : #endif
     173             :         }
     174             :     }
     175             :     ELSE
     176             :     {
     177       10640 :         EnergyLT = L_add( st_fx->EnergyLT_fx, 0 ); /*2Q_new */
     178             :     }
     179       20607 :     IF( EQ_16( L, L_FRAME8k ) )
     180             :     {
     181           0 :         Energy_in_fx[0] = st_fx->Energy_Old_fx; /*Q0*/
     182           0 :         move32();
     183             :         /* Compute block energy */
     184           0 :         FOR( blk = 0; blk < 4; blk++ )
     185             :         {
     186           0 :             Energy_fx = L_deposit_l( 0 );
     187           0 :             Energy_in_fx[blk + 1] = L_deposit_l( 0 );
     188           0 :             FOR( i = 0; i < L / 4; i++ )
     189             :             {
     190           0 :                 temp16 = extract_l( L_shr( out_filt_fx[i + blk * ( L / 4 )], 12 ) );
     191             : #ifdef ISSUE_1867_replace_overflow_libenc
     192           0 :                 Energy_fx = L_add_sat( Energy_fx, L_mult0( temp16, temp16 ) );
     193             : #else
     194             :                 Energy_fx = L_add_o( Energy_fx, L_mult0( temp16, temp16 ), &Overflow );
     195             : #endif
     196           0 :                 temp16 = shr( in_fx[i + blk * ( L / 4 )], Q_new ); /*Q0*/
     197             : #ifdef ISSUE_1867_replace_overflow_libenc
     198           0 :                 Energy_in_fx[blk + 1] = L_add_sat( Energy_in_fx[blk + 1], L_mult0( temp16, temp16 ) ); /*Q0*/
     199             : #else
     200             :                 Energy_in_fx[blk + 1] = L_add_o( Energy_in_fx[blk + 1], L_mult0( temp16, temp16 ), &Overflow );                                        /*Q0*/
     201             : #endif
     202           0 :                 move32();
     203             :             }
     204             : 
     205             : #ifdef ISSUE_1867_replace_overflow_libenc
     206           0 :             E_in_fx = L_add_sat( E_in_fx, Energy_in_fx[blk + 1] ); /*Q0*/
     207           0 :             E_out_fx = L_add_sat( E_out_fx, Energy_fx );           /*Q0*/
     208             : #else
     209             :             E_in_fx = L_add_o( E_in_fx, Energy_in_fx[blk + 1], &Overflow );                                                                            /*Q0*/
     210             :             E_out_fx = L_add_o( E_out_fx, Energy_fx, &Overflow );                                                                                      /*Q0*/
     211             : #endif
     212             : 
     213           0 :             Thres_fx = 2185; /*1 /15     Q15*/
     214           0 :             move16();
     215           0 :             IF( GT_32( Mult_32_16( Energy_fx, 5461 ), EnergyLT ) )
     216             :             {
     217           0 :                 IsTransient = 1;
     218           0 :                 move16();
     219           0 :                 position = blk;
     220           0 :                 move16();
     221             :             }
     222             : 
     223           0 :             EnergyLT = L_add( Mult_32_16( EnergyLT, 24576 /*Q15*/ ), Mult_32_16( Energy_fx, 8192 /*Q15*/ ) ); /*2Q_new*/
     224             :         }
     225             :     }
     226             :     ELSE
     227             :     {
     228             :         /* Compute block energy */
     229      103035 :         FOR( blk = 0; blk < 4; blk++ )
     230             :         {
     231       82428 :             L_tmp = L_deposit_l( 0 );
     232     6042588 :             FOR( i = 0; i < L / 8; i++ )
     233             :             {
     234             :                 /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
     235             : #ifdef ISSUE_1867_replace_overflow_libenc
     236     5960160 :                 L_tmp = L_mac0_sat( L_tmp, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )] ); /*2Q_new */
     237             : #else
     238             :                 L_tmp = L_mac0_o( L_tmp, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )], &Overflow );                              /*2Q_new */
     239             : #endif
     240             :             }
     241       82428 :             L_tmp2 = L_deposit_l( 0 );
     242     6042588 :             FOR( ; i < L / 4; i++ )
     243             :             {
     244             :                 /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
     245             : #ifdef ISSUE_1867_replace_overflow_libenc
     246     5960160 :                 L_tmp2 = L_mac0_sat( L_tmp2, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )] ); /*2Q_new */
     247             : #else
     248             :                 L_tmp2 = L_mac0_o( L_tmp2, out_filt_fx[i + blk * ( L / 4 )], out_filt_fx[i + blk * ( L / 4 )], &Overflow );                            /*2Q_new */
     249             : #endif
     250             :             }
     251       82428 :             Overflow = 0;
     252       82428 :             move16();
     253       82428 :             Energy = L_add_o( L_tmp, L_tmp2, &Overflow ); /*2Q_new */
     254       82428 :             shift = 0;
     255       82428 :             if ( Overflow != 0 )
     256             :             {
     257         757 :                 shift = 1;
     258         757 :                 move16();
     259             :             }
     260             : #ifndef ISSUE_1867_replace_overflow_libenc
     261             :             Overflow = 0;
     262             :             move16();
     263             : 
     264             :             Energy = L_add_o( L_shr( L_tmp, shift ), L_shr( L_tmp2, shift ), &Overflow ); /*2Q_new - shift*/
     265             : #else
     266       82428 :             Energy = L_add_sat( L_shr( L_tmp, shift ), L_shr( L_tmp2, shift ) );                                                                       /*2Q_new - shift*/
     267             : #endif
     268       82428 :             test();
     269       82428 :             IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) )
     270             :             {
     271             :                 /*Calculate shift to get to Q0*/
     272       46804 :                 test();
     273       46804 :                 test();
     274       46804 :                 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 ) ) )
     275             :                 {
     276         432 :                     IsTransient = 1;
     277         432 :                     move16();
     278         432 :                     position = blk;
     279         432 :                     move16();
     280             :                 }
     281             :             }
     282             :             ELSE
     283             :             {
     284       35624 :                 test();
     285       35624 :                 IF( LE_32( st_fx->total_brate, HQ_16k40 ) && EQ_16( st_fx->bwidth, SWB ) )
     286             :                 {
     287         156 :                     thr = 2427;
     288         156 :                     move16();
     289             :                 }
     290             :                 ELSE
     291             :                 {
     292       35468 :                     thr = 5461;
     293       35468 :                     move16();
     294             :                 }
     295       35624 :                 thr = shl( thr, shift );
     296             :                 /*if(Energy > L_shr(Mult_32_16(EnergyLT,22624),shift_cnt))                           //getting in Q0   32*16 = Q_inp1+Q_inp2+1-16 */
     297       35624 :                 IF( GT_32( Mult_32_16( Energy, thr ), EnergyLT ) )
     298             :                 /*if(Energy > 6.0f * EnergyLT)  */
     299             :                 {
     300         342 :                     IsTransient = 1;
     301         342 :                     move16();
     302         342 :                     position = blk;
     303         342 :                     move16();
     304             :                 }
     305             :             }
     306             :             /*EnergyLT = 0.75f*EnergyLT + 0.25f*Energy;                          */
     307             :             /*0.75f*EnergyLT in Q0                         //0.25f*Energy in Q0                  */
     308             : #ifdef ISSUE_1867_replace_overflow_libenc
     309       82428 :             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 */
     310             : #else
     311             :             EnergyLT = L_add_o( Mult_32_16( EnergyLT, 24576 /*0.75f in Q15*/ ), Mult_32_16( Energy, shl( 8192 /*0.25 in Q15*/, shift ) ), &Overflow ); /*2Q_new */
     312             : #endif
     313             :         }
     314             :     }
     315       20607 :     st_fx->EnergyLT_fx = EnergyLT;
     316       20607 :     move32();
     317             : 
     318       20607 :     test();
     319       20607 :     test();
     320       20607 :     test();
     321       20607 :     test();
     322       20607 :     test();
     323       40118 :     if ( ( NE_16( st_fx->last_extl, SWB_BWE ) && NE_16( st_fx->last_extl, SWB_TBE ) && EQ_16( st_fx->extl, SWB_BWE ) ) ||
     324       34493 :          ( NE_16( st_fx->last_extl, FB_BWE ) && NE_16( st_fx->last_extl, FB_TBE ) && EQ_16( st_fx->extl, FB_BWE ) ) )
     325             :     {
     326        1173 :         IsTransient = 0;
     327        1173 :         move16();
     328             :     }
     329             : 
     330       20607 :     test();
     331       20607 :     IF( IsTransient && L == L_FRAME8k )
     332             :     {
     333           0 :         blk = 0;
     334           0 :         move16();
     335           0 :         E_low_fx = L_deposit_l( 0 );
     336           0 :         FOR( i = 0; i < position + 1; i++ )
     337             :         {
     338             :             /*blk++;     */
     339           0 :             blk = add( blk, 1 );
     340           0 :             E_low_fx = L_add_sat( E_low_fx, Energy_in_fx[i] ); /*Q0*/
     341             :         }
     342             : 
     343           0 :         exp = norm_s( blk );
     344           0 :         temp16 = div_s( 16384, shl( blk, exp ) ); /* 15 + 14 - exp; */
     345           0 :         exp = 15 + 14 - exp;
     346           0 :         temp16 = shl( temp16, sub( 15, exp ) );
     347           0 :         E_low_fx = Mult_32_16( E_low_fx, temp16 );
     348             : 
     349           0 :         blk = 0;
     350           0 :         move16();
     351           0 :         E_high_fx = L_deposit_l( 0 );
     352           0 :         FOR( i = position + 1; i < 5; i++ )
     353             :         {
     354             :             /*blk++; */
     355           0 :             blk = add( blk, 1 );
     356           0 :             E_high_fx = L_add_sat( E_high_fx, Energy_in_fx[i] ); /*Q0*/
     357             :         }
     358             : 
     359           0 :         exp = norm_s( blk );
     360           0 :         temp16 = div_s( 16384, shl( blk, exp ) ); /* 15 + 14 - exp; */
     361           0 :         exp = 15 + 14 - exp;
     362           0 :         temp16 = shl( temp16, 15 - exp );
     363           0 :         E_high_fx = Mult_32_16( E_high_fx, temp16 );
     364             : 
     365           0 :         test();
     366           0 :         test();
     367           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 ) )
     368             :         {
     369           0 :             IsTransient = 0;
     370           0 :             move16();
     371             :         }
     372             :     }
     373       20607 :     IF( EQ_32( st_fx->core_brate, ACELP_24k40 ) )
     374             :     {
     375          78 :         test();
     376          78 :         IF( NE_16( st_fx->last_core, HQ_CORE ) || NE_32( st_fx->last_core_brate, ACELP_24k40 ) )
     377             :         {
     378          78 :             st_fx->TransientHangOver = 0;
     379          78 :             move16();
     380          78 :             IsTransient = 0;
     381          78 :             move16();
     382             :         }
     383             :         ELSE
     384             :         {
     385           0 :             IF( IsTransient )
     386             :             {
     387           0 :                 if ( EQ_16( position, 3 ) )
     388             :                 {
     389             :                     /* Set Hangover */
     390           0 :                     st_fx->TransientHangOver = 1;
     391           0 :                     move16();
     392             :                 }
     393             :             }
     394             :             ELSE
     395             :             {
     396           0 :                 IF( st_fx->TransientHangOver )
     397             :                 {
     398           0 :                     st_fx->TransientHangOver = 0;
     399           0 :                     move16();
     400           0 :                     IsTransient = 1;
     401           0 :                     move16();
     402             :                 }
     403             :             }
     404             :         }
     405             :     }
     406             :     ELSE
     407             :     {
     408       20529 :         IF( IsTransient )
     409             :         {
     410         424 :             st_fx->TransientHangOver = 1;
     411         424 :             move16();
     412             :         }
     413             :         ELSE
     414             :         {
     415       20105 :             IF( st_fx->TransientHangOver )
     416             :             {
     417         304 :                 st_fx->TransientHangOver = 0;
     418         304 :                 move16();
     419         304 :                 IsTransient = 1;
     420         304 :                 move16();
     421             :             }
     422             :         }
     423             :     }
     424             : 
     425       20607 :     if ( EQ_16( L, L_FRAME8k ) )
     426             :     {
     427           0 :         st_fx->Energy_Old_fx = Energy_in_fx[4]; /*Q0*/
     428           0 :         move32();
     429             :     }
     430             : 
     431       20607 :     return IsTransient;
     432             : }

Generated by: LCOV version 1.14