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 : }
|