LCOV - code coverage report
Current view: top level - lib_dec - er_util.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 75 107 70.1 %
Date: 2025-05-23 08:37:30 Functions: 4 5 80.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 <math.h>
      43             : #include "prot.h"
      44             : #include "cnst.h"
      45             : #include "stat_com.h"
      46             : #include "wmc_auto.h"
      47             : 
      48             : 
      49             : /*---------------------------------------------------------------------*
      50             :  * minimumStatistics()
      51             :  *
      52             :  *
      53             :  *---------------------------------------------------------------------*/
      54             : 
      55     1086396 : void minimumStatistics(
      56             :     float *noiseLevelMemory,
      57             :     int16_t *noiseLevelIndex,
      58             :     int16_t *currLevelIndex,
      59             :     float *noiseEstimate,
      60             :     float *lastFrameLevel,
      61             :     float currentFrameLevel,
      62             :     const float minLev,
      63             :     const int16_t buffSize )
      64             : {
      65             :     float aOpt, f;
      66             :     int16_t p, i;
      67             : 
      68     1086396 :     if ( currentFrameLevel < minLev )
      69             :     {
      70      204678 :         currentFrameLevel = minLev;
      71             :     }
      72             :     /* compute optimal factor aOpt for recursive smoothing of frame minima */
      73     1086396 :     if ( *lastFrameLevel >= *noiseEstimate )
      74             :     {
      75      996435 :         aOpt = *noiseEstimate / *lastFrameLevel;
      76             :     }
      77             :     else
      78             :     {
      79       89961 :         aOpt = *lastFrameLevel / *noiseEstimate;
      80             :     }
      81     1086396 :     aOpt *= aOpt;
      82     1086396 :     *lastFrameLevel = currentFrameLevel;
      83             :     /* recursively compute smoothed frame minima using optimal factor aOpt */
      84     1086396 :     f = currentFrameLevel * ( 1.0f - aOpt );
      85     1086396 :     f += aOpt * noiseLevelMemory[( *currLevelIndex ? *currLevelIndex : buffSize ) - 1];
      86             :     /* if current frame min is a new local min, set index to current index */
      87     1086396 :     p = *noiseLevelIndex;
      88     1086396 :     if ( noiseLevelMemory[p] >= f )
      89             :     {
      90      274059 :         noiseLevelMemory[*currLevelIndex] = f;
      91      274059 :         p = *currLevelIndex;
      92             :     }
      93             :     else
      94             :     {
      95      812337 :         noiseLevelMemory[*currLevelIndex] = f;
      96             :         /* current min is not a new min, so check if min must be re-searched */
      97      812337 :         if ( p != *currLevelIndex )
      98             :         {
      99      768954 :             f = noiseLevelMemory[p]; /* min is still in memory, so return it */
     100             :         }
     101             :         else
     102             :         {
     103             :             /* p == currLevelIndex; min was removed from memory, re-search min */
     104     1268814 :             for ( i = *currLevelIndex + 1; i < buffSize; i++ )
     105             :             {
     106     1225431 :                 if ( f >= noiseLevelMemory[i] )
     107             :                 {
     108       67005 :                     f = noiseLevelMemory[i];
     109       67005 :                     p = i;
     110             :                 }
     111             :             }
     112      987102 :             for ( i = 0; i <= *currLevelIndex; i++ )
     113             :             {
     114      943719 :                 if ( f >= noiseLevelMemory[i] )
     115             :                 {
     116       18384 :                     f = noiseLevelMemory[i];
     117       18384 :                     p = i;
     118             :                 }
     119             :             }
     120             :         }
     121             :     }
     122             :     /* update local-minimum-value index and current circular-buffer index */
     123     1086396 :     *noiseLevelIndex = p;
     124     1086396 :     p = *currLevelIndex + 1;
     125     1086396 :     *currLevelIndex = ( p == buffSize ) ? 0 : p;
     126             : 
     127     1086396 :     *noiseEstimate = f;
     128             : 
     129     1086396 :     return;
     130             : }
     131             : 
     132             : /*---------------------------------------------------------------------*
     133             :  * getLevelSynDeemph()
     134             :  *
     135             :  * PLC: [ACELP: Fade-out]
     136             :  * PLC: getLevelSynDeemph: derives on frame or subframe basis the level
     137             :  *      of LPC synthesis and deeemphasis based on the given input
     138             :  *----------------------------------------------------------------------*/
     139             : 
     140       16731 : float getLevelSynDeemph(
     141             :     const float h1Init[],    /* i  : input value or vector to be processed */
     142             :     const float A[],         /* i  : LPC coefficients                      */
     143             :     const int16_t lenLpcExc, /* i  : length of the LPC excitation buffer   */
     144             :     const float preemph_fac, /* i  : preemphasis factor                    */
     145             :     const int16_t numLoops   /* i  : number of loops                       */
     146             : )
     147             : {
     148             :     float levelSynDeemphSub;
     149       16731 :     float levelSynDeemph = 0;
     150             :     float h1[L_FRAME_PLUS / 4];
     151             :     float mem[M];
     152       16731 :     float tmp = 0;
     153             :     int16_t loop;
     154             : 
     155       33462 :     for ( loop = 0; loop < numLoops; loop++ )
     156             :     {
     157       16731 :         set_zero( h1, lenLpcExc );
     158       16731 :         set_zero( mem, M );
     159             : 
     160       16731 :         h1[0] = *h1Init;
     161             : 
     162       16731 :         syn_filt( A, M, h1, h1, lenLpcExc, mem, 0 );
     163       16731 :         deemph( h1, preemph_fac, lenLpcExc, &tmp );
     164       16731 :         A += ( M + 1 );
     165             : 
     166             :         /* gain introduced by synthesis+deemphasis */
     167       16731 :         levelSynDeemphSub = (float) sqrt( dotp( h1, h1, lenLpcExc ) );
     168             : 
     169             :         /* mean of the above across all subframes */
     170       16731 :         levelSynDeemph += ( 1.0f / (float) numLoops ) * levelSynDeemphSub;
     171             :     }
     172             : 
     173       16731 :     return levelSynDeemph;
     174             : }
     175             : 
     176             : 
     177             : /*---------------------------------------------------------------------
     178             :  * genPlcFiltBWAdap()
     179             :  *
     180             :  *
     181             :  *---------------------------------------------------------------------*/
     182             : 
     183           0 : void genPlcFiltBWAdap(
     184             :     const int32_t sr_core, /* i  : core sampling rate                                         */
     185             :     float *lpFiltAdapt,    /* o  : filter coefficients for filtering codebooks in case of flc */
     186             :     const int16_t type,    /* i  : type of filter, either 0 : lowpass or 1 : highpass         */
     187             :     const float alpha      /* i  : fade out factor [0 1) used decrease filter tilt            */
     188             : )
     189             : {
     190             :     float a;
     191             : 
     192           0 :     switch ( sr_core )
     193             :     {
     194           0 :         case INT_FS_16k:
     195           0 :             a = 0.4000f;
     196           0 :             break;
     197           0 :         default:
     198           0 :             a = 0.2813f; /*sr_core = INT_FS_12k8 */
     199           0 :             break;
     200             :     }
     201             : 
     202           0 :     switch ( type )
     203             :     {
     204           0 :         case 0:
     205           0 :             *lpFiltAdapt++ = a / ( 2.f * a + 1.f );
     206           0 :             *lpFiltAdapt++ = 1.f / ( 2.f * a + 1.f );
     207           0 :             *lpFiltAdapt = a / ( 2.f * a + 1.f );
     208           0 :             break;
     209           0 :         case 1:
     210           0 :             a *= alpha;
     211           0 :             *lpFiltAdapt++ = -a / ( 2.f * a + 1.f );
     212           0 :             *lpFiltAdapt++ = 1.f / ( 2.f * a + 1.f );
     213           0 :             *lpFiltAdapt = -a / ( 2.f * a + 1.f );
     214           0 :             break;
     215           0 :         default:
     216           0 :             IVAS_ERROR( IVAS_ERR_INTERNAL, "PLC: Filter type neither lowpass nor highpass." );
     217           0 :             break;
     218             :     }
     219             : 
     220           0 :     return;
     221             : }
     222             : 
     223             : /*------------------------------------------------------------------
     224             :  * highPassFiltering()
     225             :  *
     226             :  * PLC: [ACELP: general]
     227             :  * PLC: high pass filtering
     228             :  *-----------------------------------------------------------------*/
     229             : 
     230        9159 : void highPassFiltering(
     231             :     const int16_t last_good, /* i  : last classification type                           */
     232             :     const int16_t L_buffer,  /* i  : buffer length                                      */
     233             :     float exc2[],            /* i/o: unvoiced excitation before the high pass filtering */
     234             :     const float hp_filt[],   /* i  : high pass filter coefficients                      */
     235             :     const int16_t l_fir_fer  /* i  : high pass filter length                            */
     236             : )
     237             : {
     238             :     int16_t i;
     239             : 
     240        9159 :     if ( last_good > UNVOICED_TRANSITION )
     241             :     {
     242    10411668 :         for ( i = 0; i < L_buffer; i++ )
     243             :         {
     244    10402509 :             exc2[i] = dotp( &exc2[i], hp_filt, l_fir_fer );
     245             :         }
     246             :     }
     247             : 
     248        9159 :     return;
     249             : }
     250             : 
     251             : /*---------------------------------------------------------------------
     252             :  * GetPLCModeDecision()
     253             :  *
     254             :  * PLC: [Common: mode decision]
     255             :  * PLC: Decide which Concealment to use. Update pitch lags if needed
     256             :  *--------------------------------------------------------------------*/
     257             : 
     258       50778 : int16_t GetPLCModeDecision(
     259             :     Decoder_State *st /* i/o: decoder memory state pointer */
     260             : )
     261             : {
     262             :     int16_t core;
     263       50778 :     int16_t numIndices = 0;
     264       50778 :     TCX_DEC_HANDLE hTcxDec = st->hTcxDec;
     265             : 
     266       50778 :     if ( st->flagGuidedAcelp == 1 )
     267             :     {
     268             :         /* update mem_lag according to info available on future frame */
     269           0 :         st->old_pitch_buf[2 * st->nb_subfr] = (float) st->guidedT0;
     270           0 :         st->old_pitch_buf[2 * st->nb_subfr + 1] = (float) st->guidedT0;
     271           0 :         st->mem_pitch_gain[0] = st->mem_pitch_gain[1] = 1.f;
     272             :     }
     273       50778 :     if ( ( st->last_core > ACELP_CORE && hTcxDec->tcxltp_last_gain_unmodified != 0 ) || ( st->flagGuidedAcelp == 1 ) )
     274             :     {
     275             :         /* no updates needed here, because already updated in last good frame */
     276       38283 :         st->plc_use_future_lag = 1;
     277             :     }
     278             :     else
     279             :     {
     280       12495 :         st->plc_use_future_lag = 0;
     281             :     }
     282       50778 :     if ( st->last_core == -1 )
     283             :     {
     284           0 :         if ( st->Opt_AMR_WB )
     285             :         {
     286           0 :             core = ACELP_CORE;
     287             :         }
     288             :         else
     289             :         {
     290           0 :             core = TCX_20_CORE;
     291             :         }
     292           0 :         st->last_core = ACELP_CORE;
     293           0 :         st->tonal_mdct_plc_active = 0;
     294             :     }
     295             :     else
     296             :     {
     297             : #ifndef DEBUG_NO_TD_TCX_PLC
     298       50778 :         core = ACELP_CORE;
     299             : #else
     300             :         core = st->last_core;
     301             : #endif
     302       50778 :         if ( st->nbLostCmpt > 1 )
     303             :         {
     304       21135 :             core = st->last_core_bfi;
     305             :         }
     306             : 
     307             :         /* no FD TCX PLC after a TCX transition frame: the appropriate framing is not implemented */
     308       50778 :         if ( st->nbLostCmpt == 1 )
     309             :         {
     310       29643 :             st->tonal_mdct_plc_active = 0;
     311       29643 :             if ( !( st->rf_flag && st->use_partial_copy && ( st->rf_frame_type == RF_TCXTD1 || st->rf_frame_type == RF_TCXTD2 ) ) )
     312             :             {
     313       29643 :                 if ( st->hTonalMDCTConc != NULL && st->last_core == TCX_20_CORE && st->second_last_core == TCX_20_CORE && ( ( st->old_fpitch <= 0.5f * st->L_frame ) || ( hTcxDec->tcxltp_last_gain_unmodified <= 0.4f ) )
     314             :                      /* it is fine to call the detection even if no ltp information
     315             :                            is available, meaning that st->old_fpitch ==
     316             :                            st->tcxltp_second_last_pitch == st->L_frame */
     317       25950 :                      && ( st->old_fpitch == hTcxDec->tcxltp_second_last_pitch ) && !st->last_tns_active && !st->second_last_tns_active )
     318             :                 {
     319             : 
     320        7215 :                     TonalMDCTConceal_Detect( st->hTonalMDCTConc, ( hTcxDec->tcxltp_last_gain_unmodified > 0 ) ? st->old_fpitch : 0, &numIndices,
     321        7215 :                                              ( st->element_mode == IVAS_CPE_MDCT ? &( st->hTcxCfg->psychParamsTCX20 ) : st->hTcxCfg->psychParamsCurrent ) );
     322             : 
     323        7215 :                     if ( ( numIndices > 10 ) || ( ( numIndices > 5 ) && ( fabs( hTcxDec->tcxltp_third_last_pitch - hTcxDec->tcxltp_second_last_pitch ) < 0.5f ) ) || ( ( numIndices > 0 ) && ( ( st->last_good <= UNVOICED_TRANSITION ) || ( hTcxDec->tcxltp_last_gain_unmodified <= 0.4f ) ) && ( fabs( hTcxDec->tcxltp_third_last_pitch - hTcxDec->tcxltp_second_last_pitch ) < 0.5f ) ) )
     324             :                     {
     325        1359 :                         core = TCX_20_CORE;
     326             : #ifndef DEBUG_NO_TONAL_PLC
     327        1359 :                         st->tonal_mdct_plc_active = 1;
     328             : #endif
     329             :                     }
     330        5856 :                     else if ( st->last_good <= UNVOICED_TRANSITION || hTcxDec->tcxltp_last_gain_unmodified <= 0.4f )
     331             :                     {
     332        5277 :                         core = TCX_20_CORE;
     333             :                     }
     334             :                 }
     335             : #ifndef DEBUG_FORCE_TD_TCX_CONCEALMENT
     336       22428 :                 else if ( st->last_core != ACELP_CORE )
     337             :                 {
     338       22428 :                     if ( st->last_good <= UNVOICED_TRANSITION || hTcxDec->tcxltp_last_gain_unmodified <= 0.4f )
     339             :                     {
     340       13596 :                         core = st->last_core;
     341             :                     }
     342             :                 }
     343             : #endif
     344             :             }
     345             :         }
     346             :     }
     347             : 
     348       50778 :     return core;
     349             : }

Generated by: LCOV version 1.14