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 FIX_2249_MEMORY_LEAK_IN_SBA
38 : #include "ivas_rom_binaural_crend_head.h"
39 : #endif
40 : #include "ivas_cnst.h"
41 : #ifdef DEBUGGING
42 : #include "debug.h"
43 : #endif
44 : #include "math.h"
45 : #include "ivas_rom_rend.h"
46 : #include <assert.h>
47 : #include "wmc_auto.h"
48 :
49 :
50 : /* The reverberator structure implemented here is described in detail in:
51 : * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator.
52 : * Journal of the Audio Engineering Society, 59(12), 936-943. */
53 :
54 : /*-------------------------------------------------------------------------
55 : * Local constants
56 : *------------------------------------------------------------------------*/
57 :
58 : #define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */
59 :
60 : #define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */
61 :
62 : #define REV_TIME_THRESHOLD ( 0.2f )
63 :
64 : #define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */
65 : /* should be a divisor of the frame length at any sampling rate and an even number*/
66 : #define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */
67 : #define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */
68 : #define REF_LF_MIN ( 100.0f )
69 : #define REF_LF_MAX ( 250.0f )
70 : #define REF_HF_MIN ( 5000.0f )
71 : #define REF_HF_MAX ( 7950.0f )
72 : #define LF_BIAS ( 0.5f )
73 :
74 : #define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */
75 :
76 : #define IVAS_REVERB_FFT_SIZE_48K ( 512 )
77 : #define IVAS_REVERB_FFT_SIZE_32K ( 512 )
78 : #define IVAS_REVERB_FFT_SIZE_16K ( 256 )
79 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 )
80 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 )
81 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 )
82 :
83 : #define MAX_NR_OUTPUTS ( 2 )
84 :
85 : static const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 };
86 : static const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 };
87 : static const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 };
88 : static const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 };
89 :
90 : /*------------------------------------------------------------------------------------------*
91 : * Local Struct definition
92 : *------------------------------------------------------------------------------------------*/
93 :
94 : typedef struct ivas_reverb_params_t
95 : {
96 : int16_t pre_delay; /* Delay of the FDC reverb, first peak after pre_delay samples. Note that */
97 : /* there may be non-zero samples earlier due to the filters being */
98 : /* linear-phase. */
99 : int16_t nr_loops; /* Number of feedback loops (= L) */
100 : int16_t pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples. */
101 : float pLoop_feedback_matrix[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES]; /* Feedback [L][L] matrix that mixes the signals of the loops. */
102 : int16_t nr_outputs; /* Nr of signals extracted from the loops (= S). */
103 : /* Currently this is fixed to 2. */
104 : float pLoop_extract_matrix[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs. */
105 : /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback. */
106 : int16_t t60_filter_order; /* Filter order (length of vector) */
107 : float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Filters [][] in feedback loops, controlling T60. */
108 : /* In Matlab: IIR: [(2 * L) x (<order> + 1)] (odd: b-vector, even: a-vector) */
109 : /* In Matlab: FIR: [L x <order>] */
110 : float *pFc; /* Center frequencies for FFT filter design */
111 : float *pRt60; /* RT60 values at these frequencies */
112 : float *pDsr; /* DSR values at these frequencies */
113 : const float *pHrtf_avg_pwr_response_l_const; /* The HRTF set's average left ear power response */
114 : const float *pHrtf_avg_pwr_response_r_const; /* The HRTF set's average right ear power response */
115 : const float *pHrtf_inter_aural_coherence_const; /* The HRTF set's inter-aural coherence for diffuse sound */
116 :
117 : int16_t do_corr_filter; /* Flag indicating whether correlation filters should be used. */
118 : /* Correlation only supported and needed for binaural playback (i.e. */
119 : /* when nr_outputs != 2 correlation filtering is never supported). */
120 : } ivas_reverb_params_t;
121 :
122 :
123 : /*------------------------------------------------------------------------------------------*
124 : * Static functions declarations
125 : *------------------------------------------------------------------------------------------*/
126 :
127 : static ivas_error calc_jot_t60_coeffs( float *pH_dB, const uint16_t nrFrequencies, float *pFrequencies, float *pCoeffA, float *pCoeffB, const float fNyquist );
128 :
129 : #ifdef FIX_2249_MEMORY_LEAK_IN_SBA
130 :
131 : /*-------------------------------------------------------------------------
132 : * ivas_reverb_HRTF_statistics_open()
133 : *
134 : * Open and initialize HRTF statistics handle from ROM tables
135 : *------------------------------------------------------------------------*/
136 :
137 10307 : ivas_error ivas_reverb_HRTF_statistics_open(
138 : HRTFS_STATISTICS_HANDLE *hHrtfStatistics, /* o : HRTF statistics handle */
139 : const int32_t output_Fs /* i : output sampling rate */
140 : )
141 : {
142 10307 : if ( *hHrtfStatistics != NULL )
143 : {
144 696 : if ( ( *hHrtfStatistics )->fromROM == TRUE )
145 : {
146 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF statistics allocated but not initialized from binary file!\n" );
147 : }
148 :
149 : /* HRTF statistics loaded from binary file */
150 696 : return IVAS_ERR_OK;
151 : }
152 :
153 9611 : if ( ( *hHrtfStatistics = (HRTFS_STATISTICS *) malloc( sizeof( HRTFS_STATISTICS ) ) ) == NULL )
154 : {
155 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for statistics HRTF tables!" );
156 : }
157 :
158 : /* Init HRTF statistics from ROM */
159 9611 : switch ( output_Fs )
160 : {
161 3123 : case 48000:
162 3123 : ( *hHrtfStatistics )->average_energy_l = defaultHRIR_left_avg_power_48kHz;
163 3123 : ( *hHrtfStatistics )->average_energy_r = defaultHRIR_right_avg_power_48kHz;
164 3123 : ( *hHrtfStatistics )->inter_aural_coherence = defaultHRIR_coherence_48kHz;
165 3123 : break;
166 3248 : case 32000:
167 3248 : ( *hHrtfStatistics )->average_energy_l = defaultHRIR_left_avg_power_32kHz;
168 3248 : ( *hHrtfStatistics )->average_energy_r = defaultHRIR_right_avg_power_32kHz;
169 3248 : ( *hHrtfStatistics )->inter_aural_coherence = defaultHRIR_coherence_32kHz;
170 3248 : break;
171 3240 : case 16000:
172 3240 : ( *hHrtfStatistics )->average_energy_l = defaultHRIR_left_avg_power_16kHz;
173 3240 : ( *hHrtfStatistics )->average_energy_r = defaultHRIR_right_avg_power_16kHz;
174 3240 : ( *hHrtfStatistics )->inter_aural_coherence = defaultHRIR_coherence_16kHz;
175 3240 : break;
176 0 : default:
177 0 : ( *hHrtfStatistics )->average_energy_l = NULL;
178 0 : ( *hHrtfStatistics )->average_energy_r = NULL;
179 0 : ( *hHrtfStatistics )->inter_aural_coherence = NULL;
180 0 : break;
181 : }
182 :
183 9611 : ( *hHrtfStatistics )->fromROM = TRUE;
184 :
185 9611 : return IVAS_ERR_OK;
186 : }
187 :
188 : #endif
189 :
190 : /*-------------------------------------------------------------------------
191 : * binRend_rand()
192 : *
193 : *
194 : *------------------------------------------------------------------------*/
195 :
196 81676201 : static uint16_t binRend_rand(
197 : REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle */
198 : )
199 : {
200 81676201 : hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345;
201 :
202 81676201 : return (uint16_t) ( hReverb->binRend_RandNext / 65536 ) % 32768;
203 : }
204 :
205 :
206 : /*-------------------------------------------------------------------------
207 : * ivas_binaural_reverb_setPreDelay()
208 : *
209 : *
210 : *------------------------------------------------------------------------*/
211 :
212 16075 : static void ivas_binaural_reverb_setPreDelay(
213 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
214 : const int16_t delaySamples /* i : reverb pre-delay in CLDFB slots */
215 : )
216 : {
217 16075 : if ( delaySamples < 1 )
218 : {
219 0 : hReverb->preDelayBufferLength = 1;
220 :
221 0 : return;
222 : }
223 :
224 16075 : if ( delaySamples > IVAS_REVERB_PREDELAY_MAX )
225 : {
226 12 : hReverb->preDelayBufferLength = IVAS_REVERB_PREDELAY_MAX;
227 :
228 12 : return;
229 : }
230 :
231 16063 : hReverb->preDelayBufferLength = delaySamples;
232 :
233 16063 : return;
234 : }
235 :
236 :
237 : /*-------------------------------------------------------------------------
238 : * ivas_binaural_reverb_setReverbTimes()
239 : *
240 : *
241 : *------------------------------------------------------------------------*/
242 :
243 16075 : static void ivas_binaural_reverb_setReverbTimes(
244 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
245 : const int32_t output_Fs, /* i : sampling_rate */
246 : const float *revTimes, /* i : reverberation times T60 for each CLDFB bin in seconds */
247 : const float *revEnes /* i : spectrum for reverberated sound at each CLDFB bin */
248 : )
249 : {
250 : int16_t bin, ch, tap, sample;
251 : float binCenterFreq, diffuseFieldICC, tmpVal, attenuationFactorPerSample;
252 : float intendedEnergy, actualizedEnergy, energyBuildup, currentEnergy, attenuationFactorPerSampleSq;
253 :
254 16075 : hReverb->binRend_RandNext = (uint16_t) BIN_REND_RANDOM_SEED;
255 16075 : hReverb->highestBinauralCoherenceBin = 0;
256 644595 : for ( bin = 0; bin < hReverb->numBins; bin++ )
257 : {
258 : /* Determine the diffuse field binaural coherence */
259 628520 : binCenterFreq = ( (float) bin + 0.5f ) / ( (float) hReverb->numBins ) * ( (float) output_Fs ) / 2.0f;
260 628520 : if ( bin == 0 )
261 : {
262 16075 : diffuseFieldICC = 1.0f;
263 : }
264 612445 : else if ( binCenterFreq < 2700.0f )
265 : {
266 94772 : diffuseFieldICC = sinf( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) / ( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) * ( 1.0f - binCenterFreq / 2700.0f );
267 94772 : hReverb->highestBinauralCoherenceBin = bin;
268 : }
269 : else
270 : {
271 517673 : diffuseFieldICC = 0.0f;
272 : }
273 :
274 : /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */
275 628520 : tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f;
276 628520 : if ( diffuseFieldICC > 0 )
277 : {
278 62622 : hReverb->binauralCoherenceCrossmixGains[bin] = sqrtf( fabsf( tmpVal ) );
279 : }
280 : else
281 : {
282 565898 : hReverb->binauralCoherenceCrossmixGains[bin] = -sqrtf( fabsf( tmpVal ) );
283 : }
284 628520 : hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) );
285 :
286 : /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */
287 628520 : attenuationFactorPerSample = powf( 10.0f, -3.0f * ( 1.0f / ( (float) CLDFB_SLOTS_PER_SECOND * revTimes[bin] ) ) );
288 628520 : hReverb->loopAttenuationFactor[bin] = powf( attenuationFactorPerSample, hReverb->loopBufLength[bin] );
289 628520 : attenuationFactorPerSampleSq = attenuationFactorPerSample * attenuationFactorPerSample;
290 :
291 : /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved,
292 : * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */
293 628520 : intendedEnergy = 0.0f;
294 628520 : actualizedEnergy = 0.0f;
295 :
296 1885560 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
297 : {
298 1257040 : energyBuildup = 0.0f;
299 1257040 : currentEnergy = 1.0f;
300 1257040 : tap = 0;
301 :
302 64762584 : for ( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ )
303 : {
304 63505544 : intendedEnergy += currentEnergy;
305 :
306 : /* The randomization at the energy build up affects where the sparse taps are located */
307 63505544 : energyBuildup += currentEnergy + 0.1f * ( (float) binRend_rand( hReverb ) / PCM16_TO_FLT_FAC - 0.5f );
308 :
309 63505544 : if ( energyBuildup >= 1.0f ) /* A new filter tap is added at this condition */
310 : {
311 : /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */
312 18170657 : hReverb->tapPhaseShiftType[bin][ch][tap] = (int16_t) ( binRend_rand( hReverb ) % 4 );
313 : /* Set the tapPointer to point to the determined sample at the loop buffer */
314 18170657 : hReverb->tapPointersReal[bin][ch][tap] = &( hReverb->loopBufReal[bin][sample] );
315 18170657 : hReverb->tapPointersImag[bin][ch][tap] = &( hReverb->loopBufImag[bin][sample] );
316 18170657 : energyBuildup -= 1.0f; /* A tap is added, thus remove its energy from the buildup */
317 18170657 : tap++;
318 18170657 : actualizedEnergy += 1.0f;
319 : }
320 63505544 : currentEnergy *= attenuationFactorPerSampleSq;
321 : }
322 : /* In some configurations with small T60s it is possible the number of taps randomizes to zero.
323 : Ensure at least 1 filter tap. */
324 1257040 : if ( tap == 0 )
325 : {
326 0 : hReverb->tapPhaseShiftType[bin][ch][0] = (int16_t) ( binRend_rand( hReverb ) % 4 );
327 0 : hReverb->tapPointersReal[bin][ch][0] = &( hReverb->loopBufReal[bin][0] );
328 0 : hReverb->tapPointersImag[bin][ch][0] = &( hReverb->loopBufImag[bin][0] );
329 0 : tap = 1;
330 0 : actualizedEnergy = 1;
331 : }
332 :
333 1257040 : hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */
334 : }
335 :
336 : /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */
337 628520 : hReverb->reverbEqGains[bin] = sqrtf( revEnes[bin] ); /* Determined reverb spectrum */
338 628520 : hReverb->reverbEqGains[bin] *= sqrtf( intendedEnergy / actualizedEnergy ); /* Correction of random effects at the decorrelator design */
339 628520 : hReverb->reverbEqGains[bin] *= sqrtf( 0.5f * ( 1.0f - attenuationFactorPerSampleSq ) ); /* Correction of IIR decay rate */
340 : }
341 :
342 16075 : return;
343 : }
344 :
345 :
346 : /*-----------------------------------------------------------------------------------------*
347 : * Function compute_feedback_matrix()
348 : *
349 : * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again
350 : *-----------------------------------------------------------------------------------------*/
351 :
352 12409 : static ivas_error compute_feedback_matrix(
353 : float *pFeedbackMatrix,
354 : const int16_t n )
355 : {
356 : float u, v;
357 : int16_t i, j, x;
358 :
359 12409 : if ( n == 6 )
360 : {
361 : /* special case (there is no 6 x 6 Hadamard matrix in set R) */
362 0 : u = -1.0f / 3;
363 0 : v = 1.0f + u;
364 0 : for ( i = 0; i < n; i++ )
365 : {
366 0 : for ( j = 0; j < n; j++ )
367 : {
368 0 : if ( i == j )
369 : {
370 0 : pFeedbackMatrix[i * n + j] = v;
371 : }
372 : else
373 : {
374 0 : pFeedbackMatrix[i * n + j] = u;
375 : }
376 : }
377 : }
378 : }
379 : else
380 : {
381 12409 : if ( !( n == 4 || n == 8 || n == 16 ) )
382 : {
383 0 : return IVAS_ERR_INTERNAL; /* n must be 4, 6, 8 or 16, else ERROR */
384 : }
385 :
386 12409 : u = inv_sqrt( n );
387 :
388 12409 : if ( n == 4 )
389 : {
390 0 : u = -u;
391 : }
392 :
393 12409 : pFeedbackMatrix[0] = u;
394 49636 : for ( x = 1; x < n; x += x )
395 : {
396 124090 : for ( i = 0; i < x; i++ )
397 : {
398 347452 : for ( j = 0; j < x; j++ )
399 : {
400 260589 : pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j];
401 260589 : pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j];
402 260589 : pFeedbackMatrix[( i + x ) * n + j + x] = -pFeedbackMatrix[i * n + j];
403 : }
404 : }
405 : }
406 :
407 12409 : if ( n == 4 )
408 : {
409 : /* special case */
410 0 : for ( j = 12; j < 16; j++ )
411 : {
412 0 : pFeedbackMatrix[j] = -pFeedbackMatrix[j];
413 : }
414 : }
415 : }
416 :
417 12409 : return IVAS_ERR_OK;
418 : }
419 :
420 :
421 : /*-----------------------------------------------------------------------------------------*
422 : * Function compute_2_out_extract_matrix()
423 : *
424 : * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs
425 : *-----------------------------------------------------------------------------------------*/
426 :
427 12409 : static void compute_2_out_extract_matrix(
428 : float *pExtractMatrix,
429 : const int16_t n )
430 : {
431 : float ff;
432 : int16_t i;
433 :
434 12409 : ff = 1.0;
435 111681 : for ( i = 0; i < n; i++ )
436 : {
437 99272 : pExtractMatrix[i] = 1.0;
438 99272 : pExtractMatrix[i + n] = ff;
439 99272 : ff = -ff;
440 : }
441 :
442 12409 : return;
443 : }
444 :
445 :
446 : /*-----------------------------------------------------------------------------------------*
447 : * Function set_base_config()
448 : *
449 : * Set all jot reverb parameters that are independent of the input reverb configuration
450 : *-----------------------------------------------------------------------------------------*/
451 :
452 12409 : static ivas_error set_base_config(
453 : ivas_reverb_params_t *pParams,
454 : const int32_t output_Fs )
455 : {
456 : ivas_error error;
457 : int16_t loop_idx;
458 12409 : const int16_t *selected_loop_delay = NULL;
459 :
460 12409 : if ( pParams == NULL )
461 : {
462 0 : return IVAS_ERR_INTERNAL;
463 : }
464 :
465 12409 : pParams->pre_delay = 0;
466 12409 : pParams->nr_outputs = BINAURAL_CHANNELS;
467 12409 : pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES;
468 :
469 : /* set loop delays to default */
470 12409 : if ( output_Fs == 48000 )
471 : {
472 4142 : selected_loop_delay = default_loop_delay_48k;
473 : }
474 8267 : else if ( output_Fs == 32000 )
475 : {
476 4087 : selected_loop_delay = default_loop_delay_32k;
477 : }
478 4180 : else if ( output_Fs == 16000 )
479 : {
480 4180 : selected_loop_delay = default_loop_delay_16k;
481 : }
482 :
483 111681 : for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
484 : {
485 99272 : pParams->pLoop_delays[loop_idx] = selected_loop_delay[loop_idx];
486 : }
487 :
488 : /* set feedback and output matrices */
489 12409 : if ( ( error = compute_feedback_matrix( pParams->pLoop_feedback_matrix, pParams->nr_loops ) ) != IVAS_ERR_OK )
490 : {
491 0 : return error;
492 : }
493 :
494 12409 : compute_2_out_extract_matrix( pParams->pLoop_extract_matrix, pParams->nr_loops );
495 :
496 : /* pre-set the various filters; they will be set later based on reverb configuration */
497 12409 : pParams->t60_filter_order = 1; /* set to 1 in base config. */
498 :
499 12409 : if ( pParams->nr_outputs == 2 )
500 : {
501 12409 : pParams->do_corr_filter = 1;
502 : }
503 : else
504 : {
505 0 : pParams->do_corr_filter = 0;
506 : }
507 :
508 12409 : return IVAS_ERR_OK;
509 : }
510 :
511 :
512 : /*-----------------------------------------------------------------------------------------*
513 : * Function calc_dmx_gain()
514 : *
515 : * Computes the downmix gain
516 : *-----------------------------------------------------------------------------------------*/
517 :
518 8248 : static float calc_dmx_gain( void )
519 : {
520 8248 : const float dist = DEFAULT_SRC_DIST;
521 8248 : return sqrtf( 4.0f * EVS_PI * dist * dist / 0.001f );
522 : }
523 :
524 :
525 : /*-----------------------------------------------------------------------------------------*
526 : * Function calc_predelay()
527 : *
528 : * Calculate the predelay, taking shortest jot loop delay into account
529 : *-----------------------------------------------------------------------------------------*/
530 :
531 12409 : static void calc_predelay(
532 : ivas_reverb_params_t *pParams,
533 : float acoustic_predelay_sec,
534 : const int32_t output_Fs )
535 : {
536 : int16_t predelay, fbdelay, output_frame;
537 :
538 12409 : predelay = (int16_t) roundf( acoustic_predelay_sec * (float) output_Fs );
539 12409 : output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
540 12409 : fbdelay = pParams->pLoop_delays[pParams->nr_loops - 1];
541 12409 : predelay -= fbdelay;
542 :
543 12409 : if ( predelay < 0 )
544 : {
545 2005 : predelay = 0;
546 : }
547 :
548 12409 : if ( output_frame < predelay )
549 : {
550 0 : predelay = output_frame;
551 : }
552 :
553 12409 : pParams->pre_delay = predelay;
554 :
555 12409 : return;
556 : }
557 :
558 :
559 : /*-----------------------------------------------------------------------------------------*
560 : * Function compute_t60_coeffs()
561 : *
562 : * Calculate Jot reverb's T60 filter coefficients
563 : *-----------------------------------------------------------------------------------------*/
564 :
565 12409 : static ivas_error compute_t60_coeffs(
566 : ivas_reverb_params_t *pParams,
567 : const int16_t nr_fc_fft_filter,
568 : const int32_t output_Fs )
569 : {
570 : int16_t bin_idx, loop_idx, tf_T60_len, len;
571 : float loop_delay_sec, freq_Nyquist, inv_hfs;
572 : float target_gains_db[RV_LENGTH_NR_FC];
573 : float norm_f[RV_LENGTH_NR_FC];
574 : float *pCoeffs_a, *pCoeffs_b;
575 : float *targetT60, *freqT60;
576 : ivas_error error;
577 :
578 12409 : targetT60 = pParams->pRt60;
579 12409 : freqT60 = pParams->pFc;
580 :
581 12409 : error = IVAS_ERR_OK;
582 12409 : tf_T60_len = nr_fc_fft_filter;
583 12409 : len = pParams->t60_filter_order + 1;
584 12409 : freq_Nyquist = 0.5f * (float) output_Fs;
585 :
586 : /* normalize pFrequencies: 0 .. 1/2 output_Fs --> 0.0 .. 1.0 */
587 12409 : inv_hfs = 1.0f / freq_Nyquist;
588 2666482 : for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
589 : {
590 2654073 : norm_f[bin_idx] = freqT60[bin_idx] * inv_hfs;
591 : }
592 :
593 111681 : for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
594 : {
595 99272 : loop_delay_sec = (float) pParams->pLoop_delays[loop_idx] / (float) output_Fs;
596 21331856 : for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
597 : {
598 21232584 : target_gains_db[bin_idx] = -60.0f * loop_delay_sec / targetT60[bin_idx];
599 21232584 : target_gains_db[bin_idx] = max( target_gains_db[bin_idx], -120.0f );
600 : }
601 :
602 99272 : pCoeffs_a = &pParams->pT60_filter_coeff[2 * len * loop_idx + len];
603 99272 : pCoeffs_b = &pParams->pT60_filter_coeff[2 * len * loop_idx];
604 99272 : if ( ( error = calc_jot_t60_coeffs( target_gains_db, tf_T60_len, norm_f, pCoeffs_a, pCoeffs_b, freq_Nyquist ) ) != IVAS_ERR_OK )
605 : {
606 0 : return error;
607 : }
608 : }
609 :
610 12409 : len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */
611 111681 : for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
612 : {
613 99272 : pParams->pLoop_delays[loop_idx] -= len;
614 : }
615 :
616 12409 : return error;
617 : }
618 :
619 :
620 : /*-----------------------------------------------------------------------------------------*
621 : * Function calc_low_shelf_first_order_filter()
622 : *
623 : * Calculate 1st order low shelf filter
624 : *-----------------------------------------------------------------------------------------*/
625 :
626 99272 : static void calc_low_shelf_first_order_filter(
627 : float *pNum,
628 : float *pDen,
629 : const float f0,
630 : const float lin_gain_lf,
631 : const float lin_gain_hf )
632 : {
633 : float w0, gain;
634 :
635 99272 : w0 = tanf( EVS_PI * f0 / 2.0f );
636 99272 : gain = lin_gain_lf / lin_gain_hf;
637 :
638 99272 : if ( gain < 1.0f )
639 : {
640 0 : pNum[0] = 1 + w0 * gain;
641 0 : pNum[1] = w0 * gain - 1;
642 0 : pDen[0] = 1 + w0;
643 0 : pDen[1] = w0 - 1;
644 : }
645 : else
646 : {
647 99272 : pNum[0] = 1 + w0;
648 99272 : pNum[1] = w0 - 1;
649 99272 : pDen[0] = 1 + w0 / gain;
650 99272 : pDen[1] = w0 / gain - 1;
651 : }
652 :
653 : /* Normalize and adjust gain to match target amplitudes */
654 99272 : pNum[0] = ( pNum[0] / pDen[0] ) * lin_gain_hf;
655 99272 : pNum[1] = ( pNum[1] / pDen[0] ) * lin_gain_hf;
656 99272 : pDen[1] = pDen[1] / pDen[0];
657 99272 : pDen[0] = 1.0f;
658 :
659 99272 : return;
660 : }
661 :
662 :
663 : /*-----------------------------------------------------------------------------------------*
664 : * Function calc_jot_t60_coeffs()
665 : *
666 : * Calculate Jot reverb's T60 filters
667 : *-----------------------------------------------------------------------------------------*/
668 :
669 99272 : static ivas_error calc_jot_t60_coeffs(
670 : float *pH_dB,
671 : const uint16_t nrFrequencies,
672 : float *pFrequencies,
673 : float *pCoeffA,
674 : float *pCoeffB,
675 : const float fNyquist )
676 : {
677 99272 : const float ref_lf_min_norm = REF_LF_MIN / fNyquist;
678 99272 : const float ref_lf_max_norm = REF_LF_MAX / fNyquist;
679 99272 : const float ref_hf_min_norm = REF_HF_MIN / fNyquist;
680 99272 : const float ref_hf_max_norm = REF_HF_MAX / fNyquist;
681 : int16_t f_idx, minidx;
682 : float f0, tmp, minval, lf_target_gain_dB, hf_target_gain_dB, mid_crossing_gain_dB;
683 : uint16_t n_points_lf, n_points_hf;
684 : float lin_gain_lf, lin_gain_hf;
685 :
686 99272 : minidx = nrFrequencies - 1;
687 99272 : minval = 1e+20f;
688 99272 : lf_target_gain_dB = 0.0f;
689 99272 : hf_target_gain_dB = 0.0f;
690 99272 : n_points_lf = 0;
691 99272 : n_points_hf = 0;
692 :
693 21331856 : for ( f_idx = 0; f_idx < nrFrequencies; f_idx++ )
694 : {
695 21232584 : if ( ( pFrequencies[f_idx] >= ref_lf_min_norm ) && ( pFrequencies[f_idx] <= ref_lf_max_norm ) )
696 : {
697 231544 : lf_target_gain_dB += pH_dB[f_idx];
698 231544 : n_points_lf++;
699 : }
700 21232584 : if ( ( pFrequencies[f_idx] >= ref_hf_min_norm ) && ( pFrequencies[f_idx] <= ref_hf_max_norm ) )
701 : {
702 4201744 : hf_target_gain_dB += pH_dB[f_idx];
703 4201744 : n_points_hf++;
704 : }
705 : }
706 :
707 99272 : if ( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) )
708 : {
709 0 : return IVAS_ERR_INTERNAL;
710 : }
711 :
712 99272 : lf_target_gain_dB = lf_target_gain_dB / (float) n_points_lf;
713 99272 : hf_target_gain_dB = hf_target_gain_dB / (float) n_points_hf;
714 99272 : mid_crossing_gain_dB = hf_target_gain_dB + LF_BIAS * ( lf_target_gain_dB - hf_target_gain_dB );
715 :
716 21133312 : for ( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ )
717 : {
718 21034040 : tmp = fabsf( pH_dB[f_idx] - mid_crossing_gain_dB );
719 21034040 : if ( tmp < minval )
720 : {
721 1511024 : minval = tmp;
722 1511024 : minidx = f_idx;
723 : }
724 : }
725 :
726 99272 : f0 = pFrequencies[minidx];
727 99272 : lin_gain_lf = powf( 10.0f, lf_target_gain_dB * 0.05f );
728 99272 : lin_gain_hf = powf( 10.0f, hf_target_gain_dB * 0.05f );
729 :
730 : /* call low-pass iir shelf */
731 99272 : calc_low_shelf_first_order_filter( pCoeffB, pCoeffA, f0, lin_gain_lf, lin_gain_hf );
732 :
733 99272 : return IVAS_ERR_OK;
734 : }
735 :
736 :
737 : /*-----------------------------------------------------------------------------------------*
738 : * Function initialize_reverb_filters()
739 : *
740 : * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data)
741 : *-----------------------------------------------------------------------------------------*/
742 :
743 8248 : static ivas_error initialize_reverb_filters(
744 : REVERB_HANDLE hReverb )
745 : {
746 : ivas_error error;
747 :
748 : /* init correlation and coloration filters */
749 8248 : if ( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ) != IVAS_ERR_OK )
750 : {
751 0 : return error;
752 : }
753 :
754 8248 : if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ) != IVAS_ERR_OK )
755 : {
756 0 : return error;
757 : }
758 :
759 8248 : if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ) != IVAS_ERR_OK )
760 : {
761 0 : return error;
762 : }
763 :
764 8248 : if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ) != IVAS_ERR_OK )
765 : {
766 0 : return error;
767 : }
768 :
769 8248 : if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ) != IVAS_ERR_OK )
770 : {
771 0 : return error;
772 : }
773 :
774 8248 : return IVAS_ERR_OK;
775 : }
776 :
777 :
778 : /*-----------------------------------------------------------------------------------------*
779 : * Function set_t60_filter()
780 : *
781 : * Sets t60 number of taps and coefficients A and B
782 : *-----------------------------------------------------------------------------------------*/
783 :
784 99272 : static ivas_error set_t60_filter(
785 : REVERB_HANDLE hReverb,
786 : const uint16_t branch,
787 : const uint16_t nr_taps,
788 : const float coefA[],
789 : const float coefB[] )
790 : {
791 99272 : if ( branch >= hReverb->nr_of_branches )
792 : {
793 0 : return IVAS_ERR_INTERNAL;
794 : }
795 :
796 99272 : if ( nr_taps > IVAS_REV_MAX_IIR_FILTER_LENGTH )
797 : {
798 0 : return IVAS_ERR_INTERNAL;
799 : }
800 :
801 99272 : ivas_reverb_iir_filt_set( &( hReverb->t60[branch] ), nr_taps, coefA, coefB );
802 :
803 99272 : return IVAS_ERR_OK;
804 : }
805 :
806 :
807 : /*-----------------------------------------------------------------------------------------*
808 : * Function set_feedback_delay()
809 : *
810 : * Sets Delay of feedback branch in number of samples
811 : *-----------------------------------------------------------------------------------------*/
812 :
813 65984 : static ivas_error set_feedback_delay(
814 : REVERB_HANDLE hReverb,
815 : const uint16_t branch,
816 : const int16_t fb_delay )
817 : {
818 65984 : if ( branch >= hReverb->nr_of_branches )
819 : {
820 0 : return IVAS_ERR_INTERNAL;
821 : }
822 :
823 65984 : hReverb->delay_line[branch].Delay = fb_delay;
824 :
825 65984 : return IVAS_ERR_OK;
826 : }
827 :
828 :
829 : /*-----------------------------------------------------------------------------------------*
830 : * Function set_feedback_gain()
831 : *
832 : * Sets nr_of_branches feedback gain values in feedback matrix
833 : *-----------------------------------------------------------------------------------------*/
834 :
835 65984 : static ivas_error set_feedback_gain(
836 : REVERB_HANDLE hReverb,
837 : const uint16_t branch,
838 : const float *pGain )
839 : {
840 : uint16_t gain_idx;
841 65984 : if ( branch >= hReverb->nr_of_branches )
842 : {
843 0 : return IVAS_ERR_INTERNAL;
844 : }
845 :
846 593856 : for ( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ )
847 : {
848 527872 : hReverb->gain_matrix[branch][gain_idx] = pGain[gain_idx];
849 : }
850 :
851 65984 : return IVAS_ERR_OK;
852 : }
853 :
854 :
855 : /*-----------------------------------------------------------------------------------------*
856 : * Function set_correl_fft_filter()
857 : *
858 : * Sets correlation filter complex gains
859 : *-----------------------------------------------------------------------------------------*/
860 :
861 24818 : static ivas_error set_correl_fft_filter(
862 : REVERB_HANDLE hReverb,
863 : const uint16_t channel,
864 : rv_fftwf_type_complex *pSpectrum )
865 : {
866 24818 : if ( channel > 1 )
867 : {
868 0 : return IVAS_ERR_INTERNAL;
869 : }
870 :
871 24818 : if ( channel == 0 )
872 : {
873 12409 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_0.fft_spectrum, hReverb->fft_filter_correl_0.fft_size );
874 : }
875 : else
876 : {
877 12409 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_1.fft_spectrum, hReverb->fft_filter_correl_1.fft_size );
878 : }
879 :
880 24818 : return IVAS_ERR_OK;
881 : }
882 :
883 :
884 : /*-----------------------------------------------------------------------------------------*
885 : * Function set_color_fft_filter()
886 : *
887 : * Sets coloration filter complex gains
888 : *-----------------------------------------------------------------------------------------*/
889 :
890 24818 : static ivas_error set_color_fft_filter(
891 : REVERB_HANDLE hReverb,
892 : const uint16_t channel,
893 : rv_fftwf_type_complex *pSpectrum )
894 : {
895 24818 : if ( channel > 1 )
896 : {
897 0 : return IVAS_ERR_INTERNAL;
898 : }
899 :
900 24818 : if ( channel == 0 )
901 : {
902 12409 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum, hReverb->fft_filter_color_0.fft_size );
903 : }
904 : else
905 : {
906 12409 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum, hReverb->fft_filter_color_1.fft_size );
907 : }
908 :
909 24818 : return IVAS_ERR_OK;
910 : }
911 :
912 :
913 : /*-----------------------------------------------------------------------------------------*
914 : * Function set_mixer_level()
915 : *
916 : * Sets Mixer level: to mix 2 output channels from 8 feedback branches
917 : *-----------------------------------------------------------------------------------------*/
918 :
919 16496 : static ivas_error set_mixer_level(
920 : REVERB_HANDLE hReverb,
921 : const uint16_t channel,
922 : const float level[] )
923 : {
924 : uint16_t branch_idx;
925 16496 : if ( channel >= BINAURAL_CHANNELS )
926 : {
927 0 : return IVAS_ERR_INTERNAL;
928 : }
929 :
930 148464 : for ( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ )
931 : {
932 131968 : hReverb->mixer[channel][branch_idx] = level[branch_idx];
933 : }
934 :
935 16496 : return IVAS_ERR_OK;
936 : }
937 :
938 :
939 : /*-----------------------------------------------------------------------------------------*
940 : * Function clear_buffers()
941 : *
942 : * Clears buffers of delay lines and filters
943 : *-----------------------------------------------------------------------------------------*/
944 :
945 8248 : static void clear_buffers(
946 : REVERB_HANDLE hReverb )
947 : {
948 : int16_t branch_idx;
949 : ivas_rev_iir_filter_t *iirFilter;
950 : ivas_rev_delay_line_t *delay_line;
951 :
952 74232 : for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
953 : {
954 65984 : delay_line = &( hReverb->delay_line[branch_idx] );
955 65984 : set_f( delay_line->pBuffer, 0, delay_line->MaxDelay );
956 65984 : delay_line->BufferPos = 0;
957 :
958 65984 : iirFilter = &( hReverb->t60[branch_idx] );
959 65984 : set_f( iirFilter->pBuffer, 0, iirFilter->MaxTaps );
960 : }
961 :
962 8248 : ivas_reverb_t2f_f2t_ClearHistory( &hReverb->fft_filter_ols );
963 :
964 8248 : return;
965 : }
966 :
967 :
968 : /*-----------------------------------------------------------------------------------------*
969 : * Function set_fft_and_datablock_sizes()
970 : *
971 : * Sets frame size and fft-filter related sizes
972 : *-----------------------------------------------------------------------------------------*/
973 :
974 12409 : static void set_fft_and_datablock_sizes(
975 : REVERB_HANDLE hReverb,
976 : const int16_t subframe_len )
977 : {
978 12409 : hReverb->full_block_size = subframe_len;
979 12409 : if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES )
980 : {
981 4142 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K;
982 4142 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K;
983 : }
984 8267 : else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES )
985 : {
986 4087 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K;
987 4087 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K;
988 : }
989 4180 : else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES )
990 : {
991 4180 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K;
992 4180 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K;
993 : }
994 : else
995 : {
996 0 : assert( 0 ); /* unsupported block size */
997 : }
998 :
999 12409 : hReverb->fft_subblock_size = subframe_len / hReverb->num_fft_subblocks;
1000 :
1001 12409 : return;
1002 : }
1003 :
1004 :
1005 : /*-----------------------------------------------------------------------------------------*
1006 : * Function set_reverb_acoustic_data()
1007 : *
1008 : * Sets reverb acoustic data (room acoustics and HRTF), interpolating it to the filter grid
1009 : *-----------------------------------------------------------------------------------------*/
1010 :
1011 12409 : static void set_reverb_acoustic_data(
1012 : ivas_reverb_params_t *pParams,
1013 : IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics,
1014 : const int16_t nr_fc_input,
1015 : const int16_t nr_fc_fft_filter )
1016 : {
1017 : int16_t bin_idx;
1018 : float ln_1e6_inverted, delay_diff, exp_argument;
1019 : /* interpolate input table data for T60 and DSR to the FFT filter grid */
1020 12409 : ivas_reverb_interpolate_acoustic_data( nr_fc_input, pRoomAcoustics->pFc_input, pRoomAcoustics->pAcoustic_rt60, pRoomAcoustics->pAcoustic_dsr,
1021 12409 : nr_fc_fft_filter, pParams->pFc, pParams->pRt60, pParams->pDsr );
1022 :
1023 : /* adjust DSR for the delay difference */
1024 12409 : delay_diff = pRoomAcoustics->inputPreDelay - pRoomAcoustics->acousticPreDelay;
1025 12409 : ln_1e6_inverted = 1.0f / logf( 1e06f );
1026 2666482 : for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
1027 : {
1028 2654073 : exp_argument = delay_diff / ( pParams->pRt60[bin_idx] * ln_1e6_inverted );
1029 : /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */
1030 2654073 : exp_argument = min( exp_argument, 23.0f );
1031 2654073 : exp_argument = max( exp_argument, -23.0f );
1032 2654073 : pParams->pDsr[bin_idx] *= expf( exp_argument );
1033 : }
1034 :
1035 12409 : return;
1036 : }
1037 :
1038 :
1039 : /*-----------------------------------------------------------------------------------------*
1040 : * Function setup_FDN_branches()
1041 : *
1042 : * Sets up feedback delay network system
1043 : *-----------------------------------------------------------------------------------------*/
1044 :
1045 8248 : static ivas_error setup_FDN_branches(
1046 : REVERB_HANDLE hReverb,
1047 : ivas_reverb_params_t *pParams )
1048 : {
1049 : int16_t nr_coefs, branch_idx, channel_idx;
1050 : ivas_error error;
1051 8248 : error = IVAS_ERR_OK;
1052 :
1053 : /* initialize feedback branches */
1054 74232 : for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
1055 : {
1056 65984 : ivas_rev_delay_line_init( &( hReverb->delay_line[branch_idx] ), hReverb->loop_delay_buffer[branch_idx], init_loop_delay[branch_idx], pParams->pLoop_delays[branch_idx] );
1057 65984 : ivas_reverb_iir_filt_init( &( hReverb->t60[branch_idx] ), IVAS_REV_MAX_IIR_FILTER_LENGTH );
1058 65984 : hReverb->mixer[0][branch_idx] = 0.0f;
1059 65984 : hReverb->mixer[1][branch_idx] = 0.0f;
1060 : }
1061 8248 : clear_buffers( hReverb );
1062 8248 : nr_coefs = pParams->t60_filter_order + 1;
1063 :
1064 8248 : if ( IVAS_REV_MAX_IIR_FILTER_LENGTH < nr_coefs )
1065 : {
1066 0 : return IVAS_ERR_INTERNAL;
1067 : }
1068 : else
1069 : {
1070 74232 : for ( branch_idx = 0; branch_idx < pParams->nr_loops; branch_idx++ )
1071 : {
1072 65984 : if ( ( error = set_feedback_delay( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ) != IVAS_ERR_OK )
1073 : {
1074 0 : return error;
1075 : }
1076 :
1077 65984 : if ( ( error = set_feedback_gain( hReverb, branch_idx, &( pParams->pLoop_feedback_matrix[branch_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK )
1078 : {
1079 0 : return error;
1080 : }
1081 : }
1082 : }
1083 :
1084 24744 : for ( channel_idx = 0; channel_idx < pParams->nr_outputs; channel_idx++ )
1085 : {
1086 16496 : if ( ( error = set_mixer_level( hReverb, channel_idx, &( pParams->pLoop_extract_matrix[channel_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK )
1087 : {
1088 0 : return error;
1089 : }
1090 : }
1091 :
1092 8248 : return error;
1093 : }
1094 :
1095 :
1096 : /*-------------------------------------------------------------------------
1097 : * ivas_reverb_open()
1098 : *
1099 : * Allocate and initialize FDN reverberation handle
1100 : *------------------------------------------------------------------------*/
1101 :
1102 12409 : ivas_error ivas_reverb_open(
1103 : REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */
1104 : const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i : HRTF statistics handle */
1105 : RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */
1106 : const int32_t output_Fs /* i : output sampling rate */
1107 : )
1108 : {
1109 : ivas_error error;
1110 12409 : REVERB_HANDLE pState = *hReverb;
1111 : int16_t nr_coefs, branch_idx;
1112 : float *pCoef_a, *pCoef_b;
1113 : int16_t bin_idx, subframe_len, output_frame, predelay_bf_len, loop_idx;
1114 : ivas_reverb_params_t params;
1115 : rv_fftwf_type_complex pFft_wf_filter_ch0[RV_LENGTH_NR_FC];
1116 : rv_fftwf_type_complex pFft_wf_filter_ch1[RV_LENGTH_NR_FC];
1117 : float pColor_target_l[RV_LENGTH_NR_FC];
1118 : float pColor_target_r[RV_LENGTH_NR_FC];
1119 : float pTime_window[RV_FILTER_MAX_FFT_SIZE];
1120 : float freq_step;
1121 : int16_t fft_hist_size, transition_start, transition_length;
1122 : int16_t nr_fc_input, nr_fc_fft_filter;
1123 :
1124 12409 : output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC );
1125 12409 : subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES;
1126 12409 : predelay_bf_len = output_frame;
1127 12409 : nr_fc_input = hRenderConfig->roomAcoustics.nBands;
1128 :
1129 12409 : if ( *hReverb == NULL )
1130 : {
1131 : /* Allocate main reverb. handle */
1132 8248 : if ( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL )
1133 : {
1134 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator " );
1135 : }
1136 : }
1137 :
1138 12409 : if ( ( error = set_base_config( ¶ms, output_Fs ) ) != IVAS_ERR_OK )
1139 : {
1140 0 : return error;
1141 : }
1142 :
1143 12409 : if ( *hReverb == NULL )
1144 : {
1145 : /* Allocate memory for feedback delay lines */
1146 74232 : for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
1147 : {
1148 65984 : if ( ( pState->loop_delay_buffer[loop_idx] = (float *) malloc( params.pLoop_delays[loop_idx] * sizeof( float ) ) ) == NULL )
1149 : {
1150 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
1151 : }
1152 : }
1153 :
1154 : /* Allocate memory for the pre-delay delay line */
1155 8248 : if ( ( pState->pPredelay_buffer = (float *) malloc( output_frame * sizeof( float ) ) ) == NULL )
1156 : {
1157 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
1158 : }
1159 : }
1160 :
1161 12409 : pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES;
1162 12409 : set_fft_and_datablock_sizes( pState, subframe_len );
1163 :
1164 12409 : nr_fc_fft_filter = ( pState->fft_size >> 1 ) + 1;
1165 :
1166 : /* === 'Control logic': compute the reverb processing parameters from the === */
1167 : /* === room, source and listener acoustic information provided in the reverb config === */
1168 : /* Setting up shared temporary buffers for fc, RT60, DSR, etc. */
1169 12409 : params.pRt60 = &pFft_wf_filter_ch1[0][0];
1170 12409 : params.pDsr = params.pRt60 + nr_fc_fft_filter;
1171 12409 : params.pFc = &pState->fft_filter_color_0.fft_spectrum[0];
1172 :
1173 : /* Note: these temp buffers can only be used before the final step of the FFT filter design : */
1174 : /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */
1175 :
1176 : /* set the uniform frequency grid for FFT filtering */
1177 12409 : freq_step = 0.5f * output_Fs / ( nr_fc_fft_filter - 1 );
1178 2666482 : for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
1179 : {
1180 2654073 : params.pFc[bin_idx] = freq_step * bin_idx;
1181 : }
1182 :
1183 12409 : set_reverb_acoustic_data( ¶ms, &hRenderConfig->roomAcoustics, nr_fc_input, nr_fc_fft_filter );
1184 12409 : params.pHrtf_avg_pwr_response_l_const = hHrtfStatistics->average_energy_l;
1185 12409 : params.pHrtf_avg_pwr_response_r_const = hHrtfStatistics->average_energy_r;
1186 12409 : params.pHrtf_inter_aural_coherence_const = hHrtfStatistics->inter_aural_coherence;
1187 :
1188 : /* set reverb acoustic configuration based on renderer config */
1189 12409 : pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands;
1190 :
1191 12409 : if ( hRenderConfig->roomAcoustics.use_er == 1 )
1192 : {
1193 3147 : pState->pConfig.roomAcoustics.use_er = hRenderConfig->roomAcoustics.use_er;
1194 3147 : pState->pConfig.roomAcoustics.lowComplexity = hRenderConfig->roomAcoustics.lowComplexity;
1195 : }
1196 :
1197 : /* set up input downmix */
1198 12409 : if ( *hReverb == NULL )
1199 : {
1200 8248 : pState->dmx_gain = calc_dmx_gain();
1201 : }
1202 :
1203 : /* set up predelay - must be after set_base_config() and before compute_t60_coeffs() */
1204 12409 : calc_predelay( ¶ms, hRenderConfig->roomAcoustics.acousticPreDelay, output_Fs );
1205 :
1206 : /* set up jot reverb 60 filters - must be set up after set_reverb_acoustic_data() */
1207 12409 : if ( ( error = compute_t60_coeffs( ¶ms, nr_fc_fft_filter, output_Fs ) ) != IVAS_ERR_OK )
1208 : {
1209 0 : return error;
1210 : }
1211 :
1212 : /* Compute target levels (gains) for the coloration filters */
1213 12409 : ivas_reverb_calc_color_levels( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc, params.pDsr, params.pHrtf_avg_pwr_response_l_const, params.pHrtf_avg_pwr_response_r_const,
1214 : params.pLoop_delays, params.pT60_filter_coeff, pColor_target_l, pColor_target_r );
1215 :
1216 : /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */
1217 12409 : fft_hist_size = pState->fft_size - pState->fft_subblock_size;
1218 :
1219 12409 : transition_start = (int16_t) roundf( FFT_FILTER_WND_FLAT_REGION * fft_hist_size );
1220 12409 : transition_length = (int16_t) roundf( FFT_FILTER_WND_TRANS_REGION * fft_hist_size );
1221 :
1222 : /* Compute the window used for FFT filters */
1223 12409 : ivas_reverb_define_window_fft( pTime_window, transition_start, transition_length, nr_fc_fft_filter );
1224 :
1225 : /* === Copy parameters from ivas_reverb_params_t into DSP blocks === */
1226 : /* === to be used for subsequent audio signal processing === */
1227 12409 : if ( *hReverb == NULL )
1228 : {
1229 8248 : pState->do_corr_filter = params.do_corr_filter;
1230 :
1231 : /* clear & init jot reverb fft filters */
1232 8248 : if ( ( error = initialize_reverb_filters( pState ) ) != IVAS_ERR_OK )
1233 : {
1234 0 : return error;
1235 : }
1236 : }
1237 :
1238 12409 : if ( pState->do_corr_filter )
1239 : {
1240 : /* Computing correlation filters on the basis of target IA coherence */
1241 12409 : ivas_reverb_calc_correl_filters( params.pHrtf_inter_aural_coherence_const, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 );
1242 :
1243 : /* Copying the computed FFT correlation filters to the fft_filter components */
1244 12409 : if ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK )
1245 : {
1246 0 : return error;
1247 : }
1248 :
1249 12409 : if ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK )
1250 : {
1251 0 : return error;
1252 : }
1253 : }
1254 :
1255 : /* Computing coloration filters on the basis of target responses */
1256 12409 : ivas_reverb_calc_color_filters( pColor_target_l, pColor_target_r, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 );
1257 :
1258 : /* Copying the computed FFT colorations filters to the fft_filter components */
1259 12409 : if ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK )
1260 : {
1261 0 : return error;
1262 : }
1263 :
1264 12409 : if ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK )
1265 : {
1266 0 : return error;
1267 : }
1268 :
1269 12409 : if ( *hReverb == NULL )
1270 : {
1271 : /* init predelay */
1272 8248 : ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer, params.pre_delay, predelay_bf_len );
1273 :
1274 : /* set up feedback delay network */
1275 8248 : if ( ( error = setup_FDN_branches( pState, ¶ms ) ) != IVAS_ERR_OK )
1276 : {
1277 0 : return error;
1278 : }
1279 : }
1280 : else
1281 : {
1282 4161 : pState->predelay_line.Delay = params.pre_delay;
1283 : }
1284 :
1285 12409 : nr_coefs = params.t60_filter_order + 1;
1286 :
1287 111681 : for ( branch_idx = 0; branch_idx < params.nr_loops; branch_idx++ )
1288 : {
1289 99272 : pCoef_a = ¶ms.pT60_filter_coeff[2 * nr_coefs * branch_idx + nr_coefs];
1290 99272 : pCoef_b = ¶ms.pT60_filter_coeff[2 * nr_coefs * branch_idx];
1291 :
1292 99272 : if ( ( error = set_t60_filter( pState, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ) != IVAS_ERR_OK )
1293 : {
1294 0 : return error;
1295 : }
1296 : }
1297 :
1298 12409 : *hReverb = pState;
1299 :
1300 12409 : return IVAS_ERR_OK;
1301 : }
1302 :
1303 :
1304 : /*-------------------------------------------------------------------------
1305 : * ivas_reverb_close()
1306 : *
1307 : * Deallocate Crend reverberation handle
1308 : *------------------------------------------------------------------------*/
1309 :
1310 150008 : void ivas_reverb_close(
1311 : REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle */
1312 : )
1313 : {
1314 : REVERB_HANDLE hReverb;
1315 : int16_t loop_idx;
1316 :
1317 150008 : hReverb = *hReverb_in;
1318 :
1319 150008 : if ( hReverb_in == NULL || *hReverb_in == NULL )
1320 : {
1321 141760 : return;
1322 : }
1323 :
1324 74232 : for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
1325 : {
1326 65984 : if ( hReverb->loop_delay_buffer[loop_idx] != NULL )
1327 : {
1328 65984 : free( hReverb->loop_delay_buffer[loop_idx] );
1329 65984 : hReverb->loop_delay_buffer[loop_idx] = NULL;
1330 : }
1331 : }
1332 :
1333 8248 : free( hReverb->pPredelay_buffer );
1334 8248 : hReverb->pPredelay_buffer = NULL;
1335 :
1336 8248 : free( *hReverb_in );
1337 8248 : *hReverb_in = NULL;
1338 :
1339 8248 : return;
1340 : }
1341 :
1342 :
1343 : /*-----------------------------------------------------------------------------------------*
1344 : * Function post_fft_filter()
1345 : *
1346 : *
1347 : *-----------------------------------------------------------------------------------------*/
1348 :
1349 9333313 : static void post_fft_filter(
1350 : REVERB_HANDLE hReverb,
1351 : float *p0,
1352 : float *p1,
1353 : float *pBuffer_0,
1354 : float *pBuffer_1 )
1355 : {
1356 9333313 : if ( hReverb->do_corr_filter )
1357 : {
1358 9333313 : ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 );
1359 9333313 : ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_0, pBuffer_0 );
1360 9333313 : ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_1, pBuffer_1 );
1361 9333313 : ivas_reverb_fft_filter_CrossMix( pBuffer_0, pBuffer_1, hReverb->fft_filter_correl_0.fft_size );
1362 : }
1363 : else
1364 : {
1365 0 : ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 );
1366 : }
1367 :
1368 9333313 : ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_0, pBuffer_0 );
1369 9333313 : ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_1, pBuffer_1 );
1370 9333313 : ivas_reverb_t2f_f2t_out( &hReverb->fft_filter_ols, pBuffer_0, pBuffer_1, p0, p1 );
1371 :
1372 9333313 : return;
1373 : }
1374 :
1375 :
1376 : /*-----------------------------------------------------------------------------------------*
1377 : * Function reverb_block()
1378 : *
1379 : * Input a block (mono) and calculate the 2 output blocks.
1380 : *-----------------------------------------------------------------------------------------*/
1381 :
1382 9333313 : static void reverb_block(
1383 : REVERB_HANDLE hReverb,
1384 : float *pInput,
1385 : float *pOut0,
1386 : float *pOut1 )
1387 :
1388 : {
1389 9333313 : uint16_t nr_branches = hReverb->nr_of_branches;
1390 9333313 : uint16_t bsize = hReverb->full_block_size;
1391 9333313 : uint16_t inner_bsize = INNER_BLK_SIZE;
1392 : uint16_t i, j, k, ns, branch_idx, blk_idx, start_sample_idx;
1393 :
1394 : float *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE];
1395 : float pFeedback_input[INNER_BLK_SIZE];
1396 : float pTemp[INNER_BLK_SIZE];
1397 : float *ppOutput[IVAS_REV_MAX_NR_BRANCHES];
1398 : float Output[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE];
1399 :
1400 9333313 : pFFT_buf[0] = &FFT_buf_1[0];
1401 9333313 : pFFT_buf[1] = &FFT_buf_2[0];
1402 :
1403 83999817 : for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ )
1404 : {
1405 74666504 : ppOutput[branch_idx] = (float *) Output + branch_idx * inner_bsize;
1406 : }
1407 :
1408 28100560 : for ( k = 0; k < bsize; k += inner_bsize )
1409 : {
1410 18767247 : float *pO0 = &pOut0[k];
1411 18767247 : float *pO1 = &pOut1[k];
1412 1520147007 : for ( i = 0; i < inner_bsize; i++ )
1413 : {
1414 1501379760 : pO0[i] = 0.0f;
1415 1501379760 : pO1[i] = 0.0f;
1416 : }
1417 :
1418 : /* feedback network: */
1419 168905223 : for ( i = 0; i < nr_branches; i++ )
1420 : {
1421 150137976 : float *pOutput_i = &ppOutput[i][0];
1422 150137976 : float mixer_0_i = hReverb->mixer[0][i];
1423 150137976 : float mixer_1_i = hReverb->mixer[1][i];
1424 :
1425 : /* output and feedback are same, get sample from delay line ... */
1426 150137976 : ivas_rev_delay_line_get_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pTemp );
1427 150137976 : ivas_reverb_iir_filt_2taps_feed_blk( &( hReverb->t60[i] ), inner_bsize, pTemp, ppOutput[i] );
1428 12161176056 : for ( ns = 0; ns < inner_bsize; ns++ )
1429 : {
1430 12011038080 : pO0[ns] += pOutput_i[ns] * mixer_0_i; /* mixer ch 0 */
1431 12011038080 : pO1[ns] += pOutput_i[ns] * mixer_1_i; /* mixer ch 1 */
1432 : }
1433 : }
1434 :
1435 168905223 : for ( i = 0; i < nr_branches; i++ )
1436 : {
1437 150137976 : float *pIn = &pInput[k];
1438 :
1439 12161176056 : for ( ns = 0; ns < inner_bsize; ns++ )
1440 : {
1441 12011038080 : pFeedback_input[ns] = pIn[ns];
1442 : }
1443 :
1444 1351241784 : for ( j = 0; j < nr_branches; j++ )
1445 : {
1446 1201103808 : float gain_matrix_j_i = hReverb->gain_matrix[j][i];
1447 1201103808 : float *pOutput = &ppOutput[j][0];
1448 97289408448 : for ( ns = 0; ns < inner_bsize; ns++ )
1449 : {
1450 96088304640 : pFeedback_input[ns] += gain_matrix_j_i * pOutput[ns];
1451 : }
1452 : }
1453 :
1454 150137976 : ivas_rev_delay_line_feed_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pFeedback_input );
1455 : }
1456 : }
1457 :
1458 : /* Applying FFT filter to each sub-frame */
1459 18666626 : for ( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ )
1460 : {
1461 9333313 : start_sample_idx = blk_idx * hReverb->fft_subblock_size;
1462 9333313 : post_fft_filter( hReverb, pOut0 + start_sample_idx, pOut1 + start_sample_idx, pFFT_buf[0], pFFT_buf[1] );
1463 : }
1464 :
1465 9333313 : return;
1466 : }
1467 :
1468 :
1469 : /*-----------------------------------------------------------------------------------------*
1470 : * Function downmix_input_block()
1471 : *
1472 : * Downmix input to mono, taking also DSR gain into account
1473 : *-----------------------------------------------------------------------------------------*/
1474 :
1475 9333313 : static ivas_error downmix_input_block(
1476 : const REVERB_HANDLE hReverb,
1477 : float *pcm_in[],
1478 : const AUDIO_CONFIG input_audio_config,
1479 : float *pPcm_out,
1480 : const int16_t input_offset )
1481 : {
1482 : int16_t i, s, nchan_transport;
1483 9333313 : float dmx_gain = hReverb->dmx_gain;
1484 :
1485 9333313 : switch ( input_audio_config )
1486 : {
1487 7118891 : case IVAS_AUDIO_CONFIG_STEREO:
1488 : case IVAS_AUDIO_CONFIG_5_1:
1489 : case IVAS_AUDIO_CONFIG_7_1:
1490 : case IVAS_AUDIO_CONFIG_5_1_2:
1491 : case IVAS_AUDIO_CONFIG_5_1_4:
1492 : case IVAS_AUDIO_CONFIG_7_1_4:
1493 : case IVAS_AUDIO_CONFIG_ISM1:
1494 : case IVAS_AUDIO_CONFIG_ISM2:
1495 : case IVAS_AUDIO_CONFIG_ISM3:
1496 : case IVAS_AUDIO_CONFIG_ISM4:
1497 : {
1498 7118891 : nchan_transport = audioCfg2channels( input_audio_config );
1499 1150451051 : for ( s = 0; s < hReverb->full_block_size; s++ )
1500 : {
1501 1143332160 : float temp = pcm_in[0][input_offset + s];
1502 1753238400 : for ( i = 1; i < nchan_transport; i++ )
1503 : {
1504 609906240 : temp += pcm_in[i][input_offset + s];
1505 : }
1506 1143332160 : pPcm_out[s] = dmx_gain * temp;
1507 : }
1508 7118891 : break;
1509 : }
1510 2214422 : case IVAS_AUDIO_CONFIG_MONO: /* ~'ZOA_1' */
1511 : case IVAS_AUDIO_CONFIG_FOA:
1512 : case IVAS_AUDIO_CONFIG_HOA2:
1513 : case IVAS_AUDIO_CONFIG_HOA3:
1514 : {
1515 360262022 : for ( s = 0; s < hReverb->full_block_size; s++ )
1516 : {
1517 358047600 : pPcm_out[s] = dmx_gain * pcm_in[0][input_offset + s];
1518 : }
1519 2214422 : break;
1520 : }
1521 0 : default:
1522 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" );
1523 : break;
1524 : }
1525 :
1526 9333313 : return IVAS_ERR_OK;
1527 : }
1528 :
1529 :
1530 : /*-----------------------------------------------------------------------------------------*
1531 : * Function predelay_block()
1532 : *
1533 : * Perform a predelay
1534 : *-----------------------------------------------------------------------------------------*/
1535 :
1536 9333313 : static void predelay_block(
1537 : const REVERB_HANDLE hReverb,
1538 : float *pInput,
1539 : float *pOutput )
1540 : {
1541 : uint16_t i, idx, n_samples, blk_size;
1542 9333313 : uint16_t max_blk_size = (uint16_t) hReverb->predelay_line.Delay;
1543 :
1544 9333313 : if ( max_blk_size < 2 )
1545 : {
1546 359528 : if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */
1547 : {
1548 60756728 : for ( i = 0; i < hReverb->full_block_size; i++ )
1549 : {
1550 60397200 : pOutput[i] = pInput[i];
1551 : }
1552 : }
1553 : else /* 1-sample length delay line: feed the data sample-by-sample */
1554 : {
1555 0 : for ( i = 0; i < hReverb->full_block_size; i++ )
1556 : {
1557 0 : pOutput[i] = ivas_rev_delay_line_get_sample( &( hReverb->predelay_line ) );
1558 0 : ivas_rev_delay_line_feed_sample( &( hReverb->predelay_line ), pInput[i] );
1559 : }
1560 : }
1561 : }
1562 : else /* multiple-sample length delay line: use block processing */
1563 : {
1564 8973785 : idx = 0;
1565 8973785 : n_samples = hReverb->full_block_size;
1566 53842710 : while ( n_samples > 0 )
1567 : {
1568 44868925 : blk_size = n_samples;
1569 44868925 : if ( blk_size > max_blk_size )
1570 : {
1571 35895140 : blk_size = max_blk_size;
1572 : }
1573 44868925 : ivas_rev_delay_line_get_sample_blk( &( hReverb->predelay_line ), blk_size, &pOutput[idx] );
1574 44868925 : ivas_rev_delay_line_feed_sample_blk( &( hReverb->predelay_line ), blk_size, &pInput[idx] );
1575 44868925 : idx += blk_size;
1576 44868925 : n_samples -= blk_size;
1577 : }
1578 : }
1579 :
1580 9333313 : return;
1581 : }
1582 :
1583 :
1584 : /*-----------------------------------------------------------------------------------------*
1585 : * Function mix_output_block()
1586 : *
1587 : * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively
1588 : *-----------------------------------------------------------------------------------------*/
1589 :
1590 2305047 : static void mix_output_block(
1591 : const REVERB_HANDLE hReverb,
1592 : const float *pInL,
1593 : const float *pInR,
1594 : float *pOutL,
1595 : float *pOutR )
1596 : {
1597 : uint16_t i;
1598 :
1599 373804407 : for ( i = 0; i < hReverb->full_block_size; i++ )
1600 : {
1601 371499360 : pOutL[i] += pInL[i];
1602 371499360 : pOutR[i] += pInR[i];
1603 : }
1604 :
1605 2305047 : return;
1606 : }
1607 :
1608 :
1609 : /*-----------------------------------------------------------------------------------------*
1610 : * ivas_reverb_process()
1611 : *
1612 : * Process the input PCM audio into output PCM audio, applying reverb
1613 : *-----------------------------------------------------------------------------------------*/
1614 :
1615 9333313 : ivas_error ivas_reverb_process(
1616 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
1617 : const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */
1618 : const int16_t mix_signals, /* i : add reverb to output signal */
1619 : float *pcm_in[], /* i : the PCM audio to apply reverb on */
1620 : float *pcm_out[], /* o : the PCM audio with reverb applied */
1621 : const int16_t i_ts /* i : subframe index */
1622 : )
1623 : {
1624 : float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
1625 : ivas_error error;
1626 :
1627 9333313 : if ( ( error = downmix_input_block( hReverb, pcm_in, input_audio_config, tmp1, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK )
1628 : {
1629 0 : return error;
1630 : }
1631 :
1632 9333313 : predelay_block( hReverb, tmp1, tmp0 );
1633 :
1634 9333313 : reverb_block( hReverb, tmp0, tmp1, tmp2 );
1635 :
1636 9333313 : if ( mix_signals )
1637 : {
1638 2305047 : mix_output_block( hReverb, tmp1, tmp2, &pcm_out[0][i_ts * hReverb->full_block_size], &pcm_out[1][i_ts * hReverb->full_block_size] );
1639 : }
1640 : else
1641 : {
1642 7028266 : mvr2r( tmp1, &pcm_out[0][i_ts * hReverb->full_block_size], hReverb->full_block_size );
1643 7028266 : mvr2r( tmp2, &pcm_out[1][i_ts * hReverb->full_block_size], hReverb->full_block_size );
1644 : }
1645 :
1646 9333313 : return IVAS_ERR_OK;
1647 : }
1648 :
1649 :
1650 : /*-------------------------------------------------------------------------
1651 : * ivas_binaural_reverb_processSubFrame()
1652 : *
1653 : * Compute the reverberation - room effect
1654 : *------------------------------------------------------------------------*/
1655 :
1656 3786680 : void ivas_binaural_reverb_processSubframe(
1657 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
1658 : const int16_t numInChannels, /* i : num inputs to be processed */
1659 : const int16_t numSlots, /* i : number of slots to be processed */
1660 : float inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */
1661 : float inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */
1662 : float outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */
1663 : float outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* o : output CLDFB data imag */
1664 : )
1665 : {
1666 : /* Declare the required variables */
1667 : int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr;
1668 : float **tapRealPr, **tapImagPr;
1669 3786680 : push_wmops( "binaural_reverb" );
1670 :
1671 : /* 1) Rotate the data in the loop buffer of the reverberator.
1672 : * Notice that the audio at the loop buffers is at time-inverted order
1673 : * for convolution purposes later on. */
1674 159625390 : for ( bin = 0; bin < hReverb->numBins; bin++ )
1675 : {
1676 : /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */
1677 155838710 : mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + numSlots, hReverb->loopBufLength[bin] );
1678 155838710 : mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + numSlots, hReverb->loopBufLength[bin] );
1679 :
1680 : /* Add the data from the end of the loop to the beginning, with an attenuation factor
1681 : * according to RT60. This procedure generates an IIR decaying response. The response
1682 : * is decorrelated later on. */
1683 155838710 : v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], numSlots );
1684 155838710 : v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], numSlots );
1685 : }
1686 :
1687 : /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */
1688 3786680 : idx = hReverb->preDelayBufferIndex;
1689 18925030 : for ( sample = 0; sample < numSlots; sample++ )
1690 : {
1691 15138350 : invertSampleIndex = numSlots - sample - 1;
1692 :
1693 638037850 : for ( bin = 0; bin < hReverb->numBins; bin++ )
1694 : {
1695 : /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order.
1696 : * Also apply the spectral gains determined for the reverberation */
1697 622899500 : hReverb->loopBufReal[bin][invertSampleIndex] += hReverb->preDelayBufferReal[idx][bin] * hReverb->reverbEqGains[bin];
1698 622899500 : hReverb->loopBufImag[bin][invertSampleIndex] += hReverb->preDelayBufferImag[idx][bin] * hReverb->reverbEqGains[bin];
1699 622899500 : hReverb->preDelayBufferReal[idx][bin] = 0.0f;
1700 622899500 : hReverb->preDelayBufferImag[idx][bin] = 0.0f;
1701 : }
1702 :
1703 : /* Add every second input channel as is to the pre-delay buffer, and every second input channel with
1704 : * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */
1705 48200490 : for ( ch = 0; ch < numInChannels; ch++ )
1706 : {
1707 33062140 : if ( ch % 2 )
1708 : {
1709 15995438 : v_add( hReverb->preDelayBufferReal[idx], inReal[ch][sample], hReverb->preDelayBufferReal[idx], hReverb->numBins );
1710 15995438 : v_add( hReverb->preDelayBufferImag[idx], inImag[ch][sample], hReverb->preDelayBufferImag[idx], hReverb->numBins );
1711 : }
1712 : else
1713 : {
1714 17066702 : v_sub( hReverb->preDelayBufferReal[idx], inImag[ch][sample], hReverb->preDelayBufferReal[idx], hReverb->numBins );
1715 17066702 : v_add( hReverb->preDelayBufferImag[idx], inReal[ch][sample], hReverb->preDelayBufferImag[idx], hReverb->numBins );
1716 : }
1717 : }
1718 15138350 : idx = ( idx + 1 ) % hReverb->preDelayBufferLength;
1719 : }
1720 3786680 : hReverb->preDelayBufferIndex = idx;
1721 :
1722 : /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */
1723 159625390 : for ( bin = 0; bin < hReverb->numBins; bin++ )
1724 : {
1725 467516130 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1726 : {
1727 : /* These tap pointers have been determined to point to the loop buffer at sparse locations */
1728 311677420 : tapRealPr = hReverb->tapPointersReal[bin][ch];
1729 311677420 : tapImagPr = hReverb->tapPointersImag[bin][ch];
1730 :
1731 311677420 : phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch];
1732 :
1733 : /* Flush output */
1734 311677420 : set_f( hReverb->outputBufferReal[bin][ch], 0.0f, numSlots );
1735 311677420 : set_f( hReverb->outputBufferImag[bin][ch], 0.0f, numSlots );
1736 :
1737 : /* Add from temporally decaying sparse tap locations the audio to the output. */
1738 5403554372 : for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ )
1739 : {
1740 5091876952 : switch ( phaseShiftTypePr[tapIdx] )
1741 : {
1742 1228097810 : case 0: /* 0 degrees phase */
1743 1228097810 : v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
1744 1228097810 : v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
1745 1228097810 : break;
1746 1350403720 : case 1: /* 90 degrees phase */
1747 1350403720 : v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
1748 1350403720 : v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
1749 1350403720 : break;
1750 1274621675 : case 2: /* 180 degrees phase */
1751 1274621675 : v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
1752 1274621675 : v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
1753 1274621675 : break;
1754 1238753747 : default: /* 270 degrees phase */
1755 1238753747 : v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], numSlots );
1756 1238753747 : v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], numSlots );
1757 1238753747 : break;
1758 : }
1759 : }
1760 : }
1761 :
1762 : /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */
1763 155838710 : if ( bin <= hReverb->highestBinauralCoherenceBin )
1764 : {
1765 26075431 : if ( hReverb->useBinauralCoherence )
1766 : {
1767 130320005 : for ( sample = 0; sample < numSlots; sample++ )
1768 : {
1769 : float leftRe, rightRe, leftIm, rightIm;
1770 :
1771 104244574 : leftRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][1][sample];
1772 104244574 : rightRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][0][sample];
1773 104244574 : leftIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][1][sample];
1774 104244574 : rightIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][0][sample];
1775 :
1776 104244574 : hReverb->outputBufferReal[bin][0][sample] = leftRe;
1777 104244574 : hReverb->outputBufferReal[bin][1][sample] = rightRe;
1778 104244574 : hReverb->outputBufferImag[bin][0][sample] = leftIm;
1779 104244574 : hReverb->outputBufferImag[bin][1][sample] = rightIm;
1780 : }
1781 : }
1782 : }
1783 : }
1784 :
1785 : /* 4) Write data to output */
1786 11360040 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1787 : {
1788 37850060 : for ( sample = 0; sample < numSlots; sample++ )
1789 : {
1790 : /* Audio was in the temporally inverted order for convolution, re-invert audio to output */
1791 30276700 : invertSampleIndex = numSlots - sample - 1;
1792 :
1793 1276075700 : for ( bin = 0; bin < hReverb->numBins; bin++ )
1794 : {
1795 1245799000 : outReal[ch][sample][bin] = hReverb->outputBufferReal[bin][ch][invertSampleIndex];
1796 1245799000 : outImag[ch][sample][bin] = hReverb->outputBufferImag[bin][ch][invertSampleIndex];
1797 : }
1798 601079700 : for ( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
1799 : {
1800 570803000 : outReal[ch][sample][bin] = 0.0f;
1801 570803000 : outImag[ch][sample][bin] = 0.0f;
1802 : }
1803 : }
1804 : }
1805 :
1806 3786680 : pop_wmops();
1807 3786680 : return;
1808 : }
1809 :
1810 :
1811 : /*-------------------------------------------------------------------------
1812 : * ivas_binaural_reverb_open()
1813 : *
1814 : * Allocate and initialize binaural room reverberator handle
1815 : *------------------------------------------------------------------------*/
1816 :
1817 16075 : static ivas_error ivas_binaural_reverb_open(
1818 : REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */
1819 : const int16_t numBins, /* i : number of CLDFB bins */
1820 : const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */
1821 : const int32_t sampling_rate, /* i : sampling rate */
1822 : const float *revTimes, /* i : reverberation times T60 for each CLDFB bin in seconds */
1823 : const float *revEnes, /* i : spectrum for reverberated sound at each CLDFB bin */
1824 : const int16_t preDelay /* i : reverb pre-delay in CLDFB slots */
1825 : )
1826 : {
1827 : int16_t bin, chIdx, k, len;
1828 : REVERB_STRUCT_HANDLE hReverb;
1829 :
1830 16075 : if ( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL )
1831 : {
1832 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1833 : }
1834 :
1835 16075 : hReverb = *hReverbPr;
1836 :
1837 16075 : hReverb->useBinauralCoherence = 1;
1838 16075 : hReverb->preDelayBufferLength = 1;
1839 16075 : hReverb->preDelayBufferIndex = 0;
1840 :
1841 16075 : hReverb->numBins = numBins;
1842 16075 : hReverb->blockSize = numCldfbSlotsPerFrame;
1843 :
1844 353650 : for ( k = 0; k < IVAS_REVERB_PREDELAY_MAX + 1; k++ )
1845 : {
1846 337575 : set_f( hReverb->preDelayBufferReal[k], 0.0f, hReverb->numBins );
1847 337575 : set_f( hReverb->preDelayBufferImag[k], 0.0f, hReverb->numBins );
1848 : }
1849 :
1850 644595 : for ( bin = 0; bin < hReverb->numBins; bin++ )
1851 : {
1852 : /* Loop Buffer */
1853 628520 : hReverb->loopBufLengthMax[bin] = (int16_t) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) );
1854 :
1855 628520 : len = hReverb->loopBufLengthMax[bin] + hReverb->blockSize;
1856 628520 : if ( ( hReverb->loopBufReal[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
1857 : {
1858 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1859 : }
1860 :
1861 628520 : if ( ( hReverb->loopBufImag[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
1862 : {
1863 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1864 : }
1865 :
1866 628520 : set_f( hReverb->loopBufReal[bin], 0.0f, len );
1867 628520 : set_f( hReverb->loopBufImag[bin], 0.0f, len );
1868 :
1869 : /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long
1870 : * but not excessively long loops to generate reverberation. */
1871 : /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */
1872 628520 : hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 );
1873 628520 : hReverb->loopBufLength[bin] = min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] );
1874 :
1875 : /* Sparse Filter Tap Locations */
1876 1885560 : for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
1877 : {
1878 1257040 : len = hReverb->loopBufLength[bin];
1879 :
1880 1257040 : if ( ( hReverb->tapPhaseShiftType[bin][chIdx] = (int16_t *) malloc( len * sizeof( int16_t ) ) ) == NULL )
1881 : {
1882 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1883 : }
1884 1257040 : set_s( hReverb->tapPhaseShiftType[bin][chIdx], 0, len );
1885 :
1886 1257040 : if ( ( hReverb->tapPointersReal[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL )
1887 : {
1888 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1889 : }
1890 :
1891 1257040 : if ( ( hReverb->tapPointersImag[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL )
1892 : {
1893 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1894 : }
1895 :
1896 1257040 : len = hReverb->blockSize;
1897 1257040 : if ( ( hReverb->outputBufferReal[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
1898 : {
1899 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1900 : }
1901 :
1902 1257040 : if ( ( hReverb->outputBufferImag[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL )
1903 : {
1904 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
1905 : }
1906 :
1907 1257040 : set_f( hReverb->outputBufferReal[bin][chIdx], 0.0f, len );
1908 1257040 : set_f( hReverb->outputBufferImag[bin][chIdx], 0.0f, len );
1909 : }
1910 : }
1911 :
1912 16075 : ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, revTimes, revEnes );
1913 :
1914 16075 : ivas_binaural_reverb_setPreDelay( hReverb, preDelay );
1915 :
1916 16075 : return IVAS_ERR_OK;
1917 : }
1918 :
1919 :
1920 : /*-------------------------------------------------------------------------
1921 : * ivas_binaural_reverb_init()
1922 : *
1923 : * Initialize binaural room reverberator handle for FastConv renderer
1924 : *------------------------------------------------------------------------*/
1925 :
1926 16075 : ivas_error ivas_binaural_reverb_init(
1927 : REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */
1928 : const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i : HRTF statistics handle */
1929 : const int16_t numBins, /* i : number of CLDFB bins */
1930 : const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */
1931 : const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */
1932 : const int32_t sampling_rate, /* i : sampling rate */
1933 : const float *defaultTimes, /* i : default reverberation times */
1934 : const float *defaultEne, /* i : default reverberation energies */
1935 : float *earlyEne /* i/o: Early part energies to be modified */
1936 : )
1937 : {
1938 : ivas_error error;
1939 : int16_t preDelay, bin;
1940 : float revTimes[CLDFB_NO_CHANNELS_MAX];
1941 : float revEne[CLDFB_NO_CHANNELS_MAX];
1942 :
1943 16075 : if ( roomAcoustics != NULL )
1944 : {
1945 8198 : if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, revTimes, revEne ) ) != IVAS_ERR_OK )
1946 : {
1947 0 : return error;
1948 : }
1949 :
1950 : /* Convert preDelay from seconds to CLDFB slots as needed by binaural reverb */
1951 8198 : preDelay = (int16_t) roundf( roomAcoustics->acousticPreDelay * CLDFB_SLOTS_PER_SECOND );
1952 : }
1953 : else
1954 : {
1955 321947 : for ( bin = 0; bin < numBins; bin++ )
1956 : {
1957 314070 : revTimes[bin] = defaultTimes[bin];
1958 314070 : revEne[bin] = defaultEne[bin];
1959 : }
1960 7877 : preDelay = 10;
1961 : }
1962 :
1963 644595 : for ( bin = 0; bin < numBins; bin++ )
1964 : {
1965 : /* Adjust the room effect parameters when the reverberation time is less than a threshold value, to avoid
1966 : spectral artefacts with the synthetic reverberator. */
1967 628520 : if ( revTimes[bin] < REV_TIME_THRESHOLD )
1968 : {
1969 : float adjustedEarlyEne, adjustedLateEne, adjustedRevTime;
1970 : float revTimeModifier, energyModifier;
1971 :
1972 : /* Adjust reverberation times, higher towards a threshold */
1973 225932 : revTimeModifier = fmaxf( 0.0f, 1.0f - ( revTimes[bin] / REV_TIME_THRESHOLD ) );
1974 225932 : adjustedRevTime = ( 1.0f - revTimeModifier ) * revTimes[bin];
1975 225932 : adjustedRevTime += revTimeModifier * ( revTimes[bin] + REV_TIME_THRESHOLD ) * 0.5f;
1976 225932 : energyModifier = ( adjustedRevTime - revTimes[bin] ) / adjustedRevTime;
1977 :
1978 : /* Adjust early and late energies, by moving late energy to early energy */
1979 225932 : if ( earlyEne != NULL )
1980 : {
1981 175151 : adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier;
1982 175151 : earlyEne[bin] = adjustedEarlyEne; /* Store already here */
1983 : }
1984 :
1985 225932 : adjustedLateEne = revEne[bin] * ( 1.0f - energyModifier );
1986 :
1987 : /* Store adjusted room effect parameters to be used in reverb processing */
1988 225932 : revTimes[bin] = adjustedRevTime;
1989 225932 : revEne[bin] = adjustedLateEne;
1990 : }
1991 : }
1992 :
1993 16075 : error = ivas_binaural_reverb_open( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay );
1994 :
1995 16075 : return error;
1996 : }
1997 :
1998 :
1999 : /*-------------------------------------------------------------------------
2000 : * ivas_binaural_reverb_close()
2001 : *
2002 : * Close binaural room reverberator handle
2003 : *------------------------------------------------------------------------*/
2004 :
2005 16075 : void ivas_binaural_reverb_close(
2006 : REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */
2007 : )
2008 : {
2009 : int16_t bin, chIdx;
2010 :
2011 16075 : if ( hReverb == NULL || *hReverb == NULL )
2012 : {
2013 0 : return;
2014 : }
2015 :
2016 644595 : for ( bin = 0; bin < ( *hReverb )->numBins; bin++ )
2017 : {
2018 1885560 : for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
2019 : {
2020 1257040 : free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] );
2021 1257040 : free( ( *hReverb )->tapPointersReal[bin][chIdx] );
2022 1257040 : free( ( *hReverb )->tapPointersImag[bin][chIdx] );
2023 1257040 : free( ( *hReverb )->outputBufferReal[bin][chIdx] );
2024 1257040 : free( ( *hReverb )->outputBufferImag[bin][chIdx] );
2025 : }
2026 628520 : free( ( *hReverb )->loopBufReal[bin] );
2027 628520 : free( ( *hReverb )->loopBufImag[bin] );
2028 : }
2029 :
2030 16075 : free( ( *hReverb ) );
2031 16075 : ( *hReverb ) = NULL;
2032 :
2033 16075 : return;
2034 : }
|