LCOV - code coverage report
Current view: top level - lib_enc - detect_transient.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 52 85 61.2 %
Date: 2025-05-23 08:37:30 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             : #ifdef DEBUGGING
      40             : #include "debug.h"
      41             : #endif
      42             : #include "prot.h"
      43             : #include "cnst.h"
      44             : #include "rom_com.h"
      45             : #include "wmc_auto.h"
      46             : 
      47             : /*--------------------------------------------------------------------------
      48             :  * hp_filter()
      49             :  *
      50             :  * High pass filter
      51             :  *--------------------------------------------------------------------------*/
      52             : 
      53       21048 : static void hp_filter(
      54             :     const float *x, /* i  : input signal            */
      55             :     float *y,       /* o  : output signal           */
      56             :     float *oldx,    /* i/o: previous filter input   */
      57             :     float *oldy,    /* i/o: previous filter output  */
      58             :     const int16_t L /* i  : length (32 or 48Hz)     */
      59             : )
      60             : {
      61             :     int16_t i;
      62             : 
      63       21048 :     y[0] = 0.4931f * *oldy + 0.7466f * ( x[0] - *oldx );
      64             : 
      65    12105600 :     for ( i = 1; i < L; i++ )
      66             :     {
      67    12084552 :         y[i] = 0.4931f * y[i - 1] + 0.7466f * ( x[i] - x[i - 1] );
      68             :     }
      69             : 
      70       21048 :     *oldx = x[L - 1];
      71       21048 :     *oldy = y[L - 1];
      72             : 
      73       21048 :     return;
      74             : }
      75             : 
      76             : /*--------------------------------------------------------------------------
      77             :  * detect_transient()
      78             :  *
      79             :  * Detect if the signal is a transient
      80             :  *--------------------------------------------------------------------------*/
      81             : 
      82             : /*! r: transient flag */
      83       21048 : int16_t detect_transient(
      84             :     Encoder_State *st, /* i/o: Encoder state structure  */
      85             :     const float *in,   /* i  : input signal             */
      86             :     const int16_t L    /* i  : length (32 or 48kHz)     */
      87             : )
      88             : {
      89             :     float Energy;
      90             :     float EnergyLT;
      91             :     int16_t i, blk;
      92             :     int16_t IsTransient;
      93             :     float out_filt[L_FRAME48k];
      94       21048 :     int16_t position = 0;
      95             :     float thr;
      96       21048 :     float Thres = 0.f;
      97             :     float Energy_in[5];
      98             :     float E_low, E_high;
      99       21048 :     float E_in = 0.0f, E_out = 0.0f;
     100             : 
     101       21048 :     IsTransient = 0;
     102             : 
     103       21048 :     if ( st->last_extl != st->extl )
     104             :     {
     105        2284 :         st->TransientHangOver = 0;
     106        2284 :         st->old_hpfilt_in = 0;
     107        2284 :         st->old_hpfilt_out = 0;
     108        2284 :         st->Energy_Old = 0;
     109             :     }
     110             : 
     111             :     /* High-pass filter */
     112       21048 :     hp_filter( in, out_filt, &( st->old_hpfilt_in ), &( st->old_hpfilt_out ), L );
     113             : 
     114             :     /* Long-term energy */
     115       21048 :     if ( st->last_extl != st->extl || ( st->last_extl == st->extl && st->last_core != st->core ) || st->last_codec_mode == MODE2 )
     116             :     {
     117       10196 :         EnergyLT = EPSILON;
     118     2010276 :         for ( i = 0; i < L / 4; i++ )
     119             :         {
     120     2000080 :             EnergyLT += out_filt[i] * out_filt[i];
     121             :         }
     122             :     }
     123             :     else
     124             :     {
     125       10852 :         EnergyLT = st->EnergyLT;
     126             :     }
     127             : 
     128       21048 :     if ( L == L_FRAME8k )
     129             :     {
     130           0 :         Energy_in[0] = st->Energy_Old;
     131           0 :         E_in = 0;
     132           0 :         E_out = 0;
     133             : 
     134             :         /* Compute block energy */
     135           0 :         for ( blk = 0; blk < 4; blk++ )
     136             :         {
     137           0 :             Energy = EPSILON;
     138           0 :             Energy_in[blk + 1] = EPSILON;
     139             : 
     140           0 :             for ( i = 0; i < L / 4; i++ )
     141             :             {
     142           0 :                 Energy += out_filt[i + blk * ( L / 4 )] * out_filt[i + blk * ( L / 4 )];
     143           0 :                 Energy_in[blk + 1] += in[i + blk * ( L / 4 )] * in[i + blk * ( L / 4 )];
     144             :             }
     145             : 
     146           0 :             E_in += Energy_in[blk + 1];
     147           0 :             E_out += Energy;
     148             : 
     149           0 :             Thres = 15.f;
     150             : 
     151           0 :             if ( Energy > 6.0f * EnergyLT )
     152             :             {
     153           0 :                 IsTransient = 1;
     154           0 :                 position = blk;
     155             :             }
     156             : 
     157           0 :             EnergyLT = 0.75f * EnergyLT + 0.25f * Energy;
     158             :         }
     159             :     }
     160             :     else
     161             :     {
     162             :         /* Compute block energy */
     163      105240 :         for ( blk = 0; blk < 4; blk++ )
     164             :         {
     165       84192 :             Energy = EPSILON;
     166    12189792 :             for ( i = 0; i < L / 4; i++ )
     167             :             {
     168    12105600 :                 Energy += out_filt[i + blk * ( L / 4 )] * out_filt[i + blk * ( L / 4 )];
     169             :             }
     170             : 
     171       84192 :             if ( st->extl == SWB_BWE || st->extl == FB_BWE )
     172             :             {
     173       47688 :                 if ( ( Energy > 13.5f * EnergyLT ) || ( Energy > 10.0f * EnergyLT && st->core == ACELP_CORE && st->coder_type == INACTIVE ) )
     174             :                 {
     175         257 :                     IsTransient = 1;
     176         257 :                     position = blk;
     177             :                 }
     178             :             }
     179             :             else
     180             :             {
     181       36504 :                 if ( st->total_brate <= HQ_16k40 && st->bwidth == SWB )
     182             :                 {
     183         136 :                     thr = 13.5f;
     184             :                 }
     185             :                 else
     186             :                 {
     187       36368 :                     thr = 6.0f;
     188             :                 }
     189             : 
     190       36504 :                 if ( Energy > thr * EnergyLT )
     191             :                 {
     192         365 :                     IsTransient = 1;
     193         365 :                     position = blk;
     194             :                 }
     195             :             }
     196             : 
     197       84192 :             EnergyLT = 0.75f * EnergyLT + 0.25f * Energy;
     198             :         }
     199             :     }
     200             : 
     201       21048 :     st->EnergyLT = EnergyLT;
     202             : 
     203       21048 :     if ( ( st->last_extl != SWB_BWE && st->last_extl != SWB_TBE && st->extl == SWB_BWE ) ||
     204       19925 :          ( st->last_extl != FB_BWE && st->last_extl != FB_TBE && st->extl == FB_BWE ) )
     205             :     {
     206        1196 :         IsTransient = 0;
     207             :     }
     208             : 
     209       21048 :     if ( IsTransient && L == L_FRAME8k )
     210             :     {
     211           0 :         E_low = 0.f;
     212           0 :         blk = 0;
     213           0 :         for ( i = 0; i < position + 1; i++ )
     214             :         {
     215           0 :             E_low += Energy_in[i];
     216           0 :             blk++;
     217             :         }
     218           0 :         E_low /= (float) blk;
     219             : 
     220           0 :         E_high = 0.f;
     221           0 :         blk = 0;
     222           0 :         for ( i = position + 1; i < 5; i++ )
     223             :         {
     224           0 :             E_high += Energy_in[i];
     225           0 :             blk++;
     226             :         }
     227           0 :         E_high /= (float) blk;
     228             : 
     229           0 :         if ( ( ( E_high / E_low < 2.0f ) && ( E_high / E_low > 0.7f ) ) && ( ( E_in / E_out ) > Thres ) )
     230             :         {
     231           0 :             IsTransient = 0;
     232             :         }
     233             :     }
     234             : 
     235       21048 :     if ( IsTransient )
     236             :     {
     237         456 :         if ( L == L_FRAME8k )
     238             :         {
     239           0 :             if ( position == 3 )
     240             :             {
     241           0 :                 st->TransientHangOver = 1;
     242             :             }
     243             :         }
     244             :         else
     245             :         {
     246         456 :             st->TransientHangOver = 1;
     247             :         }
     248             :     }
     249             :     else
     250             :     {
     251       20592 :         if ( st->TransientHangOver )
     252             :         {
     253         328 :             st->TransientHangOver = 0;
     254         328 :             IsTransient = 1;
     255             :         }
     256             :     }
     257             : 
     258       21048 :     if ( L == L_FRAME8k )
     259             :     {
     260           0 :         st->Energy_Old = Energy_in[4];
     261             :     }
     262             : 
     263       21048 :     return IsTransient;
     264             : }

Generated by: LCOV version 1.14