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

Generated by: LCOV version 1.14