LCOV - code coverage report
Current view: top level - lib_com - ivas_transient_det.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 109 111 98.2 %
Date: 2025-05-23 08:37:30 Functions: 6 6 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             : #include <stdint.h>
      34             : #include "options.h"
      35             : #ifdef DEBUGGING
      36             : #include "debug.h"
      37             : #endif
      38             : #include "math.h"
      39             : #include "wmc_auto.h"
      40             : #include "prot.h"
      41             : #include "ivas_cnst.h"
      42             : #include "ivas_prot.h"
      43             : #include "ivas_stat_com.h"
      44             : 
      45             : /*------------------------------------------------------------------------------------------*
      46             :  * Local constants
      47             :  *------------------------------------------------------------------------------------------*/
      48             : 
      49             : #define IVAS_TDET_PARM_ENV_EPS   ( 1e-5f )
      50             : #define IVAS_TDET_DUCK_MULT_FAC  ( 1.1f )
      51             : #define IVAS_TDET_PARM_TRANS_THR ( 0.1f )
      52             : #define IVAS_TDET_ONLY           ( 1 )
      53             : 
      54             : /*env_hpf*/
      55             : #define IVAS_C_HPF_48k ( 0.675231906655777f )
      56             : #define IVAS_C_HPF_32k ( 0.554854910159853f )
      57             : #define IVAS_C_HPF_16k ( 0.307863971328499f )
      58             : 
      59             : /*env_fast*/
      60             : #define IVAS_C_FAST_48k ( 0.995842001845110f )
      61             : #define IVAS_C_FAST_32k ( 0.993769490623395f )
      62             : #define IVAS_C_FAST_16k ( 0.987577800493881f )
      63             : 
      64             : /*env_slow*/
      65             : #define IVAS_C_SLOW_48k ( 0.999739617238810f )
      66             : #define IVAS_C_SLOW_32k ( 0.999609451284012f )
      67             : #define IVAS_C_SLOW_16k ( 0.999219055096324f )
      68             : 
      69             : /*induck*/
      70             : #define IVAS_C_IN_DUCK_48k ( 0.999583420126834f )
      71             : #define IVAS_C_IN_DUCK_32k ( 0.999375195271816f )
      72             : #define IVAS_C_IN_DUCK_16k ( 0.998750780924581f )
      73             : 
      74             : /*outduck*/
      75             : #define IVAS_C_OUT_DUCK_48k ( 0.999583420126834f )
      76             : #define IVAS_C_OUT_DUCK_32k ( 0.999375195271816f )
      77             : #define IVAS_C_OUT_DUCK_16k ( 0.998750780924581f )
      78             : 
      79             : 
      80             : /*-----------------------------------------------------------------------------------------*
      81             :  * Function ivas_transient_det_init()
      82             :  *
      83             :  * Trans det init fucntion
      84             :  *-----------------------------------------------------------------------------------------*/
      85             : 
      86        5297 : static void ivas_transient_det_init(
      87             :     ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */
      88             :     const int32_t sampling_rate       /* i  : sampling rate             */
      89             : )
      90             : {
      91             :     int16_t i;
      92             :     float filt_coeff_arr[3][IVAS_BIQUAD_FILT_LEN << 1];
      93             : 
      94        5297 :     hTranDet->in_duck_gain = 1.0f;
      95        5297 :     hTranDet->out_duck_gain = 1.0f;
      96             : 
      97       21188 :     for ( i = 0; i < 3; i++ )
      98             :     {
      99       15891 :         set_zero( filt_coeff_arr[i], IVAS_BIQUAD_FILT_LEN << 1 );
     100             :     }
     101             : 
     102        5297 :     switch ( sampling_rate )
     103             :     {
     104        3311 :         case 48000:
     105             :             /*env_hpf*/
     106        3311 :             filt_coeff_arr[0][0] = IVAS_C_HPF_48k;
     107        3311 :             filt_coeff_arr[0][1] = -IVAS_C_HPF_48k;
     108        3311 :             filt_coeff_arr[0][3] = 1.0f;
     109        3311 :             filt_coeff_arr[0][4] = -IVAS_C_HPF_48k;
     110             :             /*env_fast*/
     111        3311 :             filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_48k;
     112        3311 :             filt_coeff_arr[1][3] = 1.0f;
     113        3311 :             filt_coeff_arr[1][4] = -IVAS_C_FAST_48k;
     114             :             /*env_slow*/
     115        3311 :             filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_48k;
     116        3311 :             filt_coeff_arr[2][3] = 1.0f;
     117        3311 :             filt_coeff_arr[2][4] = -IVAS_C_SLOW_48k;
     118        3311 :             hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_48k;
     119        3311 :             hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_48k;
     120        3311 :             break;
     121        1521 :         case 32000:
     122             :             /*env_hpf*/
     123        1521 :             filt_coeff_arr[0][0] = IVAS_C_HPF_32k;
     124        1521 :             filt_coeff_arr[0][1] = -IVAS_C_HPF_32k;
     125        1521 :             filt_coeff_arr[0][3] = 1.0f;
     126        1521 :             filt_coeff_arr[0][4] = -IVAS_C_HPF_32k;
     127             :             /*env_fast*/
     128        1521 :             filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_32k;
     129        1521 :             filt_coeff_arr[1][3] = 1.0f;
     130        1521 :             filt_coeff_arr[1][4] = -IVAS_C_FAST_32k;
     131             :             /*env_slow*/
     132        1521 :             filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_32k;
     133        1521 :             filt_coeff_arr[2][3] = 1.0f;
     134        1521 :             filt_coeff_arr[2][4] = -IVAS_C_SLOW_32k;
     135        1521 :             hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_32k;
     136        1521 :             hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_32k;
     137        1521 :             break;
     138         465 :         case 16000:
     139             :             /*env_hpf*/
     140         465 :             filt_coeff_arr[0][0] = IVAS_C_HPF_16k;
     141         465 :             filt_coeff_arr[0][1] = -IVAS_C_HPF_16k;
     142         465 :             filt_coeff_arr[0][3] = 1.0f;
     143         465 :             filt_coeff_arr[0][4] = -IVAS_C_HPF_16k;
     144             :             /*env_fast*/
     145         465 :             filt_coeff_arr[1][0] = 1.0f - IVAS_C_FAST_16k;
     146         465 :             filt_coeff_arr[1][3] = 1.0f;
     147         465 :             filt_coeff_arr[1][4] = -IVAS_C_FAST_16k;
     148             :             /*env_slow*/
     149         465 :             filt_coeff_arr[2][0] = 1.0f - IVAS_C_SLOW_16k;
     150         465 :             filt_coeff_arr[2][3] = 1.0f;
     151         465 :             filt_coeff_arr[2][4] = -IVAS_C_SLOW_16k;
     152         465 :             hTranDet->in_duck_coeff = IVAS_C_IN_DUCK_16k;
     153         465 :             hTranDet->out_duck_coeff = IVAS_C_OUT_DUCK_16k;
     154         465 :             break;
     155             :     }
     156             : 
     157        5297 :     ivas_filters_init( &hTranDet->env_hpf, (const float *) filt_coeff_arr[0], IVAS_FILTER_ORDER_1 );
     158        5297 :     ivas_filters_init( &hTranDet->env_fast, (const float *) filt_coeff_arr[1], IVAS_FILTER_ORDER_1 );
     159        5297 :     ivas_filters_init( &hTranDet->env_slow, (const float *) filt_coeff_arr[2], IVAS_FILTER_ORDER_1 );
     160             : 
     161        5297 :     hTranDet->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC;
     162             : 
     163        5297 :     return;
     164             : }
     165             : 
     166             : 
     167             : /*-------------------------------------------------------------------------
     168             :  * ivas_transient_det_open()
     169             :  *
     170             :  * Allocate and initialize SPAR TD handle
     171             :  *------------------------------------------------------------------------*/
     172             : 
     173        5297 : ivas_error ivas_transient_det_open(
     174             :     ivas_trans_det_state_t **hTranDet_in, /* i/o: Transient detector handle */
     175             :     const int32_t sampling_rate           /* i  : sampling rate             */
     176             : )
     177             : {
     178             :     ivas_trans_det_state_t *hTranDet;
     179             : 
     180        5297 :     if ( ( hTranDet = (ivas_trans_det_state_t *) malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL )
     181             :     {
     182           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR TD\n" );
     183             :     }
     184             : 
     185        5297 :     ivas_transient_det_init( hTranDet, sampling_rate );
     186             : 
     187        5297 :     *hTranDet_in = hTranDet;
     188             : 
     189        5297 :     return IVAS_ERR_OK;
     190             : }
     191             : 
     192             : 
     193             : /*-------------------------------------------------------------------------
     194             :  * ivas_transient_det_close()
     195             :  *
     196             :  * Deallocate and initialize Transient detector handle
     197             :  *------------------------------------------------------------------------*/
     198             : 
     199        5297 : void ivas_transient_det_close(
     200             :     ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */
     201             : )
     202             : {
     203        5297 :     if ( hTranDet == NULL || *hTranDet == NULL )
     204             :     {
     205           0 :         return;
     206             :     }
     207             : 
     208        5297 :     free( *hTranDet );
     209        5297 :     *hTranDet = NULL;
     210             : 
     211        5297 :     return;
     212             : }
     213             : 
     214             : 
     215             : /*-----------------------------------------------------------------------------------------*
     216             :  * Function ivas_transient_det_process()
     217             :  *
     218             :  * Transient detection process call
     219             :  *-----------------------------------------------------------------------------------------*/
     220             : 
     221      165820 : void ivas_transient_det_process(
     222             :     ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle            */
     223             :     float *pIn_pcm,                   /* i  : input audio channels      */
     224             :     const int16_t frame_len,          /* i  : frame length in samples   */
     225             :     int16_t transient_det[2]          /* o  : transient det outputs     */
     226             : )
     227             : {
     228             :     float in_duck_gain[L_FRAME48k];
     229             :     int16_t num_sf, sf, sf_samp, idx;
     230      165820 :     float mem = hTranDet->in_duck_gain;
     231             : 
     232      165820 :     ivas_td_decorr_get_ducking_gains( hTranDet, pIn_pcm, in_duck_gain, NULL, frame_len, IVAS_TDET_ONLY );
     233             : 
     234      165820 :     transient_det[0] = 0;
     235      165820 :     transient_det[1] = 0;
     236      165820 :     if ( mem - hTranDet->in_duck_gain > IVAS_TDET_PARM_TRANS_THR )
     237             :     {
     238       16926 :         transient_det[0] = 1;
     239             :     }
     240             : 
     241      165820 :     num_sf = 16;
     242      165820 :     sf_samp = frame_len / num_sf;
     243     2818940 :     for ( sf = 1; sf <= num_sf; sf++ )
     244             :     {
     245     2653120 :         idx = ( sf_samp * sf ) - 1;
     246     2653120 :         if ( ( mem - in_duck_gain[idx] ) > ( IVAS_TDET_PARM_TRANS_THR * 1.1f ) )
     247             :         {
     248        8796 :             transient_det[1] = 1;
     249             :         }
     250     2653120 :         mem = in_duck_gain[idx];
     251             :     }
     252             : 
     253      165820 :     return;
     254             : }
     255             : 
     256             : 
     257             : /*-----------------------------------------------------------------------------------------*
     258             :  * Function ivas_calc_duck_gain()
     259             :  *
     260             :  * Calculate ducking gain utility
     261             :  *-----------------------------------------------------------------------------------------*/
     262             : 
     263   583864440 : static float ivas_calc_duck_gain(
     264             :     const float duck_gain,
     265             :     const float duck_coeff,
     266             :     const float env_1,
     267             :     const float env_2,
     268             :     const float duck_mult_fac )
     269             : {
     270             :     float duck_gain_out;
     271             : 
     272   583864440 :     duck_gain_out = ( duck_gain - 1 ) * duck_coeff + 1;
     273             : 
     274   583864440 :     if ( ( duck_mult_fac * env_1 ) < duck_gain_out * env_2 )
     275             :     {
     276    38076326 :         duck_gain_out = duck_mult_fac * ( env_1 / env_2 );
     277             :     }
     278             : 
     279   583864440 :     return duck_gain_out;
     280             : }
     281             : 
     282             : 
     283             : /*-----------------------------------------------------------------------------------------*
     284             :  * Function ivas_td_decorr_get_ducking_gains()
     285             :  *
     286             :  * Calculate in/out ducking gains
     287             :  *-----------------------------------------------------------------------------------------*/
     288             : 
     289      447268 : void ivas_td_decorr_get_ducking_gains(
     290             :     ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */
     291             :     float *pIn_pcm,
     292             :     float *pIn_duck_gains,
     293             :     float *pOut_duck_gains,
     294             :     const int16_t frame_len,
     295             :     const int16_t tdet_flag )
     296             : {
     297             :     int16_t i;
     298             :     float e_fast[L_FRAME48k], e_slow[L_FRAME48k];
     299      447268 :     float in_duck_gain = hTranDet->in_duck_gain;
     300      447268 :     float out_duck_gain = hTranDet->out_duck_gain;
     301      447268 :     float in_duck_coeff = hTranDet->in_duck_coeff;
     302      447268 :     float out_duck_coeff = hTranDet->out_duck_coeff;
     303      447268 :     float duck_mult_fac = hTranDet->duck_mult_fac;
     304             : 
     305      447268 :     mvr2r( pIn_pcm, e_fast, frame_len );
     306             : 
     307             :     /* env hpf */
     308      447268 :     ivas_filter_process( &hTranDet->env_hpf, e_fast, frame_len );
     309             : 
     310   356853088 :     for ( i = 0; i < frame_len; i++ )
     311             :     {
     312   356405820 :         e_fast[i] = (float) fabs( e_fast[i] ) + IVAS_TDET_PARM_ENV_EPS;
     313   356405820 :         e_slow[i] = e_fast[i];
     314             :     }
     315             : 
     316             :     /* env fast*/
     317      447268 :     ivas_filter_process( &hTranDet->env_fast, e_fast, frame_len );
     318             : 
     319             :     /* env slow */
     320      447268 :     ivas_filter_process( &hTranDet->env_slow, e_slow, frame_len );
     321             : 
     322      447268 :     if ( tdet_flag )
     323             :     {
     324   129113020 :         for ( i = 0; i < frame_len; i++ )
     325             :         {
     326   128947200 :             in_duck_gain = ivas_calc_duck_gain( in_duck_gain, in_duck_coeff, e_slow[i], e_fast[i], duck_mult_fac );
     327   128947200 :             pIn_duck_gains[i] = in_duck_gain;
     328             :         }
     329      165820 :         hTranDet->in_duck_gain = in_duck_gain;
     330             :     }
     331             :     else
     332             :     {
     333   227740068 :         for ( i = 0; i < frame_len; i++ )
     334             :         {
     335   227458620 :             in_duck_gain = ivas_calc_duck_gain( in_duck_gain, in_duck_coeff, e_slow[i], e_fast[i], duck_mult_fac );
     336   227458620 :             pIn_duck_gains[i] = in_duck_gain;
     337   227458620 :             out_duck_gain = ivas_calc_duck_gain( out_duck_gain, out_duck_coeff, e_fast[i], e_slow[i], duck_mult_fac );
     338   227458620 :             pOut_duck_gains[i] = out_duck_gain;
     339             :         }
     340      281448 :         hTranDet->in_duck_gain = in_duck_gain;
     341      281448 :         hTranDet->out_duck_gain = out_duck_gain;
     342             :     }
     343             : 
     344      447268 :     return;
     345             : }

Generated by: LCOV version 1.14