LCOV - code coverage report
Current view: top level - lib_rend - ivas_reverb_fft_filter.c (source / functions) Hit Total Coverage
Test: Coverage on main @ fec202a8f89be4a2f278a9fc377bfb58b58fab11 Lines: 119 125 95.2 %
Date: 2025-09-13 07:56:30 Functions: 11 11 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 "prot.h"
      36             : #include "ivas_prot_rend.h"
      37             : #ifdef DEBUGGING
      38             : #include "debug.h"
      39             : #endif
      40             : #include <math.h>
      41             : #include "wmc_auto.h"
      42             : 
      43             : 
      44             : /*------------------------------------------------------------------------------------------*
      45             :  * Static functions declarations
      46             :  *------------------------------------------------------------------------------------------*/
      47             : 
      48             : static void fft_wrapper_2ch( float *buffer_L, float *buffer_R, const int16_t fft_size );
      49             : 
      50             : static void ifft_wrapper_2ch( float *buffer_L, float *buffer_R, const int16_t fft_size );
      51             : 
      52             : 
      53             : /*-----------------------------------------------------------------------------------------*
      54             :  * Function int_log2()
      55             :  *
      56             :  * takes integer log2 of power_of_2 input value. e.g. int_log2(1024) = 10
      57             :  * powerOf2 must be a power of two between 2^0 and 2^15
      58             :  * NOT valid for integers thar are NOT a power of 2
      59             :  *-----------------------------------------------------------------------------------------*/
      60             : 
      61             : /*! r: integer log2 */
      62       58660 : uint16_t int_log2(
      63             :     uint32_t powerOf2 )
      64             : {
      65       58660 :     int16_t l2 = 15;
      66             : 
      67       58660 :     if ( powerOf2 & 0x00FF )
      68             :     {
      69           0 :         l2 -= 8;
      70             :     }
      71             : 
      72       58660 :     if ( powerOf2 & 0x0F0F )
      73             :     {
      74       58660 :         l2 -= 4;
      75             :     }
      76             : 
      77       58660 :     if ( powerOf2 & 0x3333 )
      78             :     {
      79       58660 :         l2 -= 2;
      80             :     }
      81             : 
      82       58660 :     if ( powerOf2 & 0x5555 )
      83             :     {
      84       21393 :         l2 -= 1;
      85             :     }
      86             : 
      87       58660 :     return l2;
      88             : }
      89             : 
      90             : 
      91             : /*-----------------------------------------------------------------------------------------*
      92             :  * Function fft_wrapper_2ch()
      93             :  *
      94             :  * Wrapper uses complex FFT to perform real-input FFT on 2 channels simultaneously
      95             :  *-----------------------------------------------------------------------------------------*/
      96             : 
      97     7814825 : static void fft_wrapper_2ch(
      98             :     float *buffer_L,
      99             :     float *buffer_R,
     100             :     const int16_t fft_size )
     101             : {
     102     7814825 :     const int16_t half_sz = fft_size >> 1;
     103             :     int16_t k, mirror_k;
     104             :     float left_re, left_im, right_re, right_im;
     105             : 
     106     7814825 :     DoRTFTn( buffer_L, buffer_R, fft_size );
     107             : 
     108             :     /* separating left and right channel spectra */
     109  1690355456 :     for ( k = 1; k < half_sz; k++ )
     110             :     {
     111  1682540631 :         mirror_k = fft_size - k;
     112             : 
     113  1682540631 :         left_re = 0.5f * ( buffer_L[k] + buffer_L[mirror_k] );
     114  1682540631 :         left_im = 0.5f * ( buffer_R[k] - buffer_R[mirror_k] );
     115             : 
     116  1682540631 :         right_re = 0.5f * ( buffer_R[k] + buffer_R[mirror_k] );
     117  1682540631 :         right_im = -0.5f * ( buffer_L[k] - buffer_L[mirror_k] );
     118             : 
     119  1682540631 :         buffer_L[k] = left_re;
     120  1682540631 :         buffer_R[k] = right_re;
     121  1682540631 :         buffer_L[mirror_k] = left_im;
     122  1682540631 :         buffer_R[mirror_k] = right_im;
     123             :     }
     124             : 
     125     7814825 :     return;
     126             : }
     127             : 
     128             : /*-----------------------------------------------------------------------------------------*
     129             :  * Function ifft_wrapper_2ch()
     130             :  *
     131             :  * Wrapper uses complex FFT to perform real-output IFFT on 2 channels simultaneously
     132             :  *-----------------------------------------------------------------------------------------*/
     133             : 
     134     7814825 : static void ifft_wrapper_2ch(
     135             :     float *buffer_L,
     136             :     float *buffer_R,
     137             :     const int16_t fft_size )
     138             : {
     139             :     float buffer_L_re, buffer_L_im, buffer_R_re, buffer_R_im;
     140     7814825 :     const int16_t half_sz = fft_size >> 1;
     141     7814825 :     const float inv_sz = 1.0f / (float) fft_size;
     142             :     int16_t k, mirror_k;
     143             : 
     144             :     /* Re-arranging and adding spectra in order to obtain L/R signals as re/im ifft outputs */
     145  1690355456 :     for ( k = 1; k < half_sz; k++ )
     146             :     {
     147  1682540631 :         mirror_k = fft_size - k;
     148             : 
     149  1682540631 :         buffer_L_re = buffer_L[k];
     150  1682540631 :         buffer_L_im = buffer_L[mirror_k];
     151  1682540631 :         buffer_R_re = buffer_R[k];
     152  1682540631 :         buffer_R_im = buffer_R[mirror_k];
     153             : 
     154  1682540631 :         buffer_L[k] = buffer_L_re + buffer_R_im;
     155  1682540631 :         buffer_L[mirror_k] = buffer_L_re - buffer_R_im;
     156  1682540631 :         buffer_R[k] = buffer_R_re - buffer_L_im;
     157  1682540631 :         buffer_R[mirror_k] = buffer_R_re + buffer_L_im;
     158             :     }
     159             : 
     160     7814825 :     DoRTFTn( buffer_L, buffer_R, fft_size );
     161             : 
     162             :     /* Apply (1/length) scaling for inverse FFT */
     163  3388525737 :     for ( k = 0; k < fft_size; k++ )
     164             :     {
     165  3380710912 :         buffer_L[k] *= inv_sz;
     166  3380710912 :         buffer_R[k] *= inv_sz;
     167             :     }
     168             : 
     169     7814825 :     return;
     170             : }
     171             : 
     172             : 
     173             : /*-----------------------------------------------------------------------------------------*
     174             :  * Function ivas_reverb_t2f_f2t_init()
     175             :  *
     176             :  * Initializes t2t_f2t struct and clears history
     177             :  *-----------------------------------------------------------------------------------------*/
     178             : 
     179        5804 : int16_t ivas_reverb_t2f_f2t_init(
     180             :     ivas_reverb_t2f_f2t_t *t2f_f2t,
     181             :     const int16_t fft_size,
     182             :     const int16_t block_size )
     183             : {
     184        5804 :     if ( fft_size > RV_FILTER_MAX_FFT_SIZE )
     185             :     {
     186           0 :         return 1;
     187             :     }
     188             : 
     189        5804 :     if ( ( block_size > fft_size ) || ( fft_size - block_size > RV_FILTER_MAX_HISTORY ) )
     190             :     {
     191           0 :         return 2;
     192             :     }
     193             : 
     194        5804 :     t2f_f2t->log2_fft_size = int_log2( fft_size );
     195             : 
     196        5804 :     if ( ( 1 << t2f_f2t->log2_fft_size ) != fft_size )
     197             :     {
     198           0 :         return 3; /* fft_size not a power of 2 */
     199             :     }
     200        5804 :     t2f_f2t->fft_size = fft_size;
     201        5804 :     t2f_f2t->block_size = block_size;
     202        5804 :     t2f_f2t->hist_size = t2f_f2t->fft_size - t2f_f2t->block_size;
     203             : 
     204        5804 :     if ( t2f_f2t->hist_size > RV_FILTER_MAX_HISTORY )
     205             :     {
     206           0 :         t2f_f2t->hist_size = RV_FILTER_MAX_HISTORY;
     207             :     }
     208             : 
     209        5804 :     ivas_reverb_t2f_f2t_ClearHistory( t2f_f2t );
     210             : 
     211        5804 :     return 0;
     212             : }
     213             : 
     214             : 
     215             : /*-----------------------------------------------------------------------------------------*
     216             :  * Function ivas_reverb_t2f_f2t_ClearHistory()
     217             :  *
     218             :  * Clears the history for the overlap length (fft_size - block_size)
     219             :  *-----------------------------------------------------------------------------------------*/
     220             : 
     221       11608 : void ivas_reverb_t2f_f2t_ClearHistory(
     222             :     ivas_reverb_t2f_f2t_t *t2f_f2t )
     223             : {
     224             :     int16_t i;
     225       11608 :     float *hist_L = t2f_f2t->fft_history_L;
     226       11608 :     float *hist_R = t2f_f2t->fft_history_R;
     227             : 
     228     2986680 :     for ( i = 0; i < t2f_f2t->hist_size; i++ )
     229             :     {
     230     2975072 :         hist_L[i] = 0.0f;
     231     2975072 :         hist_R[i] = 0.0f;
     232             :     }
     233             : 
     234       11608 :     return;
     235             : }
     236             : 
     237             : 
     238             : /*-----------------------------------------------------------------------------------------*
     239             :  * Function ivas_reverb_t2f_f2t_in()
     240             :  *
     241             :  * Input of block data, history is copied, fft is taken for both L/R channels
     242             :  *-----------------------------------------------------------------------------------------*/
     243             : 
     244     7814825 : void ivas_reverb_t2f_f2t_in(
     245             :     ivas_reverb_t2f_f2t_t *t2f_f2t,
     246             :     float *input_L,
     247             :     float *input_R,
     248             :     float *buffer_L,
     249             :     float *buffer_R )
     250             : {
     251             :     int16_t i;
     252     7814825 :     int16_t hlen = t2f_f2t->hist_size;
     253     7814825 :     int16_t bsiz = t2f_f2t->block_size;
     254     7814825 :     float *hist_L = t2f_f2t->fft_history_L;
     255     7814825 :     float *hist_R = t2f_f2t->fft_history_R;
     256             :     float *pL, *pR;
     257             : 
     258             :     /* copy history to buffer */
     259  2092334057 :     for ( i = 0; i < hlen; i++ )
     260             :     {
     261  2084519232 :         buffer_L[i] = hist_L[i];
     262  2084519232 :         buffer_R[i] = hist_R[i];
     263             :     }
     264             : 
     265             :     /* copy input to buffer */
     266     7814825 :     pL = &buffer_L[hlen];
     267     7814825 :     pR = &buffer_R[hlen];
     268  1304006505 :     for ( i = 0; i < bsiz; i++ )
     269             :     {
     270  1296191680 :         pL[i] = input_L[i];
     271  1296191680 :         pR[i] = input_R[i];
     272             :     }
     273             : 
     274             :     /* copy buffer to history */
     275     7814825 :     pL = &buffer_L[bsiz];
     276     7814825 :     pR = &buffer_R[bsiz];
     277  2092334057 :     for ( i = 0; i < hlen; i++ )
     278             :     {
     279  2084519232 :         hist_L[i] = pL[i];
     280  2084519232 :         hist_R[i] = pR[i];
     281             :     }
     282             : 
     283             :     /* do FFT */
     284     7814825 :     fft_wrapper_2ch( buffer_L, buffer_R, t2f_f2t->fft_size );
     285             : 
     286     7814825 :     return;
     287             : }
     288             : 
     289             : 
     290             : /*-----------------------------------------------------------------------------------------*
     291             :  * Function ivas_reverb_t2f_f2t_out()
     292             :  *
     293             :  * Input of frequency domain data, IFFT, copied to output (both L & R channels)
     294             :  *-----------------------------------------------------------------------------------------*/
     295             : 
     296     7814825 : void ivas_reverb_t2f_f2t_out(
     297             :     ivas_reverb_t2f_f2t_t *t2f_f2t,
     298             :     float *buffer_L,
     299             :     float *buffer_R,
     300             :     float *output_L,
     301             :     float *output_R )
     302             : {
     303             :     int16_t i;
     304     7814825 :     float *pL = &buffer_L[t2f_f2t->hist_size];
     305     7814825 :     float *pR = &buffer_R[t2f_f2t->hist_size];
     306             : 
     307     7814825 :     ifft_wrapper_2ch( buffer_L, buffer_R, t2f_f2t->fft_size );
     308             : 
     309  1304006505 :     for ( i = 0; i < t2f_f2t->block_size; i++ )
     310             :     {
     311  1296191680 :         output_L[i] = pL[i];
     312  1296191680 :         output_R[i] = pR[i];
     313             :     }
     314             : 
     315     7814825 :     return;
     316             : }
     317             : 
     318             : 
     319             : /*-----------------------------------------------------------------------------------------*
     320             :  * Function ivas_reverb_fft_filter_init()
     321             :  *
     322             :  * Initializes filter struct
     323             :  *-----------------------------------------------------------------------------------------*/
     324             : 
     325       23216 : int16_t ivas_reverb_fft_filter_init(
     326             :     ivas_reverb_fft_filter_t *fft_filter,
     327             :     const int16_t fft_size )
     328             : {
     329       23216 :     if ( fft_size > RV_FILTER_MAX_FFT_SIZE )
     330             :     {
     331           0 :         return 1;
     332             :     }
     333             : 
     334       23216 :     fft_filter->fft_size = fft_size;
     335             : 
     336       23216 :     return 0;
     337             : }
     338             : 
     339             : 
     340             : /*-----------------------------------------------------------------------------------------*
     341             :  * Function ivas_reverb_fft_filter_ComplexMul()
     342             :  *
     343             :  * Buffer is complex multiplied with fft_filter internal coefficients
     344             :  *-----------------------------------------------------------------------------------------*/
     345             : 
     346    31259300 : void ivas_reverb_fft_filter_ComplexMul(
     347             :     ivas_reverb_fft_filter_t *fft_filter,
     348             :     float *buffer )
     349             : {
     350             :     int16_t f_spec, h, i, j;
     351             :     float *spec;
     352             :     float t;
     353             : 
     354    31259300 :     f_spec = fft_filter->fft_size;
     355    31259300 :     h = f_spec >> 1;
     356    31259300 :     spec = fft_filter->fft_spectrum;
     357             : 
     358    31259300 :     buffer[0] *= spec[0]; /* real multiply f0 DC */
     359    31259300 :     buffer[h] *= spec[h]; /* real multiply f_spec Nyquist */
     360    31259300 :     j = f_spec - 1;
     361  6761421824 :     for ( i = 1; i < h; i++ ) /*actual complex multiply in loop */
     362             :     {
     363  6730162524 :         t = buffer[i];
     364  6730162524 :         buffer[i] = t * spec[i] - buffer[j] * spec[j];
     365  6730162524 :         buffer[j] = t * spec[j] + buffer[j] * spec[i];
     366  6730162524 :         j--;
     367             :     }
     368             : 
     369    31259300 :     return;
     370             : }
     371             : 
     372             : 
     373             : /*-----------------------------------------------------------------------------------------*
     374             :  * Function ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR()
     375             :  *
     376             :  * Convert the FFTWF formatted spectrum to fft_real formatted spectrum
     377             :  *-----------------------------------------------------------------------------------------*/
     378             : 
     379       26428 : void ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR(
     380             :     rv_fftwf_type_complex *spectrum,
     381             :     float *fft_real,
     382             :     const int16_t fft_size )
     383             : {
     384             :     int16_t i, h;
     385             : 
     386       26428 :     h = fft_size >> 1;
     387       26428 :     fft_real[0] = spectrum[0][0];
     388       26428 :     fft_real[h] = spectrum[h][0];
     389     5548544 :     for ( i = 1; i < h; i++ )
     390             :     {
     391     5522116 :         fft_real[i] = spectrum[i][0];
     392     5522116 :         fft_real[fft_size - i] = spectrum[i][1];
     393             :     }
     394             : 
     395       26428 :     return;
     396             : }
     397             : 
     398             : 
     399             : /*-----------------------------------------------------------------------------------------*
     400             :  * Function ivas_reverb_fft_filter_CrossMix()
     401             :  *
     402             :  * buffer0 and 1 are cross mixed
     403             :  *-----------------------------------------------------------------------------------------*/
     404             : 
     405     7814825 : void ivas_reverb_fft_filter_CrossMix(
     406             :     float *buffer0,
     407             :     float *buffer1,
     408             :     const int16_t fft_size )
     409             : {
     410             :     float t;
     411             :     int16_t i;
     412             : 
     413  3388525737 :     for ( i = 0; i < fft_size; i++ )
     414             :     {
     415  3380710912 :         t = buffer0[i];
     416  3380710912 :         buffer0[i] = t + buffer1[i];
     417  3380710912 :         buffer1[i] = t - buffer1[i];
     418             :     }
     419             : 
     420     7814825 :     return;
     421             : }

Generated by: LCOV version 1.14