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