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