LCOV - code coverage report
Current view: top level - lib_rend - ivas_reverb_utils_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 0 100 0.0 %
Date: 2025-05-03 01:55:50 Functions: 0 3 0.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_fx.h"
      36             : #include "ivas_prot_rend_fx.h"
      37             : #include "ivas_rom_rend.h"
      38             : #include <math.h>
      39             : #include "wmc_auto.h"
      40             : #include "options_warnings.h"
      41             : 
      42             : /*-----------------------------------------------------------------------------------------*
      43             :  * Local constants
      44             :  *-----------------------------------------------------------------------------------------*/
      45             : 
      46             : #define DEFAULT_SRC_DIST          ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */
      47             : #define MAX_SAMPLING_RATE         ( 48000 )
      48             : #define CLDFB_CONVOLVER_NTAPS_MAX ( 16 )
      49             : #define FFT_SPECTRUM_SIZE         ( 1 + ( RV_FILTER_MAX_FFT_SIZE / 2 ) )
      50             : 
      51             : #define N_INITIAL_IGNORED_FRAMES 4
      52             : 
      53             : /*-----------------------------------------------------------------------------------------*
      54             :  * Local function prototypes
      55             :  *-----------------------------------------------------------------------------------------*/
      56             : 
      57             : typedef struct cldfb_convolver_state
      58             : {
      59             :     const float *filter_taps_left_re[CLDFB_NO_CHANNELS_MAX];
      60             :     const float *filter_taps_left_im[CLDFB_NO_CHANNELS_MAX];
      61             :     const float *filter_taps_right_re[CLDFB_NO_CHANNELS_MAX];
      62             :     const float *filter_taps_right_im[CLDFB_NO_CHANNELS_MAX];
      63             :     float filter_states_re[BINAURAL_CONVBANDS][CLDFB_CONVOLVER_NTAPS_MAX];
      64             :     float filter_states_im[BINAURAL_CONVBANDS][CLDFB_CONVOLVER_NTAPS_MAX];
      65             : } cldfb_convolver_state;
      66             : 
      67             : static ivas_error ivas_reverb_get_fastconv_hrtf_set_energies( const HRTFS_FASTCONV_HANDLE hHrtfFastConv, const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right );
      68             : 
      69             : 
      70             : /*-----------------------------------------------------------------------------------------*
      71             :  * Function ivas_reverb_prepare_cldfb_params()
      72             :  *
      73             :  * Prepares reverb parameters for CLDFB-based reverberator
      74             :  *-----------------------------------------------------------------------------------------*/
      75             : 
      76           0 : ivas_error ivas_reverb_prepare_cldfb_params(
      77             :     IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pInput_params,
      78             :     const HRTFS_FASTCONV_HANDLE hHrtfFastConv,
      79             :     const AUDIO_CONFIG input_audio_config,
      80             :     const int16_t use_brir,
      81             :     const int32_t output_Fs,
      82             :     float *pOutput_t60,
      83             :     float *pOutput_ene )
      84             : {
      85             :     int16_t idx;
      86             :     float fc[CLDFB_NO_CHANNELS_MAX];
      87             :     float avg_pwr_left[CLDFB_NO_CHANNELS_MAX];
      88             :     float avg_pwr_right[CLDFB_NO_CHANNELS_MAX];
      89             :     float delay_diff, ln_1e6_inverted, exp_argument;
      90           0 :     const float dist = DEFAULT_SRC_DIST;
      91           0 :     const float dmx_gain_2 = 4.0f * EVS_PI * dist * dist / 0.001f;
      92             :     ivas_error error;
      93             : 
      94           0 :     for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
      95             :     {
      96           0 :         fc[idx] = ( (float) idx + 0.5f ) * ( (float) MAX_SAMPLING_RATE / (float) ( 2 * CLDFB_NO_CHANNELS_MAX ) );
      97             :     }
      98           0 :     Word32 *fc_fx = (Word32 *) malloc( pInput_params->nBands * sizeof( Word32 * ) );
      99           0 :     Word32 *pOutput_t60_fx = (Word32 *) malloc( pInput_params->nBands * sizeof( Word32 * ) );
     100           0 :     Word16 *pOutput_t60_e = (Word16 *) malloc( pInput_params->nBands * sizeof( Word16 * ) );
     101           0 :     Word32 *pOutput_ene_fx = (Word32 *) malloc( pInput_params->nBands * sizeof( Word32 * ) );
     102           0 :     Word16 *pOutput_ene_e = (Word16 *) malloc( pInput_params->nBands * sizeof( Word16 * ) );
     103             :     Word32 delay_diff_fx;
     104             : 
     105           0 :     for ( int i = 0; i < pInput_params->nBands; i++ )
     106             :     {
     107           0 :         fc_fx[i] = (Word32) fc[i] * ONE_IN_Q16;
     108             :     }
     109             : 
     110           0 :     ivas_reverb_interpolate_acoustic_data_fx( pInput_params->nBands, pInput_params->pFc_input_fx, pInput_params->pAcoustic_rt60_fx, pInput_params->pAcoustic_dsr_fx,
     111             :                                               CLDFB_NO_CHANNELS_MAX, fc_fx, pOutput_t60_fx, pOutput_ene_fx, pOutput_t60_e, pOutput_ene_e );
     112             : 
     113             :     /* adjust DSR for the delay difference */
     114           0 :     delay_diff_fx = L_sub( pInput_params->inputPreDelay_fx, pInput_params->acousticPreDelay_fx );
     115             : 
     116           0 :     delay_diff = (float) delay_diff_fx / ONE_IN_Q27;
     117           0 :     for ( int i = 0; i < pInput_params->nBands; i++ )
     118             :     {
     119           0 :         pOutput_t60[i] = (float) fabs( me2f( pOutput_t60_fx[i], pOutput_t60_e[i] ) );
     120           0 :         pOutput_ene[i] = (float) fabs( me2f( pOutput_ene_fx[i], pOutput_ene_e[i] ) );
     121             :     }
     122           0 :     free( fc_fx );
     123           0 :     free( pOutput_t60_fx );
     124           0 :     free( pOutput_t60_e );
     125           0 :     free( pOutput_ene_fx );
     126           0 :     free( pOutput_ene_e );
     127           0 :     ln_1e6_inverted = 1.0f / logf( 1e06f );
     128           0 :     for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
     129             :     {
     130           0 :         exp_argument = delay_diff / ( pOutput_t60[idx] * ln_1e6_inverted );
     131             :         /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */
     132           0 :         exp_argument = min( exp_argument, 23.0f );
     133           0 :         exp_argument = max( exp_argument, -23.0f );
     134           0 :         pOutput_ene[idx] *= expf( exp_argument );
     135             :     }
     136             : 
     137           0 :     if ( ( error = ivas_reverb_get_fastconv_hrtf_set_energies( hHrtfFastConv, input_audio_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ) ) != IVAS_ERR_OK )
     138             :     {
     139           0 :         return error;
     140             :     }
     141             : 
     142           0 :     for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
     143             :     {
     144           0 :         pOutput_ene[idx] *= 0.5f * ( avg_pwr_left[idx] + avg_pwr_right[idx] ) * dmx_gain_2;
     145             :     }
     146             : 
     147           0 :     return IVAS_ERR_OK;
     148             : }
     149             : 
     150             : 
     151             : /*-----------------------------------------------------------------------------------------*
     152             :  * Function ivas_cldfb_convolver()
     153             :  *
     154             :  * Function for convolving CLDFB-domain data with filter taps
     155             :  *-----------------------------------------------------------------------------------------*/
     156             : 
     157             : 
     158             : /*-----------------------------------------------------------------------------------------*
     159             :  * Function get_IR_from_filter_taps()
     160             :  *
     161             :  * Function converts CLDFB filter taps into time-domain data
     162             :  *-----------------------------------------------------------------------------------------*/
     163             : 
     164             : 
     165             : /*-----------------------------------------------------------------------------------------*
     166             :  * Function ivas_reverb_get_cldfb_hrtf_set_properties()
     167             :  *
     168             :  * Function analyses the HRTF set and computes avarage left/right power spectrum
     169             :  *   and frequency-dependent IA coherence.
     170             :  *  Uses fastconv renderer filter taps to compute energies
     171             :  *-----------------------------------------------------------------------------------------*/
     172             : 
     173           0 : static ivas_error ivas_reverb_get_cldfb_hrtf_set_properties(
     174             :     AUDIO_CONFIG input_audio_config,
     175             :     const HRTFS_FASTCONV_HANDLE hHrtfFastConv,
     176             :     const int16_t use_brir,
     177             :     const int32_t sampling_rate,
     178             :     float *avg_pwr_left,
     179             :     float *avg_pwr_right )
     180             : {
     181             :     float current_HRTF_data_L[L_FRAME48k];
     182             :     float current_HRTF_data_R[L_FRAME48k];
     183             :     int16_t freq_idx, hrtf_idx, hrtf_count;
     184             :     float hrtf_count_inverted;
     185             :     int16_t fft_size, log2_fft_size, half_fft_size, freq_count;
     186             :     ivas_error error;
     187             :     UNUSED_PARAM( error );
     188           0 :     fft_size = RV_FILTER_MAX_FFT_SIZE;
     189             :     Word16 IR_length;
     190           0 :     IR_length = CLDFB_NO_CHANNELS_MAX * ( ( fft_size + CLDFB_NO_CHANNELS_MAX - 1 ) / CLDFB_NO_CHANNELS_MAX );
     191           0 :     log2_fft_size = int_log2( fft_size );
     192           0 :     half_fft_size = fft_size >> 1;
     193           0 :     freq_count = 1 + half_fft_size;
     194             : 
     195             :     /* chosing between ambisonics, 5.1 and 7.1 MC audio */
     196           0 :     if ( ( input_audio_config == IVAS_AUDIO_CONFIG_FOA ) || ( input_audio_config == IVAS_AUDIO_CONFIG_HOA2 ) || ( input_audio_config == IVAS_AUDIO_CONFIG_HOA3 ) )
     197             :     {
     198           0 :         hrtf_count = 1;
     199             :     }
     200           0 :     else if ( input_audio_config == IVAS_AUDIO_CONFIG_7_1 )
     201             :     {
     202           0 :         hrtf_count = 7;
     203             :     }
     204             :     else
     205             :     {
     206           0 :         hrtf_count = 5;
     207           0 :         input_audio_config = IVAS_AUDIO_CONFIG_5_1;
     208             :     }
     209             : 
     210             :     /* Zeroing before accumalation for average value computing */
     211           0 :     for ( freq_idx = 0; freq_idx < freq_count; freq_idx++ )
     212             :     {
     213           0 :         avg_pwr_left[freq_idx] = 0.0f;
     214           0 :         avg_pwr_right[freq_idx] = 0.0f;
     215             :     }
     216             : 
     217             :     /* Get power spectra and cross - correlation between left and right hrtfs
     218             :        Loop over all the HRTFs available  */
     219           0 :     for ( hrtf_idx = 0; hrtf_idx < hrtf_count; hrtf_idx++ )
     220             :     {
     221             :         UNUSED_PARAM( hHrtfFastConv );
     222             :         UNUSED_PARAM( use_brir );
     223             :         UNUSED_PARAM( sampling_rate );
     224             :         UNUSED_PARAM( IR_length );
     225             : 
     226             :         /* Perform forward FFT on both L/R channels */
     227           0 :         fft_rel( current_HRTF_data_L, (int16_t) fft_size, (int16_t) log2_fft_size );
     228           0 :         fft_rel( current_HRTF_data_R, (int16_t) fft_size, (int16_t) log2_fft_size );
     229             : 
     230             :         /* Process the DC bin (without img part) */
     231           0 :         avg_pwr_left[0] += current_HRTF_data_L[0] * current_HRTF_data_L[0];
     232           0 :         avg_pwr_right[0] += current_HRTF_data_R[0] * current_HRTF_data_R[0];
     233             : 
     234             :         /* Process the Nyquist frequency bin (without img part) */
     235           0 :         avg_pwr_left[half_fft_size] += current_HRTF_data_L[half_fft_size] * current_HRTF_data_L[half_fft_size];
     236           0 :         avg_pwr_right[half_fft_size] += current_HRTF_data_R[half_fft_size] * current_HRTF_data_R[half_fft_size];
     237             : 
     238             :         /* Process the other frequency bins containing both real and img parts */
     239           0 :         for ( freq_idx = 1; freq_idx < half_fft_size; freq_idx++ )
     240             :         {
     241             :             float L_re, L_im, R_re, R_im;
     242           0 :             L_re = current_HRTF_data_L[freq_idx];
     243           0 :             R_re = current_HRTF_data_R[freq_idx];
     244           0 :             L_im = current_HRTF_data_L[fft_size - freq_idx];
     245           0 :             R_im = current_HRTF_data_R[fft_size - freq_idx];
     246             : 
     247           0 :             avg_pwr_left[freq_idx] += L_re * L_re + L_im * L_im;
     248           0 :             avg_pwr_right[freq_idx] += R_re * R_re + R_im * R_im;
     249             :         }
     250             :     }
     251             : 
     252             :     /* Compute the averages and the IA coherence */
     253           0 :     hrtf_count_inverted = 1.0f / (float) hrtf_count;
     254           0 :     for ( freq_idx = 0; freq_idx < freq_count; freq_idx++ )
     255             :     {
     256           0 :         avg_pwr_left[freq_idx] *= hrtf_count_inverted;
     257           0 :         avg_pwr_right[freq_idx] *= hrtf_count_inverted;
     258             :     }
     259             : 
     260           0 :     return IVAS_ERR_OK;
     261             : }
     262             : 
     263             : 
     264             : /*-----------------------------------------------------------------------------------------*
     265             :  * Function ivas_reverb_get_fastconv_hrtf_set_energies()
     266             :  *
     267             :  * Function analyses the HRTF set and computes avarage left/right power spectrum.
     268             :  * Uses fastconv renderer filter taps to compute energies. Output interpolated
     269             :  * to CLDFB bin center frequencies
     270             :  *-----------------------------------------------------------------------------------------*/
     271             : 
     272           0 : static ivas_error ivas_reverb_get_fastconv_hrtf_set_energies(
     273             :     const HRTFS_FASTCONV_HANDLE hHrtfFastConv,
     274             :     const AUDIO_CONFIG input_audio_config,
     275             :     const int16_t use_brir,
     276             :     const int32_t sampling_rate,
     277             :     float *avg_pwr_left,
     278             :     float *avg_pwr_right )
     279             : {
     280             :     int16_t freq_idx;
     281             :     float avg_pwr_left_fft[FFT_SPECTRUM_SIZE];
     282             :     float avg_pwr_right_fft[FFT_SPECTRUM_SIZE];
     283             :     float input_fc[FFT_SPECTRUM_SIZE];
     284             :     ivas_error error;
     285             : 
     286           0 :     for ( freq_idx = 0; freq_idx < FFT_SPECTRUM_SIZE; freq_idx++ )
     287             :     {
     288           0 :         input_fc[freq_idx] = freq_idx * ( 0.5f * sampling_rate / (float) ( FFT_SPECTRUM_SIZE - 1 ) );
     289             :     }
     290             : 
     291             : 
     292           0 :     if ( ( error = ivas_reverb_get_cldfb_hrtf_set_properties( input_audio_config, hHrtfFastConv, use_brir, sampling_rate, avg_pwr_left_fft, avg_pwr_right_fft ) ) != IVAS_ERR_OK )
     293             :     {
     294           0 :         return error;
     295             :     }
     296           0 :     Word32 *input_fc_fx = (Word32 *) malloc( 60 * sizeof( Word32 * ) );
     297           0 :     Word32 *avg_pwr_left_fft_fx = (Word32 *) malloc( 60 * sizeof( Word32 * ) );
     298           0 :     Word32 *avg_pwr_right_fft_fx = (Word32 *) malloc( 60 * sizeof( Word32 * ) );
     299             : 
     300           0 :     Word32 *output_fc_fx = (Word32 *) malloc( 257 * sizeof( Word32 * ) );
     301           0 :     Word32 *avg_pwr_left_fx = (Word32 *) malloc( 257 * sizeof( Word32 * ) );
     302           0 :     Word16 *avg_pwr_left_e = (Word16 *) malloc( 257 * sizeof( Word16 * ) );
     303           0 :     Word32 *avg_pwr_right_fx = (Word32 *) malloc( 257 * sizeof( Word32 * ) );
     304           0 :     Word16 *avg_pwr_right_e = (Word16 *) malloc( 257 * sizeof( Word16 * ) );
     305             : 
     306           0 :     for ( int i = 0; i < 60; i++ )
     307             :     {
     308           0 :         input_fc_fx[i] = (Word32) input_fc[i] * ( 1 << 16 );
     309           0 :         avg_pwr_left_fft_fx[i] = (Word32) ( avg_pwr_left_fft[i] ) * ONE_IN_Q26;
     310           0 :         avg_pwr_right_fft_fx[i] = (Word32) avg_pwr_right_fft[i] * ONE_IN_Q30;
     311             :     }
     312             : 
     313           0 :     for ( int i = 0; i < 257; i++ )
     314             :     {
     315           0 :         output_fc_fx[i] = (Word32) input_fc[i] * ONE_IN_Q16;
     316             :     }
     317             : 
     318           0 :     ivas_reverb_interpolate_acoustic_data_fx( FFT_SPECTRUM_SIZE, input_fc_fx, avg_pwr_left_fft_fx, avg_pwr_right_fft_fx,
     319             :                                               CLDFB_NO_CHANNELS_MAX, output_fc_fx, avg_pwr_left_fx, avg_pwr_right_fx, avg_pwr_left_e, avg_pwr_right_e );
     320           0 :     for ( int i = 0; i < 257; i++ )
     321             :     {
     322           0 :         avg_pwr_left[i] = (float) fabs( me2f( avg_pwr_left_fx[i], avg_pwr_left_e[i] ) );
     323           0 :         avg_pwr_right[i] = (float) fabs( me2f( avg_pwr_right_fx[i], avg_pwr_right_e[i] ) );
     324             :     }
     325           0 :     free( input_fc_fx );
     326           0 :     free( avg_pwr_left_fft_fx );
     327           0 :     free( avg_pwr_right_fft_fx );
     328           0 :     free( output_fc_fx );
     329           0 :     free( avg_pwr_left_fx );
     330           0 :     free( avg_pwr_left_e );
     331           0 :     free( avg_pwr_right_fx );
     332           0 :     free( avg_pwr_right_e );
     333           0 :     return IVAS_ERR_OK;
     334             : }

Generated by: LCOV version 1.14