LCOV - code coverage report
Current view: top level - lib_rend - ivas_objectRenderer_sfx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 86 86 100.0 %
Date: 2025-05-23 08:37:30 Functions: 3 3 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             : #include <math.h>
      36             : #include "ivas_prot_rend.h"
      37             : #include "ivas_rom_rend.h"
      38             : #include "prot.h"
      39             : #include "wmc_auto.h"
      40             : 
      41             : 
      42             : /*---------------------------------------------------------------------*
      43             :  * Local function prototypes
      44             :  *---------------------------------------------------------------------*/
      45             : 
      46             : static void sincResample( const float *input, float *output, const int16_t length_in, const int16_t length_out );
      47             : 
      48             : 
      49             : /*---------------------------------------------------------------------*
      50             :  * TDREND_Apply_ITD()
      51             :  *
      52             :  * Apply ITD by delaying late channel
      53             :  *---------------------------------------------------------------------*/
      54             : 
      55     3461327 : void TDREND_Apply_ITD(
      56             :     float *input,        /* i  : Input subframe to be time adjusted    */
      57             :     float *out_left,     /* o  : Output left channel with ITD applied  */
      58             :     float *out_right,    /* o  : Output right channel with ITD applied */
      59             :     int16_t *previtd,    /* i/o: Previous ITD value                    */
      60             :     const int16_t itd,   /* i  : Current subframe ITD value            */
      61             :     float *mem_itd,      /* i/o: ITD buffer memory                     */
      62             :     const int16_t length /* i  : Subframe length                       */
      63             : )
      64             : {
      65             :     int16_t transition_len;
      66             :     int16_t tlen1, tlen2, tlen3;
      67             :     int16_t length_in1;
      68             :     int16_t length_in2;
      69             :     int16_t currShift;
      70             :     int16_t prevShift;
      71             :     float *pstart1;
      72             :     float *pstart2;
      73             :     float *pstart3;
      74             :     float buffer[ITD_MEM_LEN + L_SUBFRAME5MS_48k];
      75             :     float *p_input;
      76             :     float *out_buf_A, *out_buf_B;
      77             : 
      78     3461327 :     push_wmops( "TDREND_Apply_ITD" );
      79             : 
      80             :     /* Prepare resampling buffer */
      81     3461327 :     mvr2r( mem_itd, buffer, ITD_MEM_LEN );          /* Retrieve memory */
      82     3461327 :     p_input = buffer + ITD_MEM_LEN;                 /* pointer to the current subframe */
      83     3461327 :     mvr2r( input, p_input, length );                /* input current subframe */
      84     3461327 :     mvr2r( buffer + length, mem_itd, ITD_MEM_LEN ); /* update memory for next frame */
      85             : 
      86     3461327 :     currShift = (int16_t) abs( itd );
      87     3461327 :     prevShift = (int16_t) abs( *previtd );
      88     3461327 :     tlen3 = max( 0, SFX_SPAT_BIN_SINC_M - currShift ); /* Make sure there is enough look-ahead for the sinc resampling */
      89     3461327 :     transition_len = length - tlen3;
      90             : 
      91     3461327 :     if ( ( ( *previtd ) * itd ) < 0 )
      92             :     {
      93             :         /* ITD sign change - apply shift on both channels */
      94       99684 :         tlen1 = (int16_t) ( ( (float) ( transition_len * prevShift ) / ( (float) ( prevShift + currShift ) ) ) + 0.5f );
      95       99684 :         tlen2 = transition_len - tlen1;
      96       99684 :         pstart1 = p_input - prevShift;
      97       99684 :         length_in1 = tlen1 + prevShift;
      98       99684 :         pstart2 = pstart1 + length_in1;
      99       99684 :         length_in2 = tlen2 - currShift;
     100       99684 :         pstart3 = pstart2 + length_in2;
     101             :     }
     102             :     else
     103             :     {
     104             :         /* ITD sign stays the same, or one of them is zero */
     105     3361643 :         tlen1 = transition_len;
     106     3361643 :         tlen2 = 0;
     107     3361643 :         pstart1 = p_input - prevShift;
     108     3361643 :         length_in1 = transition_len + prevShift - currShift;
     109     3361643 :         pstart2 = pstart1 + length_in1;
     110     3361643 :         length_in2 = 0;
     111     3361643 :         pstart3 = pstart2 + length_in2 + currShift;
     112             :     }
     113             : 
     114     3461327 :     if ( *previtd == 0 )
     115             :     {
     116      307848 :         if ( itd > 0 )
     117             :         {
     118       12031 :             out_buf_A = out_right;
     119       12031 :             out_buf_B = out_left;
     120             :         }
     121             :         else
     122             :         {
     123      295817 :             out_buf_A = out_left;
     124      295817 :             out_buf_B = out_right;
     125             :         }
     126             :     }
     127             :     else
     128             :     {
     129     3153479 :         if ( *previtd > 0 )
     130             :         {
     131     1585921 :             out_buf_A = out_right;
     132     1585921 :             out_buf_B = out_left;
     133             :         }
     134             :         else
     135             :         {
     136     1567558 :             out_buf_A = out_left;
     137     1567558 :             out_buf_B = out_right;
     138             :         }
     139             :     }
     140             : 
     141             :     /* Output buffer A */
     142     3461327 :     sincResample( pstart1, out_buf_A, length_in1, tlen1 );
     143     3461327 :     mvr2r( pstart2, out_buf_A + tlen1, length - tlen1 );
     144             : 
     145             :     /* Output buffer B */
     146     3461327 :     mvr2r( p_input, out_buf_B, tlen1 );
     147     3461327 :     sincResample( pstart2, out_buf_B + tlen1, length_in2, tlen2 );
     148     3461327 :     mvr2r( pstart3, out_buf_B + transition_len, tlen3 );
     149             : 
     150     3461327 :     *previtd = itd;
     151     3461327 :     pop_wmops();
     152     3461327 :     return;
     153             : }
     154             : 
     155             : /*---------------------------------------------------------------------*
     156             :  * sincResample()
     157             :  *
     158             :  * Resample signal (stretch/compress) to new ITD
     159             :  * The sinc resampling reads SFX_SPAT_BIN_SINC_M (5) samples outside of
     160             :  * the target frame.
     161             :  *---------------------------------------------------------------------*/
     162             : 
     163     6922654 : static void sincResample(
     164             :     const float *input,      /*i  : Input signal  */
     165             :     float *output,           /*o  : Output signal */
     166             :     const int16_t length_in, /*i  : Input length  */
     167             :     const int16_t length_out /*i  : Output length */
     168             : )
     169             : {
     170             :     int16_t snc0;
     171             :     int16_t i, j;
     172             :     int16_t t;
     173             :     float t_frac;
     174             :     float t_step;
     175             :     float tmp;
     176             :     const float *p_mid;
     177             :     const float *p_forward;
     178             :     const float *p_backward;
     179             :     const float *p_sinc_forward;
     180             :     const float *p_sinc_backward;
     181             : 
     182             :     /* avoid division by 0 */
     183     6922654 :     if ( 0 == length_out )
     184             :     {
     185     3361643 :         return;
     186             :     }
     187             : 
     188             :     /* Compute fractional time step */
     189     3561011 :     t_step = (float) ( length_in ) / (float) ( length_out );
     190     3561011 :     t_frac = 0;
     191             : 
     192   811929352 :     for ( i = 0; i < length_out; i++ )
     193             :     {
     194   808368341 :         t = (int16_t) ( t_frac + EPSILON );
     195             : 
     196             :         /* Calculate the sinc-index for the center value of the sinc */
     197   808368341 :         snc0 = (int16_t) ( ( t_frac - t + EPSILON ) * SFX_SPAT_BIN_NUM_SUBSAMPLES + 0.5f );
     198             : 
     199             :         /* Run convolution forward and backward from mid point */
     200   808368341 :         p_mid = input + t;
     201   808368341 :         p_forward = p_mid + 1;
     202   808368341 :         p_backward = p_mid - 1;
     203   808368341 :         p_sinc_forward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES - snc0;
     204   808368341 :         p_sinc_backward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES + snc0;
     205             : 
     206   808368341 :         tmp = *p_mid * SincTable[snc0]; /* Middle point */
     207  4041841705 :         for ( j = 0; j < SFX_SPAT_BIN_SINC_M - 1; j++ )
     208             :         {
     209  3233473364 :             tmp += ( *p_forward ) * ( *p_sinc_forward ) + ( *p_backward ) * ( *p_sinc_backward );
     210  3233473364 :             p_sinc_forward += SFX_SPAT_BIN_NUM_SUBSAMPLES;
     211  3233473364 :             p_sinc_backward += SFX_SPAT_BIN_NUM_SUBSAMPLES;
     212  3233473364 :             p_forward++;
     213  3233473364 :             p_backward--;
     214             :         }
     215             : 
     216   808368341 :         output[i] = tmp;
     217             : 
     218             :         /* Advance fractional time */
     219   808368341 :         t_frac += t_step;
     220             :     }
     221             : 
     222     3561011 :     return;
     223             : }
     224             : 
     225             : /*-------------------------------------------------------------------*
     226             :  * TDREND_firfilt()
     227             :  *
     228             :  * FIR filtering function
     229             :  *
     230             :  --------------------------------------------------------------------*/
     231             : 
     232     6922654 : void TDREND_firfilt(
     233             :     float *signal,                 /* i/o: Input signal / Filtered signal */
     234             :     float *filter,                 /* i/o: FIR filter                     */
     235             :     const float *filter_delta,     /* i  : FIR filter delta               */
     236             :     const int16_t intp_count,      /* i  : interpolation count            */
     237             :     float *mem,                    /* i/o: filter memory                  */
     238             :     const int16_t subframe_length, /* i  : Length of signal               */
     239             :     const int16_t filterlength,    /* i  : Filter length                  */
     240             :     const float Gain,              /* i  : Gain                           */
     241             :     const float prevGain           /* i  : Previous gain                  */
     242             : )
     243             : {
     244             :     float buffer[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 + L_SUBFRAME5MS_48k];
     245             :     float *p_signal;
     246             :     float *p_tmp;
     247             :     float *p_filter;
     248             :     float tmp;
     249             :     int16_t i, j;
     250             :     float step, gain_tmp, gain_delta;
     251             : 
     252     6922654 :     gain_delta = ( Gain - prevGain );
     253     6922654 :     step = gain_delta / ( subframe_length );
     254     6922654 :     gain_tmp = prevGain;
     255             : 
     256             :     /* Handle memory */
     257     6922654 :     p_signal = buffer + filterlength - 1;
     258     6922654 :     mvr2r( mem, buffer, filterlength - 1 );                                        /* Insert memory */
     259     6922654 :     mvr2r( signal, p_signal, subframe_length );                                    /* Insert current frame */
     260     6922654 :     mvr2r( p_signal + subframe_length - filterlength + 1, mem, filterlength - 1 ); /* Update memory for next frame */
     261             : 
     262             :     /* Convolution */
     263  1629685534 :     for ( i = 0; i < subframe_length; i++ )
     264             :     {
     265  1622762880 :         tmp = 0.0f;
     266  1622762880 :         p_tmp = p_signal + i;
     267  1622762880 :         p_filter = filter;
     268 >20684*10^7 :         for ( j = 0; j < filterlength; j++ )
     269             :         {
     270 >20522*10^7 :             tmp += ( *p_filter++ ) * ( *p_tmp-- );
     271             :         }
     272             :         /* Apply linear gain interpolation in case of abrupt gain changes */
     273  1622762880 :         gain_tmp = gain_tmp + step;
     274  1622762880 :         signal[i] = tmp * gain_tmp;
     275             : 
     276  1622762880 :         if ( i < intp_count )
     277             :         {
     278    42456554 :             v_add( filter, filter_delta, filter, filterlength );
     279             :         }
     280             :     }
     281             : 
     282     6922654 :     return;
     283             : }

Generated by: LCOV version 1.14