LCOV - code coverage report
Current view: top level - lib_com - env_stab_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 79 79 100.0 %
Date: 2025-08-23 01:22:27 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             : 
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #include <math.h>
      41             : #include "cnst.h"
      42             : #include "prot_fx.h"
      43             : #include "rom_com.h"
      44             : #include "wmc_auto.h"
      45             : #include "stl.h"
      46             : 
      47             : /*--------------------------------------------------------------------------*
      48             :  * Local constants
      49             :  *--------------------------------------------------------------------------*/
      50             : 
      51             : #define ENV_STAB_SMO_HO 10 /* number of hangover frames when switching from music to speech state */
      52             : 
      53             : 
      54             : /*--------------------------------------------------------------------------*/
      55             : /*  Function  env_stability()                                               */
      56             : /*  ~~~~~~~~~~~~~~~~~~~~~~~~~                                               */
      57             : /*                                                                          */
      58             : /*  Envelope stability measure                                              */
      59             : /*--------------------------------------------------------------------------*/
      60             : 
      61        6607 : Word16 env_stability_fx(                                  /* in Q15 */
      62             :                          const Word16 *ynrm,              /*i:   Norm vector for current frame */
      63             :                          const Word16 nb_sfm,             /*i:   Number of sub-bands */
      64             :                          Word16 *mem_norm,                /*i/o: Norm vector memory from past frame */
      65             :                          Word16 *mem_env_delta,           /*i/o: Envelope stability memory for smoothing in Q12 */
      66             :                          const Word16 core_switching_flag /* i  : Core switching flag        */
      67             : )
      68             : {
      69             :     Word16 env_delta;
      70             :     Word16 env_stab;
      71             :     Word16 tmp, tmp_stab;
      72             :     Word16 i;
      73             : 
      74             :     Word16 exp, exp2;
      75             :     Word32 L_tmp, L_env_delta;
      76             :     Word16 inv_nb_sfm;
      77             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      78        6607 :     Flag Overflow = 0;
      79        6607 :     move32();
      80             : #endif
      81             : 
      82        6607 :     IF( core_switching_flag )
      83             :     {
      84        5193 :         FOR( i = 0; i < nb_sfm; i++ )
      85             :         {
      86        5003 :             mem_norm[i] = ynrm[i];
      87        5003 :             move16();
      88             :         }
      89         190 :         Overflow = 0;
      90         190 :         move16();
      91         190 :         env_delta = shl_o( *mem_env_delta, 1, &Overflow );
      92             :     }
      93             :     ELSE
      94             :     {
      95             :         /* Calculate envelope stability parameter */
      96        6417 :         L_env_delta = L_deposit_l( 0 );
      97      174599 :         FOR( i = 0; i < nb_sfm; i++ )
      98             :         {
      99      168182 :             tmp = sub( mem_norm[i], ynrm[i] );
     100      168182 :             L_env_delta = L_mac0( L_env_delta, tmp, tmp );
     101      168182 :             mem_norm[i] = ynrm[i];
     102      168182 :             move16();
     103             :         }
     104             : 
     105        6417 :         inv_nb_sfm = 19418; /* Q19 */
     106        6417 :         move16();
     107        6417 :         if ( nb_sfm == 26 )
     108             :         {
     109        5077 :             inv_nb_sfm = 20165; /* Q19 */
     110        5077 :             move16();
     111             :         }
     112        6417 :         exp = norm_l( L_env_delta );
     113        6417 :         L_env_delta = Mult_32_16( L_shl( L_env_delta, exp ), inv_nb_sfm ); /* 0+exp+19-15 */
     114             : 
     115        6417 :         L_tmp = Sqrt_l( L_env_delta, &exp2 ); /* exp+4+31+exp2 */
     116             : 
     117        6417 :         exp = add( 35, add( exp, exp2 ) );
     118        6417 :         if ( EQ_16( s_and( exp, 1 ), 1 ) )
     119             :         {
     120        3120 :             L_tmp = Mult_32_16( L_tmp, 23170 ); /* 1/sqrt(2) in Q15 */
     121             :         }
     122        6417 :         exp = shr( exp, 1 );
     123             : 
     124        6417 :         env_delta = round_fx_sat( L_shl_sat( L_tmp, sub( 26, exp ) ) ); /* Q10 */
     125             : 
     126        6417 :         L_tmp = L_mult0( 26214, env_delta );               /* 26214 is 0.1 in Q18. Q28 */
     127        6417 :         L_tmp = L_mac_sat( L_tmp, 29491, *mem_env_delta ); /* 29491 is 0.9 in Q15. Q28 */
     128             : 
     129        6417 :         *mem_env_delta = round_fx_sat( L_tmp ); /* Q12 */
     130        6417 :         Overflow = 0;
     131        6417 :         move16();
     132        6417 :         env_delta = round_fx_o( L_shl_o( L_tmp, 1, &Overflow ), &Overflow ); /* Q13 */
     133             :     }
     134        6607 :     IF( Overflow != 0 ) /* Saturated due to the above up-shifting operation. */
     135             :     {
     136          32 :         return stab_trans_fx[L_STAB_TBL - 1]; /* The highest quantized index. */
     137             :     }
     138             : 
     139             :     /* If tmp_stab > (D_STAB_TBL*L_STAB_TBL + M_STAB_TBL), i.e., 0.103138*10+2.51757=3.603137,
     140             :      * the quantized index is equal to 9. Hence, we only need to worry about any tmpStab < 4.
     141             :      * In this case, Q13 is good enough.
     142             :      */
     143        6575 :     tmp_stab = sub( env_delta, M_STAB_TBL_FX ); /* in Q13 */
     144        6575 :     tmp_stab = abs_s( tmp_stab );
     145             : 
     146             :     /* Table lookup for smooth transitions
     147             :      * First, find the quantization level, i, of tmpStab. */
     148             : #if L_STAB_TBL > 10
     149             : #error env_stability_fx: Use more efficient usquant()
     150             : #endif
     151        6575 :     tmp_stab = sub( tmp_stab, HALF_D_STAB_TBL_FX ); /* in Q13 */
     152       47623 :     FOR( i = 0; i < L_STAB_TBL - 1; i++ )
     153             :     {
     154       44975 :         IF( tmp_stab < 0 )
     155             :         {
     156        3927 :             BREAK;
     157             :         }
     158             :         ELSE
     159             :         {
     160       41048 :             tmp_stab = sub( tmp_stab, D_STAB_TBL_FX ); /* in Q13 */
     161             :         }
     162             :     }
     163             : 
     164        6575 :     env_stab = stab_trans_fx[i];
     165        6575 :     move16();
     166        6575 :     if ( LT_16( env_delta, M_STAB_TBL_FX ) )
     167             :     {
     168        5826 :         env_stab = sub( 0x7FFF, stab_trans_fx[i] );
     169             :     }
     170             : 
     171        6575 :     return env_stab;
     172             : }
     173             : 
     174             : /*--------------------------------------------------------------------------*
     175             :  * env_stab_smo_fx()
     176             :  *
     177             :  *
     178             :  *--------------------------------------------------------------------------*/
     179             : 
     180             : /*! r: New speech/music state */
     181        7838 : Word16 env_stab_smo_fx(                           /* Q0 */
     182             :                         Word16 env_stab,          /*i  : env_stab value                        Q15 */
     183             :                         Word16 *env_stab_state_p, /*i/o: env_stab state probabilities          Q15 */
     184             :                         Word16 *ho_cnt            /*i/o: hangover counter for speech state      */
     185             : )
     186             : {
     187             :     Word16 state, prev_state;
     188             :     Word16 maxval, pp[NUM_ENV_STAB_PLC_STATES], pa[NUM_ENV_STAB_PLC_STATES];
     189             :     Word16 i;
     190             :     Word16 tmp, sum, exp;
     191             : #ifndef ISSUE_1836_replace_overflow_libcom
     192             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     193             :     Flag Overflow = 0;
     194             :     move32();
     195             : #endif
     196             : #endif
     197             :     /* get previous state */
     198        7838 :     prev_state = maximum_fx( env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval );
     199             : 
     200             :     /* assume two states: speech(0), music(1) */
     201             :     /* set a posteriori likelihoods for the two states according to env_stab */
     202             :     /* re-scale. Unclear if needed */
     203             :     /* env_stab = (env_stab - stab_trans_fx[L_STAB_TBL-1])/(1-2*stab_trans_fx[L_STAB_TBL-1]); */
     204        7838 :     tmp = sub( env_stab, stab_trans_fx[L_STAB_TBL - 1] );
     205        7838 :     tmp = round_fx( L_shl( L_mult( tmp, INV_STAB_TRANS_FX ), 1 ) ); /* Q15 */
     206             : 
     207        7838 :     pp[0] = sub( 32767, tmp );
     208        7838 :     move16(); /* 1 in Q15 */
     209        7838 :     pp[1] = tmp;
     210        7838 :     move16();
     211             : 
     212             :     /* calculate a priori likelihoods */
     213        7838 :     pa[0] = round_fx( Dot_product( env_stab_tp_fx[0], env_stab_state_p, NUM_ENV_STAB_PLC_STATES ) ); /* Q15*/
     214        7838 :     pa[1] = round_fx( Dot_product( env_stab_tp_fx[1], env_stab_state_p, NUM_ENV_STAB_PLC_STATES ) );
     215             : 
     216             :     /* multiply elementwise with a posteriori likelihoods */
     217        7838 :     sum = 0;
     218        7838 :     move16();
     219       23514 :     FOR( i = 0; i < NUM_ENV_STAB_PLC_STATES; i++ )
     220             :     {
     221       15676 :         env_stab_state_p[i] = mult_r( pa[i], pp[i] );
     222       15676 :         move16(); /* Q15 */
     223       15676 :         sum = add( sum, env_stab_state_p[i] );
     224             :     }
     225             : 
     226             :     /* renormalize state probabilities */
     227        7838 :     exp = norm_s( sum );
     228        7838 :     tmp = div_s( 16384, shl( sum, exp ) ); /* Q(14-exp) */
     229             :     /*tmp = shl(tmp, add(exp, 1));*/       /* Q15 */
     230       23514 :     FOR( i = 0; i < NUM_ENV_STAB_PLC_STATES; i++ )
     231             :     {
     232             : #ifdef ISSUE_1836_replace_overflow_libcom
     233       15676 :         env_stab_state_p[i] = round_fx_sat( L_shl_sat( L_mult_sat( env_stab_state_p[i], tmp ), add( exp, 1 ) ) ); /* Q15 */
     234             : #else
     235             :         env_stab_state_p[i] = round_fx_o( L_shl_o( L_mult_o( env_stab_state_p[i], tmp, &Overflow ), add( exp, 1 ), &Overflow ), &Overflow ); /* Q15 */
     236             : #endif
     237       15676 :         move16();
     238             :     }
     239             : 
     240             :     /* find maximum index as return value */
     241        7838 :     state = maximum_fx( env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval );
     242             : 
     243             :     /* apply some hangover for speech */
     244        7838 :     test();
     245        7838 :     if ( state == 0 && EQ_16( prev_state, 1 ) )
     246             :     {
     247         144 :         *ho_cnt = ENV_STAB_SMO_HO;
     248         144 :         move16();
     249             :     }
     250             : 
     251        7838 :     IF( *ho_cnt > 0 )
     252             :     {
     253        1257 :         *ho_cnt = sub( *ho_cnt, 1 );
     254        1257 :         move16();
     255             :     }
     256             : 
     257        7838 :     return state;
     258             : }

Generated by: LCOV version 1.14