Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include "options.h"
35 : #include "prot_fx.h"
36 : #include "ivas_prot_rend_fx.h"
37 : #include "ivas_cnst.h"
38 : #include "math.h"
39 : #include "ivas_rom_rend.h"
40 : #include <assert.h>
41 : #include "wmc_auto.h"
42 : #include "debug.h"
43 :
44 2767 : static Word16 wrap_rad_fixed(
45 : Word32 angle /* Q13 */ )
46 : {
47 2767 : Word32 L_tmp = angle;
48 2767 : move32();
49 :
50 : /* Wrap azimuth value */
51 6965 : WHILE( GT_32( L_tmp, EVS_PI_FX ) )
52 : {
53 4198 : L_tmp = L_sub( L_tmp, EVS_2PI_FX );
54 : }
55 2767 : WHILE( LE_32( L_tmp, -EVS_PI_FX ) )
56 : {
57 0 : L_tmp = L_add( L_tmp, EVS_2PI_FX );
58 : }
59 :
60 2767 : return extract_l( L_tmp );
61 : }
62 :
63 : /* The reverberator structure implemented here is described in detail in:
64 : * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator.
65 : * Journal of the Audio Engineering Society, 59(12), 936-943. */
66 :
67 : /*-------------------------------------------------------------------------
68 : * Local constants
69 : *------------------------------------------------------------------------*/
70 :
71 : #define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */
72 :
73 : #define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */
74 :
75 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
76 : #define REV_TIME_THRESHOLD ( 13421773 ) /* 0.2f in Q26 */
77 : #define Q26_REV_TIME_THRESHOLD_TIMES_0_5 ( 6710886 ) /* 0.2 * 0.5 in Q26 */
78 : #define Q29_0_5_PER_REV_TIME_THRESHOLD ( 1342177280 ) /* 0.2 / 0.5 in Q29 */
79 : #endif
80 :
81 : #define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */
82 : /* should be a divisor of the frame length at any sampling rate and an even number*/
83 : #define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */
84 : #define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */
85 : #define FFT_FILTER_WND_FLAT_REGION_FX ( 26214 ) /*Q16 flat section (==1) length of FFT filter window, in proportion to overlap */
86 : #define FFT_FILTER_WND_TRANS_REGION_FX ( 9830 ) /*Q16 transition (1->0) length of FFT filter window, in proportion to overlap */
87 : #define REF_LF_MIN ( 100.0f )
88 : #define REF_LF_MAX ( 250.0f )
89 : #define REF_HF_MIN ( 5000.0f )
90 : #define REF_HF_MAX ( 7950.0f )
91 :
92 : #define REF_LF_MIN_FX ( 100 )
93 : #define REF_LF_MAX_FX ( 250 )
94 : #define REF_HF_MIN_FX ( 5000 )
95 : #define REF_HF_MAX_FX ( 7950 )
96 : #define LF_BIAS ( 0.5f )
97 :
98 : #define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */
99 : #define DMX_GAIN ( 1410542208 )
100 : #define IVAS_REVERB_FFT_SIZE_48K ( 512 )
101 : #define IVAS_REVERB_FFT_SIZE_32K ( 512 )
102 : #define IVAS_REVERB_FFT_SIZE_16K ( 256 )
103 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 )
104 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 )
105 : #define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 )
106 :
107 : #define MAX_NR_OUTPUTS ( 2 )
108 :
109 : #ifdef FIX_1942_ASSERTION_LOWSHELF
110 : #define M60Q9 ( -30720 ) //-60 in Q9
111 : #define M120Q8 ( -30720 ) //-120 in Q8
112 : #endif
113 :
114 : const Word16 init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 };
115 : const Word16 default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 };
116 : const Word16 default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 };
117 : const Word16 default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 };
118 :
119 : /*------------------------------------------------------------------------------------------*
120 : * Local Struct definition
121 : *------------------------------------------------------------------------------------------*/
122 : typedef struct ivas_reverb_params_t
123 : {
124 : Word16 pre_delay; /* Delay of the FDC reverb, first peak after pre_delay samples. Note that */
125 : /* there may be non-zero samples earlier due to the filters being */
126 : /* linear-phase. */
127 : Word16 nr_loops; /* Number of feedback loops (= L) */
128 : Word16 pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples. */ /* Feedback [L][L] matrix that mixes the signals of the loops. */
129 : Word32 pLoop_feedback_matrix_fx[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES]; /* Feedback [L][L] matrix that mixes the signals of the loops. */
130 : Word16 nr_outputs; /* Nr of signals extracted from the loops (= S). */
131 : /* Currently this is fixed to 2. */ /* Mix [S][L] matrix from feedback loops to outputs. */
132 : Word16 pLoop_extract_matrix_fx[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs. */ /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback. */
133 : Word16 t60_filter_order; /* Filter order (length of vector) */
134 : Word16 pT60_filter_coeff_fx[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH];
135 : /* In Matlab: IIR: [(2 * L) x (<order> + 1)] (odd: b-vector, even: a-vector) */
136 : /* In Matlab: FIR: [L x <order>] */
137 : Word32 *pFc_fx; /* Center frequencies for FFT filter design */
138 : Word32 *pRt60_fx; /* RT60 values at these frequencies */
139 : Word16 *pRt60_e; /* exponents for RT60 values at these frequencies */
140 : Word32 *pDsr_fx; /* DSR values at these frequencies */
141 : Word16 *pDsr_e; /* DSR values at these frequencies */
142 : #ifndef FIX_1053_REVERB_RECONFIGURATION
143 : Word32 *pHrtf_avg_pwr_response_l_fx; /* The HRTF set's average left ear power response */
144 : Word32 *pHrtf_avg_pwr_response_r_fx; /* The HRTF set's average right ear power response */
145 : Word32 *pHrtf_inter_aural_coherence_fx; /* The HRTF set's inter-aural coherence for diffuse sound */
146 : #endif
147 : const Word32 *pHrtf_avg_pwr_response_l_const_fx; /* The HRTF set's average left ear power response */
148 : const Word32 *pHrtf_avg_pwr_response_r_const_fx; /* The HRTF set's average right ear power response */
149 : const Word32 *pHrtf_inter_aural_coherence_const_fx; /* The HRTF set's inter-aural coherence for diffuse sound */
150 :
151 : Word16 do_corr_filter; /* Flag indicating whether correlation filters should be used. */
152 : /* Correlation only supported and needed for binaural playback (i.e. */
153 : /* when nr_outputs != 2 correlation filtering is never supported). */
154 : } ivas_reverb_params_t;
155 :
156 : /*------------------------------------------------------------------------------------------*
157 : * Static functions declarations
158 : *------------------------------------------------------------------------------------------*/
159 :
160 : static ivas_error calc_jot_t60_coeffs_fx( Word16 *pH_dB_fx, Word16 pH_dB_exp, const UWord16 nrFrequencies, Word16 *pFrequencies_fx, Word16 *pCoeffA_fx, Word16 *pCoeffB_fx, const Word16 fNyquist_fx );
161 :
162 : /*-------------------------------------------------------------------------
163 : * binRend_rand()
164 : *
165 : *
166 : *------------------------------------------------------------------------*/
167 :
168 3498271 : static UWord16 binRend_rand(
169 : REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle */
170 : )
171 : {
172 3498271 : hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345;
173 :
174 3498271 : return (UWord16) ( hReverb->binRend_RandNext / 65536 ) % 32768;
175 : }
176 :
177 :
178 : /*-------------------------------------------------------------------------
179 : * ivas_binaural_reverb_setPreDelay()
180 : *
181 : *
182 : *------------------------------------------------------------------------*/
183 :
184 477 : static void ivas_binaural_reverb_setPreDelay_fx(
185 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
186 : const Word16 delaySamples /* i : reverb pre-delay in CLDFB slots */
187 : )
188 : {
189 477 : IF( LT_16( delaySamples, 1 ) )
190 : {
191 0 : hReverb->preDelayBufferLength = 1;
192 0 : move16();
193 :
194 0 : return;
195 : }
196 :
197 477 : IF( GT_16( delaySamples, REVERB_PREDELAY_MAX ) )
198 : {
199 4 : hReverb->preDelayBufferLength = REVERB_PREDELAY_MAX;
200 4 : move16();
201 :
202 4 : return;
203 : }
204 :
205 473 : hReverb->preDelayBufferLength = delaySamples;
206 473 : move16();
207 :
208 473 : return;
209 : }
210 :
211 :
212 : /*-------------------------------------------------------------------------
213 : * ivas_binaural_reverb_setReverbTimes()
214 : *
215 : *
216 : *------------------------------------------------------------------------*/
217 :
218 :
219 477 : static void ivas_binaural_reverb_setReverbTimes_fx(
220 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
221 : const Word32 output_Fs, /* i : sampling_rate */
222 : const Word32 *revTimes_fx, /*Q26 i : reverberation times T60 for each CLDFB bin in seconds */
223 : const Word32 *revEnes_fx /*Q31 i : spectrum for reverberated sound at each CLDFB bin */
224 : )
225 : {
226 : Word16 bin, ch, tap, sample;
227 :
228 : Word32 binCenterFreq_fx, diffuseFieldICC_fx, tmpVal_fx, attenuationFactorPerSample_fx, L_tmp;
229 : Word32 intendedEnergy_fx, actualizedEnergy_fx, energyBuildup_fx, currentEnergy_fx, attenuationFactorPerSampleSq_fx;
230 : Word16 tmp, tmp_exp, scale, tmpVal_exp, attenuationFactorPerSample_exp, attenuationFactorPerSampleSq_exp, energyBuildup_exp, currentEnergy_exp, intendedEnergy_exp, actualizedEnergy_exp;
231 : Word16 sine_inp, norm, div_exp1, div1, sine, binCenterFreq_exp;
232 477 : Word16 reverb_exp = 0;
233 477 : move16();
234 :
235 477 : hReverb->binRend_RandNext = (UWord16) BIN_REND_RANDOM_SEED;
236 477 : move16();
237 477 : hReverb->highestBinauralCoherenceBin = 0;
238 477 : move16();
239 :
240 20747 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
241 : {
242 : /* Determine the diffuse field binaural coherence */
243 : Word16 exp;
244 20270 : tmp_exp = BASOP_Util_Add_MantExp( bin, 15, 1, 14, &tmp );
245 20270 : tmp = BASOP_Util_Divide3232_Scale( L_deposit_h( tmp ), L_deposit_h( hReverb->numBins ), &exp );
246 20270 : exp = add( exp, sub( tmp_exp, 15 ) );
247 20270 : L_tmp = Mpy_32_16_1( output_Fs, tmp ); /*- exp */
248 20270 : binCenterFreq_exp = add( 31, exp );
249 20270 : binCenterFreq_fx = L_shr( L_tmp, 1 ); // divide by 2
250 : #ifdef FIX_1931_BIN_COHR_CROSS_MIX
251 20270 : norm = norm_l( binCenterFreq_fx );
252 20270 : binCenterFreq_fx = L_shl( binCenterFreq_fx, norm );
253 20270 : binCenterFreq_exp = sub( binCenterFreq_exp, norm );
254 : #endif
255 20270 : IF( bin == 0 )
256 : {
257 477 : diffuseFieldICC_fx = ONE_IN_Q31;
258 477 : move32();
259 : }
260 19793 : ELSE IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( binCenterFreq_fx, binCenterFreq_exp, 2700, 31 ), -1 ) )
261 : {
262 : /* binCenterFreq / 550.0f */
263 2767 : L_tmp = Mpy_32_32( binCenterFreq_fx, 3904516 /* 1 / 550 in Q31 */ );
264 2767 : norm = norm_l( L_tmp );
265 2767 : tmp = extract_h( L_shl( L_tmp, norm ) );
266 2767 : tmp = add( mult( EVS_PI_FX, tmp ), EPSILLON_FX ); // to avoid divide by 0 issue
267 2767 : tmp_exp = sub( add( binCenterFreq_exp, 2 ), norm );
268 :
269 2767 : sine_inp = wrap_rad_fixed( L_shl( tmp, sub( tmp_exp, 2 ) ) ); // Q13
270 :
271 2767 : sine = getSinWord16( sine_inp ); // Q15
272 2767 : div1 = BASOP_Util_Divide1616_Scale( sine, tmp, &scale );
273 2767 : div_exp1 = add( scale, sub( 0, tmp_exp ) );
274 2767 : div1 = shl( div1, div_exp1 ); /* Q15 */
275 :
276 : /* binCenterFreq / 2700.0f */
277 2767 : L_tmp = Mpy_32_32( binCenterFreq_fx, 795364 /* 1 / 2700 in Q31 */ );
278 : #ifdef FIX_1931_BIN_COHR_CROSS_MIX
279 2767 : L_tmp = L_shl( L_tmp, binCenterFreq_exp ); /* Q31 */
280 : #else
281 : norm = norm_l( L_tmp );
282 : L_tmp = L_shl( L_tmp, norm ); /* Q31 */
283 : #endif
284 : /* ( 1.0f - binCenterFreq / 2700.0f ) */
285 2767 : L_tmp = L_sub( ONE_IN_Q31, L_tmp ); /* Q31 */
286 :
287 2767 : diffuseFieldICC_fx = Mpy_32_16_1( L_tmp, div1 ); /* Q31 */
288 :
289 2767 : hReverb->highestBinauralCoherenceBin = bin;
290 2767 : move16();
291 : }
292 : ELSE
293 : {
294 :
295 17026 : diffuseFieldICC_fx = 0;
296 17026 : move32();
297 : }
298 :
299 : /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */
300 : /* tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f; */
301 20270 : L_tmp = Mpy_32_32( diffuseFieldICC_fx, diffuseFieldICC_fx ); // square
302 20270 : L_tmp = L_sub( ONE_IN_Q31, L_tmp );
303 20270 : scale = 0;
304 20270 : L_tmp = Sqrt32( L_tmp, &scale );
305 20270 : L_tmp = L_shl( L_tmp, scale ); /* Q31 */
306 20270 : tmpVal_fx = L_shr( L_sub( ONE_IN_Q31, L_tmp ), 1 );
307 20270 : tmpVal_exp = 0;
308 20270 : move16();
309 :
310 20270 : IF( diffuseFieldICC_fx > 0 )
311 : {
312 1431 : exp = tmpVal_exp;
313 1431 : move16();
314 1431 : L_tmp = Sqrt32( L_abs( tmpVal_fx ), &exp );
315 1431 : hReverb->binauralCoherenceCrossmixGains_fx[bin] = L_shl( L_tmp, exp ); // Q31
316 : }
317 : ELSE
318 : {
319 18839 : exp = tmpVal_exp;
320 18839 : move16();
321 18839 : L_tmp = Sqrt32( L_abs( tmpVal_fx ), &exp );
322 18839 : hReverb->binauralCoherenceCrossmixGains_fx[bin] = L_negate( L_shl( L_tmp, exp ) ); // Q31
323 : }
324 :
325 : /* hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) ); */
326 20270 : exp = tmpVal_exp;
327 20270 : move16();
328 20270 : L_tmp = L_sub( ONE_IN_Q31, L_abs( tmpVal_fx ) );
329 20270 : L_tmp = Sqrt32( L_abs( L_tmp ), &exp );
330 20270 : hReverb->binauralCoherenceDirectGains_fx[bin] = L_shl( L_tmp, exp ); // making as Q31
331 :
332 : /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */
333 20270 : L_tmp = Mpy_32_32( 1677721600, revTimes_fx[bin] ); // e10 --> 800 * 2^21, + e0
334 20270 : tmp = BASOP_Util_Divide3232_Scale( 1073741824, L_tmp, &scale );
335 20270 : scale = add( scale, sub( 1, 15 ) ); // revTimes_fx in Q26
336 20270 : L_tmp = Mpy_32_16_1( -1610612736, tmp ); // * -3
337 20270 : scale = add( 2, scale );
338 20270 : L_tmp = Mpy_32_32( 1783446563, L_tmp ); // scale + 2
339 20270 : attenuationFactorPerSample_fx = BASOP_util_Pow2( L_tmp, add( scale, 2 ), &attenuationFactorPerSample_exp );
340 :
341 : Word32 tmp_mul;
342 20270 : scale = norm_l( hReverb->loopBufLength[bin] );
343 20270 : tmp_mul = L_shl( hReverb->loopBufLength[bin], scale );
344 20270 : L_tmp = BASOP_Util_Log2( attenuationFactorPerSample_fx ); // Q25
345 20270 : L_tmp = L_add( L_tmp, L_shl( (Word32) attenuationFactorPerSample_exp, 25 ) ); // Q25
346 20270 : L_tmp = Mpy_32_32( L_tmp, tmp_mul );
347 20270 : L_tmp = BASOP_util_Pow2( L_tmp, sub( 6 + 31, scale ), &exp );
348 20270 : hReverb->loopAttenuationFactor_fx[bin] = L_shl( L_tmp, exp ); // making as Q31
349 :
350 20270 : attenuationFactorPerSampleSq_fx = Mpy_32_32( attenuationFactorPerSample_fx, attenuationFactorPerSample_fx );
351 20270 : attenuationFactorPerSampleSq_exp = attenuationFactorPerSample_exp + attenuationFactorPerSample_exp;
352 :
353 : /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved,
354 : * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */
355 :
356 20270 : intendedEnergy_fx = 0;
357 20270 : move32();
358 20270 : intendedEnergy_exp = 0;
359 20270 : move16();
360 20270 : actualizedEnergy_fx = 0;
361 20270 : move32();
362 20270 : actualizedEnergy_exp = 0;
363 20270 : move16();
364 :
365 60810 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
366 : {
367 :
368 40540 : energyBuildup_fx = 0;
369 40540 : move32();
370 40540 : energyBuildup_exp = 0;
371 40540 : move16();
372 40540 : currentEnergy_fx = ONE_IN_Q30;
373 40540 : move32();
374 40540 : currentEnergy_exp = 1;
375 40540 : move16();
376 :
377 40540 : tap = 0;
378 40540 : move16();
379 :
380 2574672 : FOR( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ )
381 : {
382 2534132 : intendedEnergy_fx = BASOP_Util_Add_Mant32Exp( intendedEnergy_fx, intendedEnergy_exp, currentEnergy_fx, currentEnergy_exp, &intendedEnergy_exp );
383 : /* The randomization at the energy build up affects where the sparse taps are located */
384 :
385 2534132 : UWord16 ret_binRend = binRend_rand( hReverb );
386 :
387 2534132 : tmp = BASOP_Util_Divide3232_Scale( ret_binRend, PCM16_TO_FLT_FAC_FX, &tmp_exp );
388 2534132 : L_tmp = BASOP_Util_Add_Mant32Exp( L_deposit_h( tmp ), tmp_exp, L_negate( 1073741824 ), 0, &exp );
389 2534132 : L_tmp = Mpy_32_32( L_tmp, 214748364 ); // exp + 0
390 2534132 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, exp, currentEnergy_fx, currentEnergy_exp, &exp );
391 2534132 : energyBuildup_fx = BASOP_Util_Add_Mant32Exp( energyBuildup_fx, energyBuildup_exp, L_tmp, exp, &energyBuildup_exp );
392 2534132 : IF( energyBuildup_fx >= 0 ) /* A new filter tap is added at this condition */
393 : {
394 2533789 : IF( ( BASOP_Util_Cmp_Mant32Exp( energyBuildup_fx, energyBuildup_exp, 1, 31 ) > 0 ) )
395 : {
396 : /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */
397 964139 : hReverb->tapPhaseShiftType[bin][ch][tap] = (Word16) ( binRend_rand( hReverb ) % 4 );
398 964139 : move16();
399 : /* Set the tapPointer to point to the determined sample at the loop buffer */
400 :
401 964139 : hReverb->tapPointersReal_fx[bin][ch][tap] = &( hReverb->loopBufReal_fx[bin][sample] );
402 964139 : hReverb->tapPointersImag_fx[bin][ch][tap] = &( hReverb->loopBufImag_fx[bin][sample] );
403 :
404 964139 : energyBuildup_fx = BASOP_Util_Add_Mant32Exp( energyBuildup_fx, energyBuildup_exp, L_negate( 1073741824 ), 1, &energyBuildup_exp ); /* A tap is added, thus remove its energy from the buildup */
405 :
406 964139 : tap = add( tap, 1 );
407 :
408 964139 : actualizedEnergy_fx = BASOP_Util_Add_Mant32Exp( actualizedEnergy_fx, actualizedEnergy_exp, 1073741824, 1, &actualizedEnergy_exp );
409 : }
410 : }
411 :
412 2534132 : currentEnergy_fx = BASOP_Util_Add_Mant32Exp( currentEnergy_fx, currentEnergy_exp, 0, 0, ¤tEnergy_exp );
413 2534132 : currentEnergy_fx = Mpy_32_32( currentEnergy_fx, attenuationFactorPerSampleSq_fx );
414 2534132 : currentEnergy_exp = currentEnergy_exp + attenuationFactorPerSampleSq_exp;
415 : }
416 :
417 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
418 : /* In some configurations with small T60s it is possible the number of taps randomizes to zero.
419 : Ensure at least 1 filter tap. */
420 40540 : IF( EQ_16( tap, 0 ) )
421 : {
422 0 : hReverb->tapPhaseShiftType[bin][ch][0] = (Word16) ( binRend_rand( hReverb ) % 4 );
423 0 : move16();
424 0 : hReverb->tapPointersReal_fx[bin][ch][0] = &( hReverb->loopBufReal_fx[bin][0] );
425 0 : hReverb->tapPointersImag_fx[bin][ch][0] = &( hReverb->loopBufImag_fx[bin][0] );
426 0 : tap = 1;
427 0 : move16();
428 0 : actualizedEnergy_fx = ONE_IN_Q30;
429 0 : move32();
430 0 : actualizedEnergy_exp = 1;
431 0 : move16();
432 : }
433 : #endif
434 :
435 40540 : hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */
436 40540 : move16();
437 : }
438 :
439 : /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */
440 20270 : reverb_exp = 0;
441 20270 : move16();
442 20270 : hReverb->reverbEqGains_fx[bin] = Sqrt32( revEnes_fx[bin], &reverb_exp ); /* Determined reverb spectrum */
443 20270 : move32();
444 20270 : hReverb->reverbEqGains_fx[bin] = BASOP_Util_Add_Mant32Exp( hReverb->reverbEqGains_fx[bin], reverb_exp, 0, 0, &reverb_exp );
445 20270 : move32();
446 :
447 20270 : tmp = BASOP_Util_Divide3232_Scale( intendedEnergy_fx, actualizedEnergy_fx, &tmp_exp );
448 20270 : tmp_exp = add( tmp_exp, sub( intendedEnergy_exp, actualizedEnergy_exp ) );
449 20270 : hReverb->reverbEqGains_fx[bin] = BASOP_Util_Add_Mant32Exp( hReverb->reverbEqGains_fx[bin], reverb_exp, 0, 0, &reverb_exp );
450 20270 : move32();
451 20270 : L_tmp = Sqrt32( L_deposit_h( tmp ), &tmp_exp );
452 20270 : hReverb->reverbEqGains_fx[bin] = Mpy_32_32( hReverb->reverbEqGains_fx[bin], L_tmp );
453 20270 : move32();
454 20270 : reverb_exp = add( reverb_exp, tmp_exp );
455 :
456 20270 : L_tmp = BASOP_Util_Add_Mant32Exp( 1073741824, 1, L_negate( attenuationFactorPerSampleSq_fx ), attenuationFactorPerSampleSq_exp, &tmp_exp );
457 20270 : L_tmp = Mpy_32_32( L_tmp, 1073741824 ); // tmp_exp + 1
458 20270 : tmp_exp = add( tmp_exp, 0 );
459 20270 : L_tmp = Sqrt32( L_tmp, &tmp_exp );
460 20270 : hReverb->reverbEqGains_fx[bin] = Mpy_32_32( L_tmp, hReverb->reverbEqGains_fx[bin] );
461 20270 : move32();
462 20270 : reverb_exp = add( reverb_exp, tmp_exp );
463 20270 : hReverb->reverbEqGains_fx[bin] = L_shl( hReverb->reverbEqGains_fx[bin], reverb_exp ); // making as Q31
464 20270 : move32();
465 : }
466 477 : return;
467 : }
468 :
469 : /*-----------------------------------------------------------------------------------------*
470 : * Function compute_feedback_matrix()
471 : *
472 : * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again
473 : *-----------------------------------------------------------------------------------------*/
474 :
475 218 : static ivas_error compute_feedback_matrix_fx(
476 : Word32 *pFeedbackMatrix, // Q31
477 : const Word16 n )
478 : {
479 : Word32 u;
480 : Word16 i, j, x;
481 :
482 218 : u = MATRIX_CONSTANT; // Q31
483 218 : move32();
484 :
485 218 : pFeedbackMatrix[0] = u;
486 218 : move32();
487 872 : FOR( x = 1; x < n; x += x )
488 : {
489 2180 : FOR( i = 0; i < x; i++ )
490 : {
491 6104 : FOR( j = 0; j < x; j++ )
492 : {
493 4578 : pFeedbackMatrix[add( i_mult( add( i, x ), n ), j )] = pFeedbackMatrix[add( i_mult( i, n ), j )];
494 4578 : move32();
495 4578 : pFeedbackMatrix[i_mult( i, n ) + j + x] = pFeedbackMatrix[add( i_mult( i, n ), j )];
496 4578 : move32();
497 4578 : pFeedbackMatrix[add( add( i_mult( add( i, x ), n ), j ), x )] = L_negate( pFeedbackMatrix[add( i_mult( i, n ), j )] );
498 4578 : move32();
499 : }
500 : }
501 : }
502 :
503 :
504 218 : return IVAS_ERR_OK;
505 : }
506 :
507 :
508 : /*-----------------------------------------------------------------------------------------*
509 : * Function compute_2_out_extract_matrix()
510 : *
511 : * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs
512 : *-----------------------------------------------------------------------------------------*/
513 :
514 218 : static void compute_2_out_extract_matrix_fx(
515 : Word16 *pExtractMatrix,
516 : const Word16 n )
517 : {
518 : Word16 ff;
519 : Word16 i;
520 :
521 218 : ff = 1;
522 218 : move16();
523 :
524 1962 : FOR( i = 0; i < n; i++ )
525 : {
526 1744 : pExtractMatrix[i] = 1;
527 1744 : move16();
528 1744 : pExtractMatrix[add( i, n )] = ff;
529 1744 : move16();
530 1744 : ff = negate( ff );
531 : }
532 :
533 218 : return;
534 : }
535 : /*-----------------------------------------------------------------------------------------*
536 : * Function set_base_config()
537 : *
538 : * Set all jot reverb parameters that are independent of the input reverb configuration
539 : *-----------------------------------------------------------------------------------------*/
540 :
541 218 : static ivas_error set_base_config_fx(
542 : ivas_reverb_params_t *pParams,
543 : const Word32 output_Fs )
544 : {
545 : ivas_error error;
546 : Word16 loop_idx;
547 218 : const Word16 *selected_loop_delay = NULL;
548 :
549 218 : IF( pParams == NULL )
550 : {
551 0 : return IVAS_ERR_INTERNAL;
552 : }
553 :
554 218 : pParams->pre_delay = 0;
555 218 : move16();
556 218 : pParams->nr_outputs = BINAURAL_CHANNELS;
557 218 : move16();
558 218 : pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES;
559 218 : move16();
560 :
561 : /* set loop delays to default */
562 218 : IF( EQ_32( output_Fs, 48000 ) )
563 : {
564 127 : selected_loop_delay = default_loop_delay_48k; // Q0
565 : }
566 91 : ELSE IF( EQ_32( output_Fs, 32000 ) )
567 : {
568 30 : selected_loop_delay = default_loop_delay_32k; // Q0
569 : }
570 61 : ELSE IF( EQ_32( output_Fs, 16000 ) )
571 : {
572 61 : selected_loop_delay = default_loop_delay_16k; // Q0
573 : }
574 :
575 1962 : FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
576 : {
577 1744 : pParams->pLoop_delays[loop_idx] = selected_loop_delay[loop_idx];
578 1744 : move16();
579 : }
580 :
581 : /* set feedback and output matrices */
582 218 : IF( NE_32( ( error = compute_feedback_matrix_fx( pParams->pLoop_feedback_matrix_fx, pParams->nr_loops ) ), IVAS_ERR_OK ) )
583 : {
584 0 : return error;
585 : }
586 :
587 218 : compute_2_out_extract_matrix_fx( pParams->pLoop_extract_matrix_fx, pParams->nr_loops );
588 : /* pre-set the various filters; they will be set later based on reverb configuration */
589 218 : pParams->t60_filter_order = 1; /* set to 1 in base config. */
590 218 : move16();
591 :
592 218 : IF( EQ_16( pParams->nr_outputs, 2 ) )
593 : {
594 218 : pParams->do_corr_filter = 1;
595 218 : move16();
596 : }
597 : ELSE
598 : {
599 0 : pParams->do_corr_filter = 0;
600 0 : move16();
601 : }
602 :
603 218 : return IVAS_ERR_OK;
604 : }
605 :
606 : /*-----------------------------------------------------------------------------------------*
607 : * Function calc_dmx_gain()
608 : *
609 : * Computes the downmix gain
610 : *-----------------------------------------------------------------------------------------*/
611 163 : static Word32 calc_dmx_gain_fx( void )
612 : {
613 163 : const Word32 gain = DMX_GAIN; // Q23
614 163 : move32();
615 163 : return gain;
616 : }
617 : /*-----------------------------------------------------------------------------------------*
618 : * Function calc_predelay()
619 : *
620 : * Calculate the predelay, taking shortest jot loop delay into account
621 : *-----------------------------------------------------------------------------------------*/
622 :
623 218 : static void calc_predelay_fx(
624 : ivas_reverb_params_t *pParams,
625 : Word32 acoustic_predelay_sec,
626 : const Word32 output_Fs )
627 : {
628 : Word16 predelay, fbdelay, output_frame;
629 218 : predelay = round_fx( L_shl( Mult_32_32( L_shl( output_Fs, 15 ), acoustic_predelay_sec ), 5 ) );
630 218 : output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) );
631 218 : fbdelay = pParams->pLoop_delays[sub( pParams->nr_loops, 1 )];
632 218 : move16();
633 218 : predelay = sub( predelay, fbdelay );
634 :
635 218 : if ( predelay < 0 )
636 : {
637 0 : predelay = 0;
638 0 : move16();
639 : }
640 :
641 218 : if ( LT_16( output_frame, predelay ) )
642 : {
643 0 : predelay = output_frame; // Q0
644 0 : move16();
645 : }
646 :
647 218 : pParams->pre_delay = predelay; // Q0
648 218 : move16();
649 218 : move16();
650 218 : move16();
651 218 : return;
652 : }
653 :
654 : /*-----------------------------------------------------------------------------------------*
655 : * Function compute_t60_coeffs()
656 : *
657 : * Calculate Jot reverb's T60 filter coefficients
658 : *-----------------------------------------------------------------------------------------*/
659 218 : static ivas_error compute_t60_coeffs_fx(
660 : ivas_reverb_params_t *pParams,
661 : const Word16 nr_fc_fft_filter, /*Q0*/
662 : const Word32 output_Fs )
663 : {
664 : Word16 bin_idx, loop_idx, tf_T60_len, len;
665 : ivas_error error;
666 : #ifdef FIX_1942_ASSERTION_LOWSHELF
667 : Word16 loop_delay_sec_fx, tmp, tmp_e;
668 : #else
669 : Word16 loop_delay_sec_fx, tmp;
670 : #endif
671 218 : Word32 freq_Nyquist_fx = L_shr( output_Fs, 1 );
672 : Word16 target_gains_db_fx[RV_LENGTH_NR_FC]; // Q8
673 : Word16 norm_f_fx[RV_LENGTH_NR_FC];
674 : Word16 *pCoeffs_a_fx, *pCoeffs_b_fx;
675 : Word16 e;
676 : #ifndef FIX_1942_ASSERTION_LOWSHELF
677 : const Word16 min120q8 = -30720; // -120 in Q8
678 : #endif
679 218 : error = IVAS_ERR_OK;
680 218 : move32();
681 218 : tf_T60_len = nr_fc_fft_filter;
682 218 : move16();
683 218 : len = add( pParams->t60_filter_order, 1 );
684 :
685 48436 : FOR( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
686 : {
687 48218 : norm_f_fx[bin_idx] = BASOP_Util_Divide3232_Scale( pParams->pFc_fx[bin_idx], freq_Nyquist_fx, &e );
688 48218 : move16();
689 48218 : e = add( e, sub( 15, 31 ) );
690 48218 : norm_f_fx[bin_idx] = shl( norm_f_fx[bin_idx], sub( e, 1 ) ); // making Q14
691 48218 : move16();
692 : }
693 :
694 1962 : FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
695 : {
696 1744 : loop_delay_sec_fx = BASOP_Util_Divide3232_Scale( pParams->pLoop_delays[loop_idx], output_Fs, &e );
697 1744 : loop_delay_sec_fx = shl( loop_delay_sec_fx, e ); // Q15
698 :
699 387488 : FOR( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ )
700 : {
701 385744 : IF( EQ_32( pParams->pRt60_fx[bin_idx], 0 ) )
702 : {
703 : // If RT60 is 0, target gain is -120dB
704 : #ifdef FIX_1942_ASSERTION_LOWSHELF
705 0 : target_gains_db_fx[bin_idx] = M120Q8;
706 0 : move16();
707 : #else
708 : target_gains_db_fx[bin_idx] = min120q8;
709 : #endif
710 : }
711 : ELSE
712 : {
713 385744 : tmp = BASOP_Util_Divide3232_Scale( L_deposit_h( loop_delay_sec_fx ), pParams->pRt60_fx[bin_idx], &e );
714 : #ifdef FIX_1942_ASSERTION_LOWSHELF
715 385744 : tmp_e = add( e, sub( 0, 5 ) ); // L_deposit_h( loop_delay_sec_fx ):Q0.31, pParams->pRt60_fx[bin_idx]:Q5.26
716 :
717 385744 : tmp_e = add( tmp_e, 6 ); // + Q6.9(M60Q9)
718 385744 : target_gains_db_fx[bin_idx] = mult( M60Q9, tmp );
719 :
720 : // gain < - 120 ? -120: gain
721 385744 : tmp_e = sub( tmp_e, 7 ); // - Q7.8(M120Q8)
722 385744 : IF( GT_16( tmp_e, 0 ) )
723 : {
724 0 : IF( LT_16( target_gains_db_fx[bin_idx], shr( M120Q8, tmp_e ) ) )
725 : {
726 0 : target_gains_db_fx[bin_idx] = M120Q8; // Q8
727 0 : move16();
728 : }
729 : ELSE
730 : {
731 0 : target_gains_db_fx[bin_idx] = shl_r( target_gains_db_fx[bin_idx], tmp_e ); // Q8, gain must be less than 128
732 : }
733 : }
734 : ELSE
735 : {
736 385744 : target_gains_db_fx[bin_idx] = shl_r( target_gains_db_fx[bin_idx], tmp_e ); // Q8, gain must be less than 128
737 385744 : IF( LT_16( target_gains_db_fx[bin_idx], M120Q8 ) )
738 : {
739 0 : target_gains_db_fx[bin_idx] = M120Q8; // Q8
740 0 : move16();
741 : }
742 : }
743 : }
744 : #else
745 : IF( LT_16( e, -1 ) )
746 : {
747 : target_gains_db_fx[bin_idx] = min120q8;
748 : }
749 : ELSE
750 : {
751 : tmp = shr( tmp, sub( 5, e ) ); // scaling tmp to Q15
752 : target_gains_db_fx[bin_idx] = mult( shr( min120q8, 1 ), tmp ); // Q8
753 : }
754 : }
755 : // gain < - 120 ? -120: gain
756 : IF( LT_16( target_gains_db_fx[bin_idx], -30720 ) )
757 : {
758 : target_gains_db_fx[bin_idx] = -30720;
759 : move16();
760 : }
761 : #endif
762 : }
763 :
764 1744 : pCoeffs_a_fx = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( len, loop_idx ), 1 ), len )]; // Q14
765 1744 : pCoeffs_b_fx = &pParams->pT60_filter_coeff_fx[shl( i_mult( len, loop_idx ), 1 )]; // Q14
766 :
767 1744 : move16();
768 :
769 1744 : Word16 val = 7;
770 :
771 1744 : IF( NE_32( ( error = calc_jot_t60_coeffs_fx( target_gains_db_fx, val, tf_T60_len, norm_f_fx, pCoeffs_a_fx, pCoeffs_b_fx, extract_l( freq_Nyquist_fx ) ) ), IVAS_ERR_OK ) )
772 : {
773 0 : return error;
774 : }
775 : }
776 :
777 218 : len = shr( ( add( pParams->t60_filter_order, 1 ) ), 1 ); // Q0// /* == floor( (order+1) / 2) */
778 1962 : FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ )
779 : {
780 1744 : pParams->pLoop_delays[loop_idx] = sub( pParams->pLoop_delays[loop_idx], len ); // Q0
781 1744 : move16();
782 : }
783 218 : return error;
784 : }
785 :
786 :
787 : /*-----------------------------------------------------------------------------------------*
788 : * Function calc_low_shelf_first_order_filter()
789 : *
790 : * Calculate 1st order low shelf filter
791 : *-----------------------------------------------------------------------------------------*/
792 :
793 :
794 1744 : static void calc_low_shelf_first_order_filter_fx(
795 : Word16 *pNum, /* Q14 */
796 : Word16 *pDen, /* Q14 */
797 : const Word16 f0,
798 : const Word16 lin_gain_lf,
799 : const Word16 lin_gain_hf )
800 : {
801 : Word16 sine_val, shift;
802 : Word16 cos_val, tmp, tan_val, tan_exp, gain_exp, exp, norm_num0, norm_num1, norm_den0, norm_den1;
803 : Word32 L_tmp;
804 :
805 1744 : tmp = mult( EVS_PI_BY_2_FX, f0 );
806 1744 : sine_val = getSinWord16( shl( tmp, 1 ) ); // Q15
807 :
808 1744 : tmp = mult( EVS_PI_BY_2_FX, f0 );
809 1744 : cos_val = getCosWord16( shl( tmp, 1 ) ); // Q14
810 :
811 1744 : tan_val = BASOP_Util_Divide1616_Scale( sine_val, cos_val, &tan_exp );
812 1744 : tan_exp = add( tan_exp, sub( 0, 1 ) );
813 :
814 : Word16 gain_fx;
815 1744 : gain_fx = BASOP_Util_Divide1616_Scale( lin_gain_lf, lin_gain_hf, &gain_exp );
816 :
817 1744 : IF( LT_16( gain_fx, 16384 ) )
818 : {
819 :
820 7 : tmp = mult( tan_val, gain_fx );
821 7 : norm_num0 = add( tan_exp, gain_exp );
822 7 : L_tmp = L_add( L_shl( 1, sub( 15, norm_num0 ) ), tmp );
823 7 : shift = norm_l( L_tmp );
824 7 : L_tmp = L_shl( L_tmp, shift );
825 7 : tmp = extract_h( L_tmp );
826 7 : pNum[0] = tmp;
827 7 : move16();
828 7 : norm_num0 = sub( norm_num0, sub( shift, 16 ) );
829 :
830 7 : tmp = mult( tan_val, gain_fx );
831 7 : norm_num1 = add( tan_exp, gain_exp );
832 7 : L_tmp = L_sub( tmp, L_shl( 1, sub( 15, norm_num1 ) ) );
833 7 : shift = norm_l( L_tmp );
834 7 : L_tmp = L_shl( L_tmp, shift );
835 7 : tmp = extract_h( L_tmp );
836 7 : pNum[1] = tmp;
837 7 : move16();
838 7 : norm_num1 = sub( norm_num1, sub( shift, 16 ) );
839 :
840 7 : L_tmp = L_add( L_shl( 1, sub( 15, tan_exp ) ), tan_val );
841 7 : shift = norm_l( L_tmp );
842 7 : L_tmp = L_shl( L_tmp, shift );
843 7 : tmp = extract_h( L_tmp );
844 7 : pDen[0] = tmp;
845 7 : move16();
846 7 : norm_den0 = sub( tan_exp, sub( shift, 16 ) );
847 :
848 7 : L_tmp = L_sub( tan_val, L_shl( 1, sub( 15, tan_exp ) ) );
849 7 : shift = norm_l( L_tmp );
850 7 : L_tmp = L_shl( L_tmp, shift );
851 7 : tmp = extract_h( L_tmp );
852 7 : pDen[1] = tmp;
853 7 : move16();
854 7 : norm_den1 = sub( tan_exp, sub( shift, 16 ) );
855 : }
856 : ELSE
857 : {
858 1737 : L_tmp = L_add( L_shl( 1, ( sub( 15, tan_exp ) ) ), tan_val );
859 1737 : shift = norm_l( L_tmp );
860 1737 : L_tmp = L_shl( L_tmp, shift );
861 1737 : tmp = extract_h( L_tmp );
862 1737 : pNum[0] = tmp;
863 1737 : move16();
864 1737 : norm_num0 = sub( tan_exp, sub( shift, 16 ) );
865 :
866 1737 : L_tmp = L_sub( tan_val, L_shl( 1, ( sub( 15, tan_exp ) ) ) );
867 1737 : shift = norm_l( L_tmp );
868 1737 : L_tmp = L_shl( L_tmp, shift );
869 1737 : tmp = extract_h( L_tmp );
870 1737 : pNum[1] = tmp;
871 1737 : move16();
872 1737 : norm_num1 = sub( tan_exp, sub( shift, 16 ) );
873 :
874 1737 : tmp = BASOP_Util_Divide1616_Scale( tan_val, gain_fx, &exp );
875 1737 : exp = add( exp, sub( tan_exp, gain_exp ) );
876 1737 : L_tmp = L_add( L_shl( 1, sub( 15, exp ) ), tmp );
877 1737 : shift = norm_l( L_tmp );
878 1737 : L_tmp = L_shl( L_tmp, shift );
879 1737 : tmp = extract_h( L_tmp );
880 1737 : pDen[0] = tmp;
881 1737 : move16();
882 1737 : norm_den0 = sub( exp, sub( shift, 16 ) );
883 :
884 1737 : tmp = BASOP_Util_Divide1616_Scale( tan_val, gain_fx, &exp );
885 1737 : exp = add( exp, sub( tan_exp, gain_exp ) );
886 1737 : L_tmp = L_sub( tmp, 1 * L_shl( 1, sub( 15, exp ) ) );
887 1737 : shift = norm_l( L_tmp );
888 1737 : L_tmp = L_shl( L_tmp, shift );
889 1737 : tmp = extract_h( L_tmp );
890 1737 : pDen[1] = tmp;
891 1737 : move16();
892 1737 : norm_den1 = sub( exp, sub( shift, 16 ) );
893 : }
894 :
895 : /* Normalize and adjust gain to match target amplitudes */
896 1744 : pNum[0] = mult( BASOP_Util_Divide1616_Scale( pNum[0], pDen[0], &exp ), lin_gain_hf );
897 1744 : move16();
898 1744 : norm_num0 = add( exp, sub( norm_num0, norm_den0 ) );
899 :
900 1744 : pNum[1] = mult( BASOP_Util_Divide1616_Scale( pNum[1], pDen[0], &exp ), lin_gain_hf );
901 1744 : move16();
902 1744 : norm_num1 = add( exp, sub( norm_num1, norm_den0 ) );
903 :
904 1744 : pDen[1] = BASOP_Util_Divide1616_Scale( pDen[1], pDen[0], &exp );
905 1744 : move16();
906 1744 : norm_den1 = add( exp, sub( norm_den1, norm_den0 ) );
907 :
908 1744 : pNum[0] = shr( pNum[0], sub( 1, norm_num0 ) ); // Q14
909 1744 : move16();
910 1744 : pNum[1] = shr( pNum[1], sub( 1, norm_num1 ) ); // Q14
911 1744 : move16();
912 1744 : pDen[1] = shr( pDen[1], sub( 1, norm_den1 ) ); // Q14
913 1744 : move16();
914 1744 : pDen[0] = shl( 1, 14 ); // Q14
915 1744 : move16();
916 1744 : return;
917 : }
918 :
919 :
920 : /*-----------------------------------------------------------------------------------------*
921 : * Function calc_jot_t60_coeffs()
922 : *
923 : * Calculate Jot reverb's T60 filters
924 : *-----------------------------------------------------------------------------------------*/
925 :
926 :
927 1744 : static ivas_error calc_jot_t60_coeffs_fx(
928 : Word16 *pH_dB_fx,
929 : Word16 pH_dB_exp,
930 : const UWord16 nrFrequencies,
931 : Word16 *pFrequencies_fx,
932 : Word16 *pCoeffA_fx, /* Q14 */
933 : Word16 *pCoeffB_fx, /* Q14 */
934 : const Word16 fNyquist_fx )
935 : {
936 : Word16 scale1, scale2, scale3, scale4;
937 1744 : Word16 ref_lf_min_norm_fx = BASOP_Util_Divide1616_Scale( REF_LF_MIN_FX, fNyquist_fx, &scale1 );
938 1744 : Word16 ref_lf_max_norm_fx = BASOP_Util_Divide1616_Scale( REF_LF_MAX_FX, fNyquist_fx, &scale2 );
939 1744 : Word16 ref_hf_min_norm_fx = BASOP_Util_Divide1616_Scale( REF_HF_MIN_FX, fNyquist_fx, &scale3 );
940 1744 : Word16 ref_hf_max_norm_fx = BASOP_Util_Divide1616_Scale( REF_HF_MAX_FX, fNyquist_fx, &scale4 );
941 :
942 1744 : ref_lf_min_norm_fx = shl( ref_lf_min_norm_fx, sub( scale1, 1 ) ); // Q14
943 1744 : ref_lf_max_norm_fx = shl( ref_lf_max_norm_fx, sub( scale2, 1 ) ); // Q14
944 1744 : ref_hf_min_norm_fx = shl( ref_hf_min_norm_fx, sub( scale3, 1 ) ); // Q14
945 1744 : ref_hf_max_norm_fx = shl( ref_hf_max_norm_fx, sub( scale4, 1 ) ); // Q14
946 :
947 : Word32 L_tmp;
948 : Word16 f0_fx, tmp_fx, lf_target_gain_dB_fx, hf_target_gain_dB_fx, mid_crossing_gain_dB_fx;
949 : Word16 lin_gain_lf_fx, lin_gain_hf_fx, shift, expl, exph;
950 1744 : Word16 f_idx, e = pH_dB_exp;
951 1744 : move16();
952 : UWord16 n_points_lf, n_points_hf;
953 :
954 1744 : lf_target_gain_dB_fx = 0;
955 1744 : move16();
956 1744 : hf_target_gain_dB_fx = 0;
957 1744 : move16();
958 1744 : Word32 minval_fx = 1455191552;
959 1744 : move32();
960 1744 : Word16 minval_e = 67, exp;
961 1744 : move16();
962 :
963 1744 : Word32 L_tmpl = 0, L_tmph = 0;
964 1744 : move32();
965 1744 : move32();
966 1744 : n_points_lf = 0;
967 1744 : move16();
968 1744 : n_points_hf = 0;
969 1744 : move16();
970 1744 : Word16 minidx_fx = sub( nrFrequencies, 1 );
971 :
972 387488 : FOR( f_idx = 0; f_idx < nrFrequencies; f_idx++ )
973 : {
974 385744 : test();
975 385744 : IF( GE_16( pFrequencies_fx[f_idx], ref_lf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_lf_max_norm_fx ) )
976 : {
977 3200 : L_tmpl = L_add( L_tmpl, pH_dB_fx[f_idx] );
978 3200 : n_points_lf = add( n_points_lf, 1 );
979 : }
980 385744 : test();
981 385744 : IF( GE_16( pFrequencies_fx[f_idx], ref_hf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_hf_max_norm_fx ) )
982 : {
983 66440 : L_tmph = L_add( L_tmph, pH_dB_fx[f_idx] );
984 66440 : n_points_hf = add( n_points_hf, 1 );
985 : }
986 : }
987 1744 : shift = norm_l( L_tmpl );
988 1744 : L_tmpl = L_shl( L_tmpl, shift );
989 1744 : tmp_fx = extract_h( L_tmpl );
990 1744 : expl = sub( e, sub( shift, 16 ) );
991 1744 : lf_target_gain_dB_fx = tmp_fx;
992 1744 : move16();
993 :
994 1744 : shift = norm_l( L_tmph );
995 1744 : L_tmph = L_shl( L_tmph, shift );
996 1744 : tmp_fx = extract_h( L_tmph );
997 1744 : exph = sub( e, sub( shift, 16 ) );
998 1744 : hf_target_gain_dB_fx = tmp_fx;
999 1744 : move16();
1000 :
1001 1744 : test();
1002 1744 : IF( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) )
1003 : {
1004 0 : return IVAS_ERR_INTERNAL;
1005 : }
1006 :
1007 1744 : lf_target_gain_dB_fx = BASOP_Util_Divide1616_Scale( lf_target_gain_dB_fx, n_points_lf, &e );
1008 1744 : expl = add( e, sub( expl, 15 ) );
1009 :
1010 1744 : hf_target_gain_dB_fx = BASOP_Util_Divide1616_Scale( hf_target_gain_dB_fx, n_points_hf, &e );
1011 1744 : exph = add( e, sub( exph, 15 ) );
1012 :
1013 1744 : e = BASOP_Util_Add_MantExp( lf_target_gain_dB_fx, expl, negate( hf_target_gain_dB_fx ), exph, &tmp_fx );
1014 1744 : exp = BASOP_Util_Add_MantExp( hf_target_gain_dB_fx, exph, tmp_fx, e - 1, &mid_crossing_gain_dB_fx );
1015 :
1016 384000 : FOR( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ )
1017 : {
1018 : Word16 tmp1;
1019 382256 : e = BASOP_Util_Add_MantExp( pH_dB_fx[f_idx], pH_dB_exp, negate( mid_crossing_gain_dB_fx ), exp, &tmp_fx );
1020 382256 : tmp1 = abs_s( tmp_fx );
1021 :
1022 382256 : tmp_fx = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( tmp1 ), e, minval_fx, minval_e );
1023 :
1024 382256 : IF( EQ_16( tmp_fx, -1 ) )
1025 : {
1026 25199 : minval_fx = L_deposit_h( tmp1 );
1027 25199 : minval_e = e;
1028 25199 : move16();
1029 25199 : minidx_fx = f_idx;
1030 25199 : move16();
1031 : }
1032 : }
1033 :
1034 1744 : f0_fx = pFrequencies_fx[minidx_fx];
1035 1744 : move16();
1036 :
1037 1744 : tmp_fx = mult( lf_target_gain_dB_fx, 5443 ); // expl
1038 1744 : L_tmp = BASOP_util_Pow2( L_deposit_h( tmp_fx ), expl, &e );
1039 1744 : lin_gain_lf_fx = extract_l( L_shr( L_tmp, sub( 16, e ) ) );
1040 :
1041 1744 : tmp_fx = mult( hf_target_gain_dB_fx, 5443 ); // exph
1042 1744 : L_tmp = BASOP_util_Pow2( L_deposit_h( tmp_fx ), exph, &e );
1043 1744 : lin_gain_hf_fx = extract_l( L_shr( L_tmp, sub( 16, e ) ) );
1044 :
1045 : #ifdef FIX_1942_ASSERTION_LOWSHELF
1046 1744 : IF( EQ_16( lin_gain_hf_fx, 0 ) )
1047 : {
1048 0 : lin_gain_hf_fx = 1;
1049 0 : move16();
1050 : }
1051 : #endif
1052 : /* call low-pass iir shelf */
1053 1744 : calc_low_shelf_first_order_filter_fx( pCoeffB_fx, pCoeffA_fx, f0_fx, lin_gain_lf_fx, lin_gain_hf_fx );
1054 1744 : return IVAS_ERR_OK;
1055 : }
1056 :
1057 : /*-----------------------------------------------------------------------------------------*
1058 : * Function initialize_reverb_filters()
1059 : *
1060 : * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data)
1061 : *-----------------------------------------------------------------------------------------*/
1062 163 : static ivas_error initialize_reverb_filters_fx(
1063 : REVERB_HANDLE hReverb )
1064 : {
1065 : ivas_error error;
1066 :
1067 163 : error = IVAS_ERR_OK;
1068 :
1069 : /* init correlation and coloration filters */
1070 163 : IF( NE_32( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ), IVAS_ERR_OK ) )
1071 : {
1072 0 : return error;
1073 : }
1074 :
1075 163 : IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ), IVAS_ERR_OK ) )
1076 : {
1077 0 : return error;
1078 : }
1079 :
1080 163 : IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ), IVAS_ERR_OK ) )
1081 : {
1082 0 : return error;
1083 : }
1084 :
1085 163 : IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ), IVAS_ERR_OK ) )
1086 : {
1087 0 : return error;
1088 : }
1089 :
1090 163 : IF( NE_32( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ), IVAS_ERR_OK ) )
1091 : {
1092 0 : return error;
1093 : }
1094 :
1095 163 : return error;
1096 : }
1097 :
1098 : /*-----------------------------------------------------------------------------------------*
1099 : * Function set_t60_filter()
1100 : *
1101 : * Sets t60 number of taps and coefficients A and B
1102 : *-----------------------------------------------------------------------------------------*/
1103 :
1104 1744 : static ivas_error set_t60_filter(
1105 : REVERB_HANDLE hReverb,
1106 : const UWord16 branch,
1107 : const UWord16 nr_taps,
1108 : const Word16 coefA[], /*Q14*/
1109 : const Word16 coefB[] /*Q14*/ )
1110 : {
1111 1744 : IF( GE_32( branch, hReverb->nr_of_branches ) )
1112 : {
1113 0 : return IVAS_ERR_INTERNAL;
1114 : }
1115 :
1116 1744 : IF( GT_32( nr_taps, IVAS_REV_MAX_IIR_FILTER_LENGTH ) )
1117 : {
1118 0 : return IVAS_ERR_INTERNAL;
1119 : }
1120 :
1121 1744 : ivas_reverb_iir_filt_set( &( hReverb->t60[branch] ), nr_taps, coefA, coefB );
1122 :
1123 1744 : return IVAS_ERR_OK;
1124 : }
1125 :
1126 : /*-----------------------------------------------------------------------------------------*
1127 : * Function set_feedback_delay()
1128 : *
1129 : * Sets Delay of feedback branch in number of samples
1130 : *-----------------------------------------------------------------------------------------*/
1131 :
1132 1304 : static ivas_error set_feedback_delay_fx(
1133 : REVERB_HANDLE hReverb,
1134 : const UWord16 branch,
1135 : const Word16 fb_delay /*Q0*/ )
1136 : {
1137 1304 : IF( GE_32( branch, hReverb->nr_of_branches ) )
1138 : {
1139 0 : return IVAS_ERR_INTERNAL;
1140 : }
1141 :
1142 1304 : hReverb->delay_line[branch].Delay = fb_delay;
1143 1304 : move16();
1144 :
1145 1304 : return IVAS_ERR_OK;
1146 : }
1147 : /*-----------------------------------------------------------------------------------------*
1148 : * Function set_feedback_gain()
1149 : *
1150 : * Sets nr_of_branches feedback gain values in feedback matrix
1151 : *-----------------------------------------------------------------------------------------*/
1152 :
1153 1304 : static ivas_error set_feedback_gain_fx(
1154 : REVERB_HANDLE hReverb,
1155 : const UWord16 branch,
1156 : const Word32 *pGain /*Q31*/ )
1157 : {
1158 : UWord16 gain_idx;
1159 1304 : IF( GE_32( branch, hReverb->nr_of_branches ) )
1160 : {
1161 0 : return IVAS_ERR_INTERNAL;
1162 : }
1163 :
1164 11736 : FOR( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ )
1165 : {
1166 10432 : hReverb->gain_matrix_fx[branch][gain_idx] = pGain[gain_idx]; // Q31
1167 10432 : move32();
1168 : }
1169 :
1170 1304 : return IVAS_ERR_OK;
1171 : }
1172 : /*-----------------------------------------------------------------------------------------*
1173 : * Function set_correl_fft_filter()
1174 : *
1175 : * Sets correlation filter complex gains
1176 : *-----------------------------------------------------------------------------------------*/
1177 :
1178 436 : static ivas_error set_correl_fft_filter_fx(
1179 : REVERB_HANDLE hReverb,
1180 : const UWord16 channel,
1181 : rv_fftwf_type_complex_fx *pSpectrum )
1182 : {
1183 436 : IF( GT_32( channel, 1 ) )
1184 : {
1185 0 : return IVAS_ERR_INTERNAL;
1186 : }
1187 :
1188 436 : IF( EQ_32( channel, 0 ) )
1189 : {
1190 218 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_correl_0.fft_spectrum_fx, hReverb->fft_filter_correl_0.fft_size );
1191 : }
1192 : ELSE
1193 : {
1194 218 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_correl_1.fft_spectrum_fx, hReverb->fft_filter_correl_1.fft_size );
1195 : }
1196 :
1197 436 : return IVAS_ERR_OK;
1198 : }
1199 :
1200 :
1201 : /*-----------------------------------------------------------------------------------------*
1202 : * Function set_color_fft_filter()
1203 : *
1204 : * Sets coloration filter complex gains
1205 : *-----------------------------------------------------------------------------------------*/
1206 :
1207 436 : static ivas_error set_color_fft_filter_fx(
1208 : REVERB_HANDLE hReverb,
1209 : const UWord16 channel,
1210 : rv_fftwf_type_complex_fx *pSpectrum )
1211 : {
1212 436 : IF( GT_32( channel, 1 ) )
1213 : {
1214 0 : return IVAS_ERR_INTERNAL;
1215 : }
1216 :
1217 436 : IF( EQ_32( channel, 0 ) )
1218 : {
1219 218 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum_fx, hReverb->fft_filter_color_0.fft_size );
1220 : }
1221 : ELSE
1222 : {
1223 218 : ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum_fx, hReverb->fft_filter_color_1.fft_size );
1224 : }
1225 :
1226 436 : return IVAS_ERR_OK;
1227 : }
1228 :
1229 :
1230 : /*-----------------------------------------------------------------------------------------*
1231 : * Function set_mixer_level_fx()
1232 : *
1233 : * Sets Mixer level: to mix 2 output channels from 8 feedback branches
1234 : *-----------------------------------------------------------------------------------------*/
1235 :
1236 326 : static ivas_error set_mixer_level_fx(
1237 : REVERB_HANDLE hReverb,
1238 : const UWord16 channel,
1239 : const Word16 level[] /*Q0*/ )
1240 : {
1241 : UWord16 branch_idx;
1242 326 : IF( GE_32( channel, BINAURAL_CHANNELS ) )
1243 : {
1244 0 : return IVAS_ERR_INTERNAL;
1245 : }
1246 :
1247 2934 : FOR( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ )
1248 : {
1249 2608 : hReverb->mixer_fx[channel][branch_idx] = level[branch_idx]; /*Q0*/
1250 2608 : move16();
1251 : }
1252 :
1253 326 : return IVAS_ERR_OK;
1254 : }
1255 : /*-----------------------------------------------------------------------------------------*
1256 : * Function clear_buffers_fx()
1257 : *
1258 : * Clears buffers of delay lines and filters
1259 : *-----------------------------------------------------------------------------------------*/
1260 :
1261 163 : static void clear_buffers_fx(
1262 : REVERB_HANDLE hReverb )
1263 : {
1264 : Word16 branch_idx;
1265 : ivas_rev_iir_filter_t *iirFilter;
1266 : ivas_rev_delay_line_t *delay_line;
1267 :
1268 1467 : FOR( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
1269 : {
1270 1304 : delay_line = &( hReverb->delay_line[branch_idx] );
1271 1304 : set32_fx( delay_line->pBuffer_fx, 0, delay_line->MaxDelay );
1272 1304 : delay_line->BufferPos = 0;
1273 1304 : move16();
1274 :
1275 1304 : iirFilter = &( hReverb->t60[branch_idx] );
1276 1304 : set32_fx( iirFilter->pBuffer_fx, 0, iirFilter->MaxTaps );
1277 : }
1278 :
1279 163 : ivas_reverb_t2f_f2t_ClearHistory( &hReverb->fft_filter_ols );
1280 :
1281 163 : return;
1282 : }
1283 :
1284 : /*-----------------------------------------------------------------------------------------*
1285 : * Function set_fft_and_datablock_sizes_fx()
1286 : *
1287 : * Sets frame size and fft-filter related sizes
1288 : *-----------------------------------------------------------------------------------------*/
1289 :
1290 218 : static void set_fft_and_datablock_sizes_fx(
1291 : REVERB_HANDLE hReverb,
1292 : const Word16 subframe_len )
1293 : {
1294 218 : hReverb->full_block_size = subframe_len;
1295 218 : IF( EQ_16( subframe_len, 240 /*L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
1296 : {
1297 127 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K;
1298 127 : move16();
1299 127 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K;
1300 127 : move16();
1301 : }
1302 91 : ELSE IF( EQ_16( subframe_len, 160 /*L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
1303 : {
1304 30 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K;
1305 30 : move16();
1306 30 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K;
1307 30 : move16();
1308 : }
1309 61 : ELSE IF( EQ_16( subframe_len, 80 /*L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) )
1310 : {
1311 61 : hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K;
1312 61 : move16();
1313 61 : hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K;
1314 61 : move16();
1315 : }
1316 : ELSE
1317 : {
1318 0 : assert( 0 ); /* unsupported block size */
1319 : }
1320 :
1321 218 : hReverb->fft_subblock_size = (UWord16) idiv1616( subframe_len, hReverb->num_fft_subblocks );
1322 218 : move16();
1323 :
1324 218 : return;
1325 : }
1326 :
1327 : /*-----------------------------------------------------------------------------------------*
1328 : * Function set_reverb_acoustic_data_fx()
1329 : *
1330 : * Sets reverb acoustic data (room acoustics and HRTF), interpolating it to the filter grid
1331 : *-----------------------------------------------------------------------------------------*/
1332 :
1333 218 : static void set_reverb_acoustic_data_fx(
1334 : ivas_reverb_params_t *pParams,
1335 : IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics,
1336 : const Word16 nr_fc_input,
1337 : const Word16 nr_fc_fft_filter )
1338 : {
1339 : Word16 bin_idx;
1340 : Word32 ln_1e6_inverted_fx, delay_diff_fx, L_tmp;
1341 : Word32 exp_argument_fx, tmp;
1342 : Word16 pow_exp, exp_argument_e;
1343 :
1344 218 : Word32 *pFc_input_fx = pRoomAcoustics->pFc_input_fx;
1345 218 : Word32 *pAcoustic_rt60_fx = pRoomAcoustics->pAcoustic_rt60_fx;
1346 218 : Word32 *pAcoustic_dsr_fx = pRoomAcoustics->pAcoustic_dsr_fx;
1347 :
1348 218 : Word32 *pFc_fx = pParams->pFc_fx;
1349 218 : Word32 *pRt60_fx = pParams->pRt60_fx;
1350 218 : Word32 *pDsr_fx = pParams->pDsr_fx;
1351 :
1352 : /* interpolate input table data for T60 and DSR to the FFT filter grid */
1353 :
1354 218 : ivas_reverb_interp_on_freq_grid_fx( nr_fc_input, pFc_input_fx, pAcoustic_rt60_fx, nr_fc_fft_filter, pFc_fx, pRt60_fx ); // Q26
1355 218 : ivas_reverb_interp_on_freq_grid_fx( nr_fc_input, pFc_input_fx, pAcoustic_dsr_fx, nr_fc_fft_filter, pFc_fx, pDsr_fx ); // Q30
1356 :
1357 : ///* adjust DSR for the delay difference */
1358 :
1359 218 : delay_diff_fx = L_sub( pRoomAcoustics->inputPreDelay_fx, pRoomAcoustics->acousticPreDelay_fx ); // Q27
1360 :
1361 218 : ln_1e6_inverted_fx = 155440049; // Q31 /* 1.0f / logf( 1e06f ) */
1362 218 : move32();
1363 :
1364 48436 : FOR( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
1365 : {
1366 48218 : L_tmp = Mpy_32_32( pRt60_fx[bin_idx], ln_1e6_inverted_fx ); // Q26
1367 :
1368 48218 : exp_argument_fx = BASOP_Util_Divide3232_Scale_newton( delay_diff_fx, L_tmp, &exp_argument_e );
1369 48218 : exp_argument_fx = L_shr_sat( exp_argument_fx, sub( 6, exp_argument_e ) ); // Q26
1370 :
1371 : /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */
1372 48218 : IF( GT_32( exp_argument_fx, 1543503872 ) ) // 23 in Q26
1373 : {
1374 0 : exp_argument_fx = 1543503872;
1375 : }
1376 48218 : IF( LT_32( exp_argument_fx, -1543503872 ) ) // 23 in Q26
1377 : {
1378 0 : exp_argument_fx = -1543503872;
1379 : }
1380 :
1381 48218 : tmp = Mpy_32_32( 96817114, exp_argument_fx ); // Q21
1382 :
1383 48218 : L_tmp = BASOP_util_Pow2( tmp, 10, &pow_exp );
1384 48218 : L_tmp = Mpy_32_32( L_tmp, pDsr_fx[bin_idx] );
1385 48218 : L_tmp = L_shl_sat( L_tmp, add( 1, pow_exp ) ); // Q31
1386 :
1387 48218 : pDsr_fx[bin_idx] = L_tmp;
1388 48218 : move32();
1389 : }
1390 218 : return;
1391 : }
1392 :
1393 :
1394 : /*-----------------------------------------------------------------------------------------*
1395 : * Function setup_FDN_branches_fx()
1396 : *
1397 : * Sets up feedback delay network system
1398 : *-----------------------------------------------------------------------------------------*/
1399 :
1400 163 : static ivas_error setup_FDN_branches_fx(
1401 : REVERB_HANDLE hReverb,
1402 : ivas_reverb_params_t *pParams )
1403 : {
1404 : Word16 nr_coefs, branch_idx, channel_idx;
1405 : ivas_error error;
1406 : #ifndef FIX_1053_REVERB_RECONFIGURATION
1407 : Word16 *pCoef_a, *pCoef_b;
1408 : #endif
1409 163 : error = IVAS_ERR_OK;
1410 :
1411 : /* initialize feedback branches */
1412 1467 : FOR( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ )
1413 : {
1414 1304 : ivas_rev_delay_line_init( &( hReverb->delay_line[branch_idx] ), hReverb->loop_delay_buffer_fx[branch_idx], init_loop_delay[branch_idx], pParams->pLoop_delays[branch_idx] );
1415 1304 : ivas_reverb_iir_filt_init( &( hReverb->t60[branch_idx] ), IVAS_REV_MAX_IIR_FILTER_LENGTH );
1416 1304 : hReverb->mixer_fx[0][branch_idx] = 0;
1417 1304 : move16();
1418 1304 : hReverb->mixer_fx[1][branch_idx] = 0;
1419 1304 : move16();
1420 : }
1421 163 : clear_buffers_fx( hReverb );
1422 163 : nr_coefs = add( pParams->t60_filter_order, 1 );
1423 :
1424 163 : IF( LT_16( IVAS_REV_MAX_IIR_FILTER_LENGTH, nr_coefs ) )
1425 : {
1426 0 : return IVAS_ERR_INTERNAL;
1427 : }
1428 : ELSE
1429 : {
1430 1467 : FOR( branch_idx = 0; branch_idx < pParams->nr_loops; branch_idx++ )
1431 : {
1432 : #ifndef FIX_1053_REVERB_RECONFIGURATION
1433 : pCoef_b = &pParams->pT60_filter_coeff_fx[shl( i_mult( nr_coefs, branch_idx ), 1 )]; /*Q14*/
1434 : pCoef_a = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( nr_coefs, branch_idx ), 1 ), nr_coefs )]; /*Q14*/
1435 :
1436 : IF( NE_32( ( error = set_t60_filter( hReverb, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ), IVAS_ERR_OK ) )
1437 : {
1438 : return error;
1439 : }
1440 : #endif
1441 1304 : IF( NE_32( ( error = set_feedback_delay_fx( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ), IVAS_ERR_OK ) )
1442 : {
1443 0 : return error;
1444 : }
1445 1304 : IF( NE_32( ( error = set_feedback_gain_fx( hReverb, branch_idx, &( pParams->pLoop_feedback_matrix_fx[i_mult( branch_idx, pParams->nr_loops )] ) ) ), IVAS_ERR_OK ) )
1446 : {
1447 0 : return error;
1448 : }
1449 : }
1450 : }
1451 :
1452 489 : FOR( channel_idx = 0; channel_idx < pParams->nr_outputs; channel_idx++ )
1453 : {
1454 326 : IF( NE_32( ( error = set_mixer_level_fx( hReverb, channel_idx, &( pParams->pLoop_extract_matrix_fx[i_mult( channel_idx, pParams->nr_loops )] ) ) ), IVAS_ERR_OK ) )
1455 : {
1456 0 : return error;
1457 : }
1458 : }
1459 :
1460 163 : return error;
1461 : }
1462 :
1463 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1464 : /*-------------------------------------------------------------------------
1465 : * ivas_reverb_open_fx()
1466 : *
1467 : * Allocate and initialize FDN reverberation handle
1468 : *------------------------------------------------------------------------*/
1469 : #else
1470 : /*-------------------------------------------------------------------------
1471 : * ivas_reverb_open_fx()
1472 : *
1473 : * Allocate and initialize Crend reverberation handle
1474 : *------------------------------------------------------------------------*/
1475 : #endif
1476 218 : ivas_error ivas_reverb_open_fx(
1477 : REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */
1478 : const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i : HRTF statistics handle */
1479 : RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */
1480 : const Word32 output_Fs )
1481 : {
1482 : ivas_error error;
1483 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1484 218 : REVERB_HANDLE pState = *hReverb;
1485 : UWord16 nr_coefs, branch_idx;
1486 : Word16 *pCoef_a, *pCoef_b;
1487 : #else
1488 : REVERB_HANDLE pState = NULL;
1489 : #endif
1490 : Word16 bin_idx, subframe_len, output_frame, predelay_bf_len, loop_idx, i;
1491 : ivas_reverb_params_t params;
1492 : Word32 pColor_target_l_fx[RV_LENGTH_NR_FC];
1493 : Word32 pColor_target_r_fx[RV_LENGTH_NR_FC];
1494 : Word32 pTime_window_fx[RV_FILTER_MAX_FFT_SIZE];
1495 : Word32 freq_step_fx;
1496 : Word16 fft_hist_size, transition_start, transition_length;
1497 : Word16 nr_fc_input, nr_fc_fft_filter;
1498 : rv_fftwf_type_complex_fx pFft_wf_filter_ch0_fx[RV_LENGTH_NR_FC];
1499 : rv_fftwf_type_complex_fx pFft_wf_filter_ch1_fx[RV_LENGTH_NR_FC];
1500 :
1501 218 : error = IVAS_ERR_OK;
1502 218 : output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) );
1503 218 : subframe_len = shr( output_frame, 2 ); /*output_frame / MAX_PARAM_SPATIAL_SUBFRAMES*/
1504 218 : predelay_bf_len = output_frame;
1505 218 : move16();
1506 218 : nr_fc_input = hRenderConfig->roomAcoustics.nBands;
1507 :
1508 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1509 218 : IF( *hReverb == NULL )
1510 : {
1511 163 : IF( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL )
1512 : {
1513 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
1514 : }
1515 : }
1516 : #else
1517 : /* Allocate main reverb. handle */
1518 : IF( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL )
1519 : {
1520 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " );
1521 : }
1522 : #endif
1523 218 : IF( NE_32( ( error = set_base_config_fx( ¶ms, output_Fs ) ), IVAS_ERR_OK ) )
1524 : {
1525 0 : return error;
1526 : }
1527 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1528 218 : IF( *hReverb == NULL )
1529 : {
1530 : /* Allocate memory for feedback delay lines */
1531 1467 : FOR( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
1532 : {
1533 1304 : IF( ( pState->loop_delay_buffer_fx[loop_idx] = (Word32 *) malloc( params.pLoop_delays[loop_idx] * sizeof( Word32 ) ) ) == NULL )
1534 : {
1535 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FDN Reverberator" );
1536 : }
1537 : }
1538 :
1539 : /* Allocate memory for the pre-delay line */
1540 163 : IF( ( pState->pPredelay_buffer_fx = (Word32 *) malloc( output_frame * sizeof( Word32 ) ) ) == NULL )
1541 : {
1542 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" );
1543 : }
1544 : }
1545 : #else
1546 : /* Allocate memory for feedback delay lines */
1547 : FOR( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
1548 : {
1549 : IF( ( pState->loop_delay_buffer_fx[loop_idx] = (Word32 *) malloc( params.pLoop_delays[loop_idx] * sizeof( Word32 ) ) ) == NULL )
1550 : {
1551 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" );
1552 : }
1553 : }
1554 :
1555 : /* Allocate memory for the pre-delay delay line */
1556 : IF( ( pState->pPredelay_buffer_fx = (Word32 *) malloc( output_frame * sizeof( Word32 ) ) ) == NULL )
1557 : {
1558 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" );
1559 : }
1560 : #endif
1561 218 : pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES;
1562 218 : move16();
1563 218 : set_fft_and_datablock_sizes_fx( pState, subframe_len );
1564 :
1565 218 : nr_fc_fft_filter = add( extract_l( L_shr( pState->fft_size, 1 ) ), 1 );
1566 :
1567 : /* === 'Control logic': compute the reverb processing parameters from the === */
1568 : /* === room, source and listener acoustic information provided in the reverb config === */
1569 : /* Setting up shared temporary buffers for fc, RT60, DSR, etc. */
1570 : #ifndef FIX_1053_REVERB_RECONFIGURATION
1571 : params.pHrtf_avg_pwr_response_l_fx = &pFft_wf_filter_ch0_fx[0][0];
1572 : params.pHrtf_avg_pwr_response_r_fx = params.pHrtf_avg_pwr_response_l_fx + nr_fc_fft_filter;
1573 : #endif
1574 218 : params.pRt60_fx = &pFft_wf_filter_ch1_fx[0][0];
1575 218 : params.pDsr_fx = params.pRt60_fx + nr_fc_fft_filter;
1576 218 : params.pFc_fx = &pState->fft_filter_color_0.fft_spectrum_fx[0];
1577 : #ifndef FIX_1053_REVERB_RECONFIGURATION
1578 : params.pHrtf_inter_aural_coherence_fx = &pState->fft_filter_color_1.fft_spectrum_fx[0];
1579 : #endif
1580 218 : set32_fx( pState->fft_filter_color_1.fft_spectrum_fx, 0, RV_FILTER_MAX_FFT_SIZE );
1581 : /* Note: these temp buffers can only be used before the final step of the FFT filter design : */
1582 : /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */
1583 :
1584 : /* set the uniform frequency grid for FFT filtering */
1585 218 : freq_step_fx = L_mult0( extract_l( L_shr( output_Fs, 2 ) ), div_s( 1, ( nr_fc_fft_filter - 1 ) ) ); /*Q14:0.5f * output_Fs / ( nr_fc_fft_filter - 1 )*/
1586 48436 : FOR( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ )
1587 : {
1588 48218 : params.pFc_fx[bin_idx] = W_extract_l( W_mult0_32_32( freq_step_fx, bin_idx ) ); /*Q16*/
1589 : }
1590 :
1591 218 : test();
1592 :
1593 : /* set up reverb acoustic data on the basis of HRTF data and renderer config */
1594 218 : Scale_sig32( params.pFc_fx, nr_fc_fft_filter, 2 );
1595 :
1596 218 : set_reverb_acoustic_data_fx( ¶ms, &hRenderConfig->roomAcoustics, nr_fc_input, nr_fc_fft_filter );
1597 :
1598 218 : params.pHrtf_avg_pwr_response_l_const_fx = hHrtfStatistics->average_energy_l;
1599 218 : params.pHrtf_avg_pwr_response_r_const_fx = hHrtfStatistics->average_energy_r;
1600 218 : params.pHrtf_inter_aural_coherence_const_fx = hHrtfStatistics->inter_aural_coherence;
1601 :
1602 :
1603 : /* set reverb acoustic configuration based on renderer config */
1604 : #ifndef FIX_587_DEFAULT_REVERB
1605 : pState->pConfig.roomAcoustics.override = hRenderConfig->roomAcoustics.override;
1606 : move16();
1607 : #endif
1608 218 : pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands;
1609 218 : move16();
1610 :
1611 218 : IF( EQ_16( hRenderConfig->roomAcoustics.use_er, 1 ) )
1612 : {
1613 7 : pState->pConfig.roomAcoustics.use_er = hRenderConfig->roomAcoustics.use_er;
1614 7 : move16();
1615 7 : pState->pConfig.roomAcoustics.lowComplexity = hRenderConfig->roomAcoustics.lowComplexity;
1616 7 : move32();
1617 : }
1618 :
1619 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1620 218 : IF( *hReverb == NULL )
1621 : {
1622 163 : pState->dmx_gain_fx = calc_dmx_gain_fx();
1623 : }
1624 : #else
1625 : /* set up input downmix */
1626 : pState->dmx_gain_fx = calc_dmx_gain_fx();
1627 : #endif
1628 :
1629 : /* set up predelay - must be after set_base_config() and before compute_t60_coeffs() */
1630 218 : calc_predelay_fx( ¶ms, hRenderConfig->roomAcoustics.acousticPreDelay_fx, output_Fs );
1631 :
1632 : /* set up jot reverb 60 filters - must be set up after set_reverb_acoustic_data() */
1633 :
1634 218 : IF( NE_32( ( error = compute_t60_coeffs_fx( ¶ms, nr_fc_fft_filter, output_Fs ) ), IVAS_ERR_OK ) )
1635 : {
1636 0 : return error;
1637 : }
1638 : /* Compute target levels (gains) for the coloration filters */
1639 218 : Word32 *pHrtf_avg_pwr_response_l_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 * ) );
1640 218 : Word32 *pHrtf_avg_pwr_response_r_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 * ) );
1641 218 : Word16 lenT60_filter_coeff = add( params.t60_filter_order, 1 );
1642 218 : lenT60_filter_coeff = add( i_mult( shl( lenT60_filter_coeff, 1 ), sub( params.nr_loops, 1 ) ), add( lenT60_filter_coeff, 2 ) );
1643 218 : Word32 *pT60_filter_coeff = (Word32 *) malloc( ( lenT60_filter_coeff ) * sizeof( Word32 * ) );
1644 :
1645 :
1646 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1647 : {
1648 48218 : pHrtf_avg_pwr_response_l_const[i] = params.pHrtf_avg_pwr_response_l_const_fx[i]; /*Q28*/
1649 48218 : move32();
1650 48218 : pHrtf_avg_pwr_response_r_const[i] = params.pHrtf_avg_pwr_response_r_const_fx[i]; /*Q23+5*/
1651 48218 : move32();
1652 : }
1653 7194 : FOR( i = 0; i < lenT60_filter_coeff; i++ )
1654 : {
1655 6976 : pT60_filter_coeff[i] = L_shl_sat( params.pT60_filter_coeff_fx[i], 17 );
1656 6976 : move32();
1657 : }
1658 218 : ivas_reverb_calc_color_levels_fx( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc_fx, params.pDsr_fx, pHrtf_avg_pwr_response_l_const, pHrtf_avg_pwr_response_r_const,
1659 : params.pLoop_delays, pT60_filter_coeff, pColor_target_l_fx, pColor_target_r_fx );
1660 :
1661 218 : free( pHrtf_avg_pwr_response_l_const );
1662 218 : free( pHrtf_avg_pwr_response_r_const );
1663 218 : free( pT60_filter_coeff );
1664 :
1665 : /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */
1666 218 : fft_hist_size = sub( pState->fft_size, pState->fft_subblock_size );
1667 :
1668 218 : transition_start = round_fx( L_mult0( FFT_FILTER_WND_FLAT_REGION_FX, fft_hist_size ) );
1669 218 : transition_length = round_fx( L_mult0( FFT_FILTER_WND_TRANS_REGION_FX, fft_hist_size ) );
1670 :
1671 : /* Compute the window used for FFT filters */
1672 218 : ivas_reverb_define_window_fft_fx( pTime_window_fx, transition_start, transition_length, nr_fc_fft_filter );
1673 :
1674 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1675 : /* === Copy parameters from ivas_reverb_params_t into DSP blocks === */
1676 : /* === to be used for subsequent audio signal processing === */
1677 218 : if ( *hReverb == NULL )
1678 : {
1679 163 : pState->do_corr_filter = params.do_corr_filter;
1680 163 : move16();
1681 :
1682 : /* clear & init jot reverb fft filters */
1683 163 : IF( NE_32( ( error = initialize_reverb_filters_fx( pState ) ), IVAS_ERR_OK ) )
1684 : {
1685 0 : return error;
1686 : }
1687 : }
1688 : #else
1689 : /* === Now, copy parameters from ivas_reverb_params_t into DSP blocks === */
1690 : /* === to be used for subsequent audio signal processing === */
1691 :
1692 : pState->do_corr_filter = params.do_corr_filter;
1693 : move16();
1694 :
1695 : /* clear & init jot reverb fft filters */
1696 : IF( NE_32( ( error = initialize_reverb_filters_fx( pState ) ), IVAS_ERR_OK ) )
1697 : {
1698 : return error;
1699 : }
1700 : #endif
1701 :
1702 218 : Word16 q_pFft_wf_filter_ch0_fx = 23, q_pFft_wf_filter_ch1_fx = 23;
1703 218 : move16();
1704 218 : move16();
1705 :
1706 :
1707 218 : IF( pState->do_corr_filter )
1708 : {
1709 : /* Computing correlation filters on the basis of target IA coherence */
1710 96218 : FOR( i = 0; i < shl( sub( nr_fc_fft_filter, 1 ), 1 ); i++ )
1711 : {
1712 96000 : pTime_window_fx[i] = L_shr( pTime_window_fx[i], 1 ); /*Scaling signal down to 30*/
1713 96000 : move32();
1714 : }
1715 :
1716 218 : Word32 *pHrtf_inter_aural_coherence_const = (Word32 *) malloc( nr_fc_fft_filter * sizeof( Word32 ) );
1717 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1718 : {
1719 48218 : pHrtf_inter_aural_coherence_const[i] = L_shl( params.pHrtf_inter_aural_coherence_const_fx[i], 4 ); /*Scaling up to Q30*/
1720 48218 : move32();
1721 : }
1722 218 : ivas_reverb_calc_correl_filters_fx( pHrtf_inter_aural_coherence_const, pTime_window_fx, pState->fft_size, pFft_wf_filter_ch0_fx, pFft_wf_filter_ch1_fx, &q_pFft_wf_filter_ch0_fx, &q_pFft_wf_filter_ch1_fx );
1723 :
1724 218 : free( pHrtf_inter_aural_coherence_const );
1725 :
1726 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1727 : {
1728 48218 : pFft_wf_filter_ch0_fx[i][0] = L_shl( pFft_wf_filter_ch0_fx[i][0], sub( 31, q_pFft_wf_filter_ch0_fx ) ); // Scale to Q31
1729 48218 : move32();
1730 48218 : pFft_wf_filter_ch0_fx[i][1] = L_shl( pFft_wf_filter_ch0_fx[i][1], sub( 31, q_pFft_wf_filter_ch0_fx ) ); // Scale to Q31
1731 48218 : move32();
1732 : }
1733 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1734 : {
1735 48218 : pFft_wf_filter_ch1_fx[i][0] = L_shl( pFft_wf_filter_ch1_fx[i][0], sub( 31, q_pFft_wf_filter_ch1_fx ) ); // Scale to Q31
1736 48218 : move32();
1737 48218 : pFft_wf_filter_ch1_fx[i][1] = L_shl( pFft_wf_filter_ch1_fx[i][1], sub( 31, q_pFft_wf_filter_ch1_fx ) ); // Scale to Q31
1738 48218 : move32();
1739 : }
1740 : /* Copying the computed FFT correlation filters to the fft_filter components */
1741 218 : IF( NE_32( ( error = set_correl_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ), IVAS_ERR_OK ) )
1742 : {
1743 0 : return error;
1744 : }
1745 :
1746 218 : IF( NE_32( ( error = set_correl_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ), IVAS_ERR_OK ) )
1747 : {
1748 0 : return error;
1749 : }
1750 : }
1751 :
1752 : /* Computing coloration filters on the basis of target responses */
1753 :
1754 218 : ivas_reverb_calc_color_filters_fx( pColor_target_l_fx, pColor_target_r_fx, pTime_window_fx, pState->fft_size, pFft_wf_filter_ch0_fx, pFft_wf_filter_ch1_fx, &q_pFft_wf_filter_ch0_fx, &q_pFft_wf_filter_ch1_fx );
1755 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1756 : {
1757 48218 : pFft_wf_filter_ch0_fx[i][0] = L_shl( pFft_wf_filter_ch0_fx[i][0], sub( 31, q_pFft_wf_filter_ch0_fx ) );
1758 48218 : move32();
1759 48218 : pFft_wf_filter_ch0_fx[i][1] = L_shl( pFft_wf_filter_ch0_fx[i][1], sub( 31, q_pFft_wf_filter_ch0_fx ) );
1760 48218 : move32();
1761 : }
1762 48436 : FOR( i = 0; i < nr_fc_fft_filter; i++ )
1763 : {
1764 48218 : pFft_wf_filter_ch1_fx[i][0] = L_shl( pFft_wf_filter_ch1_fx[i][0], sub( 31, q_pFft_wf_filter_ch1_fx ) );
1765 48218 : move32();
1766 48218 : pFft_wf_filter_ch1_fx[i][1] = L_shl( pFft_wf_filter_ch1_fx[i][1], sub( 31, q_pFft_wf_filter_ch1_fx ) );
1767 48218 : move32();
1768 : }
1769 : #ifndef FIX_1053_REVERB_RECONFIGURATION
1770 : Scale_sig32( params.pHrtf_inter_aural_coherence_fx, nr_fc_fft_filter, 4 ); /*Scaling ( *hReverb )->fft_filter_color_0.fft_spectrum_fx to Q31*/
1771 : Scale_sig32( params.pFc_fx, nr_fc_fft_filter, 17 ); /*Scaling ( *hReverb )->fft_filter_color_1.fft_spectrum_fx to Q31*/
1772 : #endif
1773 :
1774 : /* Copying the computed FFT colorations filters to the fft_filter components */
1775 218 : IF( NE_32( ( error = set_color_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ), IVAS_ERR_OK ) )
1776 : {
1777 0 : return error;
1778 : }
1779 :
1780 218 : IF( NE_32( ( error = set_color_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ), IVAS_ERR_OK ) )
1781 : {
1782 0 : return error;
1783 : }
1784 :
1785 : #ifdef FIX_1053_REVERB_RECONFIGURATION
1786 218 : if ( *hReverb == NULL )
1787 : {
1788 : /* init predelay */
1789 163 : ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer_fx, params.pre_delay, predelay_bf_len );
1790 :
1791 : /* set up feedback delay network */
1792 163 : if ( ( error = setup_FDN_branches_fx( pState, ¶ms ) ) != IVAS_ERR_OK )
1793 : {
1794 0 : return error;
1795 : }
1796 : }
1797 : else
1798 : {
1799 55 : pState->predelay_line.Delay = params.pre_delay;
1800 : }
1801 :
1802 218 : nr_coefs = params.t60_filter_order + 1;
1803 :
1804 1962 : for ( branch_idx = 0; branch_idx < params.nr_loops; branch_idx++ )
1805 : {
1806 1744 : pCoef_a = ¶ms.pT60_filter_coeff_fx[2 * nr_coefs * branch_idx + nr_coefs];
1807 1744 : pCoef_b = ¶ms.pT60_filter_coeff_fx[2 * nr_coefs * branch_idx];
1808 :
1809 1744 : if ( ( error = set_t60_filter( pState, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ) != IVAS_ERR_OK )
1810 : {
1811 0 : return error;
1812 : }
1813 : }
1814 : #else
1815 : /* init predelay */
1816 : ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer_fx, params.pre_delay, predelay_bf_len );
1817 :
1818 : /* set up feedback delay network */
1819 : IF( NE_32( ( error = setup_FDN_branches_fx( pState, ¶ms ) ), IVAS_ERR_OK ) )
1820 : {
1821 : return error;
1822 : }
1823 : #endif
1824 218 : *hReverb = pState;
1825 :
1826 218 : return error;
1827 : }
1828 : /*-------------------------------------------------------------------------
1829 : * ivas_reverb_close()
1830 : *
1831 : * Deallocate Crend reverberation handle
1832 : *------------------------------------------------------------------------*/
1833 :
1834 4506 : void ivas_reverb_close(
1835 : REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle */
1836 : )
1837 : {
1838 : REVERB_HANDLE hReverb;
1839 : Word16 loop_idx;
1840 :
1841 4506 : hReverb = *hReverb_in;
1842 :
1843 4506 : test();
1844 4506 : IF( hReverb_in == NULL || *hReverb_in == NULL )
1845 : {
1846 4343 : return;
1847 : }
1848 :
1849 1467 : FOR( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ )
1850 : {
1851 1304 : IF( hReverb->loop_delay_buffer_fx[loop_idx] != NULL )
1852 : {
1853 1304 : free( hReverb->loop_delay_buffer_fx[loop_idx] );
1854 1304 : hReverb->loop_delay_buffer_fx[loop_idx] = NULL;
1855 : }
1856 : }
1857 :
1858 163 : free( hReverb->pPredelay_buffer_fx );
1859 163 : hReverb->pPredelay_buffer_fx = NULL;
1860 :
1861 163 : free( *hReverb_in );
1862 163 : *hReverb_in = NULL;
1863 :
1864 163 : return;
1865 : }
1866 : /*-----------------------------------------------------------------------------------------*
1867 : * Function post_fft_filter()
1868 : *
1869 : *
1870 : *-----------------------------------------------------------------------------------------*/
1871 :
1872 376823 : static void post_fft_filter_fx(
1873 : REVERB_HANDLE hReverb,
1874 : Word32 *input_L_fx,
1875 : Word32 *input_R_fx,
1876 : Word32 *buffer_L_fx,
1877 : Word32 *buffer_R_fx )
1878 : {
1879 :
1880 376823 : IF( hReverb->do_corr_filter )
1881 : {
1882 376823 : ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx );
1883 376823 : ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_0, buffer_L_fx );
1884 376823 : ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_1, buffer_R_fx );
1885 376823 : ivas_reverb_fft_filter_CrossMix_fx( buffer_L_fx, buffer_R_fx, hReverb->fft_filter_correl_0.fft_size );
1886 : }
1887 : ELSE
1888 : {
1889 0 : ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx );
1890 : }
1891 376823 : ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_color_0, buffer_L_fx );
1892 376823 : ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_color_1, buffer_R_fx );
1893 376823 : ivas_reverb_t2f_f2t_out_fx( &hReverb->fft_filter_ols, buffer_L_fx, buffer_R_fx, input_L_fx, input_R_fx );
1894 :
1895 376823 : return;
1896 : }
1897 : /*-----------------------------------------------------------------------------------------*
1898 : * Function reverb_block()
1899 : *
1900 : * Input a block (mono) and calculate the 2 output blocks.
1901 : *-----------------------------------------------------------------------------------------*/
1902 :
1903 376823 : static void reverb_block_fx(
1904 : REVERB_HANDLE hReverb,
1905 : Word32 *pInput_fx, /*Q11*/
1906 : Word32 *pOut0_fx,
1907 : Word32 *pOut1_fx )
1908 :
1909 : {
1910 376823 : UWord16 nr_branches = hReverb->nr_of_branches;
1911 376823 : UWord16 bsize = hReverb->full_block_size;
1912 376823 : UWord16 inner_bsize = INNER_BLK_SIZE;
1913 : UWord16 i, j, k, ns, branch_idx, blk_idx, start_sample_idx;
1914 : Word32 *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE];
1915 : Word32 pFeedback_input_fx[INNER_BLK_SIZE];
1916 : Word32 pTemp_fx[INNER_BLK_SIZE];
1917 : Word32 *ppOutput_fx[IVAS_REV_MAX_NR_BRANCHES];
1918 : Word32 Output_fx[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE];
1919 : Word16 shift;
1920 376823 : move16();
1921 376823 : move16();
1922 376823 : move16();
1923 :
1924 376823 : pFFT_buf[0] = &FFT_buf_1[0];
1925 376823 : pFFT_buf[1] = &FFT_buf_2[0];
1926 :
1927 3391407 : FOR( branch_idx = 0; branch_idx < nr_branches; branch_idx++ )
1928 : {
1929 3014584 : ppOutput_fx[branch_idx] = (Word32 *) Output_fx + i_mult( branch_idx, inner_bsize );
1930 : }
1931 :
1932 1493759 : FOR( k = 0; k < bsize; k += inner_bsize )
1933 : {
1934 1116936 : Word32 *pO0 = &pOut0_fx[k];
1935 1116936 : Word32 *pO1 = &pOut1_fx[k];
1936 90471816 : FOR( i = 0; i < inner_bsize; i++ )
1937 : {
1938 89354880 : pO0[i] = 0;
1939 89354880 : move16();
1940 89354880 : pO1[i] = 0;
1941 89354880 : move16();
1942 : }
1943 :
1944 : /* feedback network: */
1945 10052424 : FOR( i = 0; i < nr_branches; i++ )
1946 : {
1947 8935488 : Word32 *pOutput_i_fx = &ppOutput_fx[i][0];
1948 8935488 : Word16 mixer_0_i = hReverb->mixer_fx[0][i];
1949 8935488 : move16();
1950 8935488 : Word16 mixer_1_i = hReverb->mixer_fx[1][i];
1951 8935488 : move16();
1952 : /* output and feedback are same, get sample from delay line ... */
1953 8935488 : ivas_rev_delay_line_get_sample_blk_fx( &( hReverb->delay_line[i] ), inner_bsize, pTemp_fx );
1954 8935488 : ivas_reverb_iir_filt_2taps_feed_blk_fx( &( hReverb->t60[i] ), inner_bsize, pTemp_fx, ppOutput_fx[i] );
1955 723774528 : FOR( ns = 0; ns < inner_bsize; ns++ )
1956 : {
1957 714839040 : pO0[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_0_i ), pO0[ns] ); /* mixer ch 0 */
1958 714839040 : move32();
1959 714839040 : pO1[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_1_i ), pO1[ns] ); /* mixer ch 1 */
1960 714839040 : move32();
1961 : }
1962 : }
1963 :
1964 10052424 : FOR( i = 0; i < nr_branches; i++ )
1965 : {
1966 8935488 : Word32 *pIn = &pInput_fx[k];
1967 :
1968 723774528 : FOR( ns = 0; ns < inner_bsize; ns++ )
1969 : {
1970 714839040 : pFeedback_input_fx[ns] = L_shr( pIn[ns], 3 ); // to make the Qfactor similar to pOutput
1971 714839040 : move32();
1972 : }
1973 :
1974 80419392 : FOR( j = 0; j < nr_branches; j++ )
1975 : {
1976 71483904 : Word32 gain_matrix_j_i = hReverb->gain_matrix_fx[j][i]; // Q31
1977 71483904 : move32();
1978 71483904 : Word32 *pOutput = &ppOutput_fx[j][0];
1979 5790196224 : FOR( ns = 0; ns < inner_bsize; ns++ )
1980 : {
1981 5718712320 : pFeedback_input_fx[ns] = ( L_add_sat( Mpy_32_32( gain_matrix_j_i, pOutput[ns] ), pFeedback_input_fx[ns] ) );
1982 5718712320 : move32();
1983 : }
1984 : }
1985 :
1986 8935488 : ivas_rev_delay_line_feed_sample_blk_fx( &( hReverb->delay_line[i] ), inner_bsize, pFeedback_input_fx );
1987 : }
1988 : }
1989 :
1990 376823 : shift = s_min( L_norm_arr( pOut0_fx, hReverb->fft_filter_ols.block_size ), L_norm_arr( pOut1_fx, hReverb->fft_filter_ols.block_size ) );
1991 :
1992 376823 : IF( LT_16( shift, hReverb->fft_filter_ols.prev_shift ) )
1993 : {
1994 1279 : scale_sig32( pOut0_fx, hReverb->fft_filter_ols.block_size, shift );
1995 1279 : scale_sig32( pOut1_fx, hReverb->fft_filter_ols.block_size, shift );
1996 1279 : scale_sig32( hReverb->fft_filter_ols.fft_history_L_fx, hReverb->fft_filter_ols.hist_size, sub( shift, hReverb->fft_filter_ols.prev_shift ) );
1997 1279 : scale_sig32( hReverb->fft_filter_ols.fft_history_R_fx, hReverb->fft_filter_ols.hist_size, sub( shift, hReverb->fft_filter_ols.prev_shift ) );
1998 :
1999 1279 : hReverb->fft_filter_ols.prev_shift = shift;
2000 1279 : move16();
2001 : }
2002 : ELSE
2003 : {
2004 375544 : scale_sig32( pOut0_fx, hReverb->fft_filter_ols.block_size, hReverb->fft_filter_ols.prev_shift );
2005 375544 : scale_sig32( pOut1_fx, hReverb->fft_filter_ols.block_size, hReverb->fft_filter_ols.prev_shift );
2006 :
2007 375544 : shift = hReverb->fft_filter_ols.prev_shift;
2008 375544 : move16();
2009 : }
2010 :
2011 : Word16 r_shift;
2012 376823 : r_shift = add( find_guarded_bits_fx( hReverb->fft_filter_ols.fft_size ), 1 );
2013 : // Applying guard bits for the DoRTFT inside the post_fft_filter function
2014 89731703 : FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ )
2015 : {
2016 89354880 : pOut0_fx[k] = (Word32) L_shr( pOut0_fx[k], ( r_shift ) );
2017 89354880 : move32();
2018 89354880 : pOut1_fx[k] = (Word32) L_shr( pOut1_fx[k], ( r_shift ) );
2019 89354880 : move32();
2020 : }
2021 : /* Applying FFT filter to each sub-frame */
2022 753646 : FOR( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ )
2023 : {
2024 376823 : start_sample_idx = imult1616( blk_idx, hReverb->fft_subblock_size );
2025 376823 : post_fft_filter_fx( hReverb, pOut0_fx + start_sample_idx, pOut1_fx + start_sample_idx, pFFT_buf[0], pFFT_buf[1] );
2026 : }
2027 :
2028 89731703 : FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ )
2029 : {
2030 89354880 : pOut0_fx[k] = (Word32) L_shl( pOut0_fx[k], sub( 1, shift ) );
2031 89354880 : move32();
2032 89354880 : pOut1_fx[k] = (Word32) L_shl( pOut1_fx[k], sub( 1, shift ) );
2033 89354880 : move32();
2034 : }
2035 :
2036 376823 : return;
2037 : }
2038 : /*-----------------------------------------------------------------------------------------*
2039 : * Function downmix_input_block()
2040 : *
2041 : * Downmix input to mono, taking also DSR gain into account
2042 : *-----------------------------------------------------------------------------------------*/
2043 :
2044 376823 : static ivas_error downmix_input_block_fx(
2045 : const REVERB_HANDLE hReverb,
2046 : Word32 *pcm_in[], /* i Q11 : the input PCM audio */
2047 : const AUDIO_CONFIG input_audio_config,
2048 : Word32 *pPcm_out, /* o Q11 : the output PCM audio */
2049 : const Word16 input_offset )
2050 : {
2051 : Word16 i, s, nchan_transport;
2052 376823 : Word32 dmx_gain_fx = hReverb->dmx_gain_fx;
2053 376823 : move32();
2054 376823 : SWITCH( input_audio_config )
2055 : {
2056 317303 : case IVAS_AUDIO_CONFIG_STEREO:
2057 : case IVAS_AUDIO_CONFIG_5_1:
2058 : case IVAS_AUDIO_CONFIG_7_1:
2059 : case IVAS_AUDIO_CONFIG_5_1_2:
2060 : case IVAS_AUDIO_CONFIG_5_1_4:
2061 : case IVAS_AUDIO_CONFIG_7_1_4:
2062 : case IVAS_AUDIO_CONFIG_ISM1:
2063 : case IVAS_AUDIO_CONFIG_ISM2:
2064 : case IVAS_AUDIO_CONFIG_ISM3:
2065 : case IVAS_AUDIO_CONFIG_ISM4:
2066 : {
2067 317303 : nchan_transport = audioCfg2channels( input_audio_config );
2068 75515383 : FOR( s = 0; s < hReverb->full_block_size; s++ )
2069 : {
2070 75198080 : Word32 temp = pcm_in[0][add( input_offset, s )];
2071 75198080 : move32();
2072 203219840 : FOR( i = 1; i < nchan_transport; i++ )
2073 : {
2074 128021760 : temp = L_add( temp, pcm_in[i][add( input_offset, s )] );
2075 : }
2076 75198080 : pPcm_out[s] = W_extract_h( W_shl( W_mult0_32_32( dmx_gain_fx, temp ), 9 ) ); // ( Q23 + Q11 + Q9 ) - 32 = Q11
2077 75198080 : move32();
2078 : }
2079 317303 : BREAK;
2080 : }
2081 59520 : case IVAS_AUDIO_CONFIG_MONO: /* ~'ZOA_1' */
2082 : case IVAS_AUDIO_CONFIG_FOA:
2083 : case IVAS_AUDIO_CONFIG_HOA2:
2084 : case IVAS_AUDIO_CONFIG_HOA3:
2085 : {
2086 14216320 : FOR( s = 0; s < hReverb->full_block_size; s++ )
2087 : {
2088 14156800 : pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( pcm_in[0][input_offset + s], 8 ) ); //(Q23 + Q11 + Q8) - 31 = Q11
2089 14156800 : move32();
2090 : }
2091 59520 : BREAK;
2092 : }
2093 0 : default:
2094 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" );
2095 : }
2096 :
2097 376823 : return IVAS_ERR_OK;
2098 : }
2099 : /*-----------------------------------------------------------------------------------------*
2100 : * Function predelay_block()
2101 : *
2102 : * Perform a predelay
2103 : *-----------------------------------------------------------------------------------------*/
2104 :
2105 376823 : static void predelay_block_fx(
2106 : const REVERB_HANDLE hReverb,
2107 : Word32 *pInput, /*Q11*/
2108 : Word32 *pOutput /*Q11*/ )
2109 : {
2110 : UWord16 i, idx, n_samples, blk_size;
2111 376823 : UWord16 max_blk_size = (UWord16) hReverb->predelay_line.Delay;
2112 376823 : IF( LT_32( max_blk_size, 2 ) )
2113 : {
2114 0 : IF( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */
2115 : {
2116 0 : FOR( i = 0; i < hReverb->full_block_size; i++ )
2117 : {
2118 0 : pOutput[i] = pInput[i]; // Q11
2119 0 : move32();
2120 : }
2121 : }
2122 : ELSE /* 1-sample length delay line: feed the data sample-by-sample */
2123 : {
2124 0 : FOR( i = 0; i < hReverb->full_block_size; i++ )
2125 : {
2126 0 : pOutput[i] = ivas_rev_delay_line_get_sample_fx( &( hReverb->predelay_line ) ); // Q11
2127 0 : move32();
2128 0 : ivas_rev_delay_line_feed_sample_fx( &( hReverb->predelay_line ), pInput[i] );
2129 : }
2130 : }
2131 : }
2132 : ELSE /* multiple-sample length delay line: use block processing */
2133 : {
2134 376823 : idx = 0;
2135 376823 : move16();
2136 376823 : n_samples = hReverb->full_block_size;
2137 2260938 : WHILE( n_samples > 0 )
2138 : {
2139 1884115 : blk_size = n_samples;
2140 1884115 : move16();
2141 1884115 : if ( GT_16( blk_size, max_blk_size ) )
2142 : {
2143 1507292 : blk_size = max_blk_size;
2144 1507292 : move16();
2145 : }
2146 1884115 : ivas_rev_delay_line_get_sample_blk_fx( &( hReverb->predelay_line ), blk_size, &pOutput[idx] );
2147 1884115 : ivas_rev_delay_line_feed_sample_blk_fx( &( hReverb->predelay_line ), blk_size, &pInput[idx] );
2148 1884115 : idx = (UWord16) UL_addNsD( idx, blk_size );
2149 1884115 : move16();
2150 1884115 : n_samples = (UWord16) UL_subNsD( n_samples, blk_size );
2151 1884115 : move16();
2152 : }
2153 : }
2154 :
2155 376823 : return;
2156 : }
2157 : /*-----------------------------------------------------------------------------------------*
2158 : * Function mix_output_block()
2159 : *
2160 : * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively
2161 : *-----------------------------------------------------------------------------------------*/
2162 :
2163 103880 : static void mix_output_block_fx(
2164 : const REVERB_HANDLE hReverb,
2165 : const Word32 *pInL,
2166 : const Word32 *pInR,
2167 : Word32 *pOutL,
2168 : Word32 *pOutR )
2169 : {
2170 : UWord16 i;
2171 :
2172 24100680 : FOR( i = 0; i < hReverb->full_block_size; i++ )
2173 : {
2174 23996800 : pOutL[i] = L_add( pInL[i], ( L_shr( pOutL[i], 2 ) ) );
2175 23996800 : move32();
2176 23996800 : pOutR[i] = L_add( pInR[i], ( L_shr( pOutR[i], 2 ) ) );
2177 23996800 : move32();
2178 : }
2179 :
2180 103880 : return;
2181 : }
2182 : /*-----------------------------------------------------------------------------------------*
2183 : * ivas_reverb_process()
2184 : *
2185 : * Process the input PCM audio into output PCM audio, applying reverb
2186 : *-----------------------------------------------------------------------------------------*/
2187 :
2188 376823 : ivas_error ivas_reverb_process_fx(
2189 : const REVERB_HANDLE hReverb, /* i : Reverberator handle */
2190 : const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */
2191 : const Word16 mix_signals, /* i : add reverb to output signal */
2192 : Word32 *pcm_in_fx[], /* i Q11 : the PCM audio to apply reverb on */
2193 : Word32 *pcm_out_fx[], /* o Q11 : the PCM audio with reverb applied */
2194 : const Word16 i_ts /* i : subframe index */
2195 : )
2196 : {
2197 : Word32 tmp0_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES];
2198 : ivas_error error;
2199 :
2200 376823 : IF( NE_32( ( error = downmix_input_block_fx( hReverb, pcm_in_fx, input_audio_config, tmp1_fx, i_ts * hReverb->full_block_size ) ), IVAS_ERR_OK ) )
2201 : {
2202 0 : return error;
2203 : }
2204 :
2205 376823 : predelay_block_fx( hReverb, tmp1_fx, tmp0_fx );
2206 :
2207 376823 : reverb_block_fx( hReverb, tmp0_fx, tmp1_fx, tmp2_fx );
2208 :
2209 376823 : IF( mix_signals )
2210 : {
2211 103880 : mix_output_block_fx( hReverb, tmp1_fx, tmp2_fx, &pcm_out_fx[0][i_ts * hReverb->full_block_size], &pcm_out_fx[1][i_ts * hReverb->full_block_size] );
2212 : }
2213 : ELSE
2214 : {
2215 272943 : MVR2R_WORD32( tmp1_fx, &pcm_out_fx[0][i_mult( i_ts, hReverb->full_block_size )], hReverb->full_block_size );
2216 272943 : MVR2R_WORD32( tmp2_fx, &pcm_out_fx[1][i_mult( i_ts, hReverb->full_block_size )], hReverb->full_block_size );
2217 : }
2218 :
2219 376823 : return IVAS_ERR_OK;
2220 : }
2221 :
2222 : /*-------------------------------------------------------------------------
2223 : * ivas_binaural_reverb_processSubFrame()
2224 : *
2225 : * Compute the reverberation - room effect
2226 : *------------------------------------------------------------------------*/
2227 :
2228 :
2229 : /*-------------------------------------------------------------------------
2230 : * ivas_binaural_reverb_processSubFrame_fx()
2231 : *
2232 : * Compute the reverberation - room effect
2233 : *------------------------------------------------------------------------*/
2234 :
2235 219612 : void ivas_binaural_reverb_processSubframe_fx(
2236 : REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */
2237 : const Word16 numInChannels, /* i : num inputs to be processed */
2238 : const Word16 numSlots, /* i : number of slots to be processed */
2239 : Word32 inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i (Q_in) : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */
2240 : Word32 inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i (Q_in) : input CLDFB data imag */
2241 : Word32 outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o (Q_in) : output CLDFB data real */
2242 : Word32 outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* o (Q_in) : output CLDFB data imag */
2243 : )
2244 : {
2245 : /* Declare the required variables */
2246 : Word16 idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr;
2247 : Word32 **tapRealPr_fx, **tapImagPr_fx;
2248 219612 : push_wmops( "binaural_reverb" );
2249 :
2250 : /* 1) Rotate the data in the loop buffer of the reverberator.
2251 : * Notice that the audio at the loop buffers is at time-inverted order
2252 : * for convolution purposes later on. */
2253 10225032 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
2254 : {
2255 : /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */
2256 10005420 : Copy32( hReverb->loopBufReal_fx[bin], hReverb->loopBufReal_fx[bin] + numSlots, hReverb->loopBufLength[bin] );
2257 10005420 : Copy32( hReverb->loopBufImag_fx[bin], hReverb->loopBufImag_fx[bin] + numSlots, hReverb->loopBufLength[bin] );
2258 :
2259 : /* Add the data from the end of the loop to the beginning, with an attenuation factor
2260 : * according to RT60. This procedure generates an IIR decaying response. The response
2261 : * is decorrelated later on. */
2262 10005420 : v_multc_fixed( hReverb->loopBufReal_fx[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor_fx[bin], hReverb->loopBufReal_fx[bin], numSlots );
2263 10005420 : v_multc_fixed( hReverb->loopBufImag_fx[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor_fx[bin], hReverb->loopBufImag_fx[bin], numSlots );
2264 : }
2265 :
2266 : /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */
2267 219612 : idx = hReverb->preDelayBufferIndex;
2268 1093585 : FOR( sample = 0; sample < numSlots; sample++ )
2269 : {
2270 873973 : invertSampleIndex = sub( sub( numSlots, sample ), 1 );
2271 :
2272 40657573 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
2273 : {
2274 : /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order.
2275 : * Also apply the spectral gains determined for the reverberation */
2276 39783600 : Word32 temp_1 = Mpy_32_32( hReverb->preDelayBufferReal_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); /*Q_in*/
2277 39783600 : Word32 temp_2 = Mpy_32_32( hReverb->preDelayBufferImag_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); /*Q_in*/
2278 39783600 : hReverb->loopBufReal_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufReal_fx[bin][invertSampleIndex], temp_1 ); /*Q_in*/
2279 39783600 : move32();
2280 39783600 : hReverb->loopBufImag_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufImag_fx[bin][invertSampleIndex], temp_2 ); /*Q_in*/
2281 39783600 : move32();
2282 39783600 : hReverb->preDelayBufferReal_fx[idx][bin] = 0;
2283 39783600 : move32();
2284 39783600 : hReverb->preDelayBufferImag_fx[idx][bin] = 0;
2285 39783600 : move32();
2286 : }
2287 :
2288 : /* Add every second input channel as is to the pre-delay buffer, and every second input channel with
2289 : * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */
2290 2643727 : FOR( ch = 0; ch < numInChannels; ch++ )
2291 : {
2292 1769754 : IF( s_and( ch, 1 ) )
2293 : {
2294 880053 : v_add_fixed_no_hdrm( hReverb->preDelayBufferReal_fx[idx], inReal[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins );
2295 880053 : v_add_fixed_no_hdrm( hReverb->preDelayBufferImag_fx[idx], inImag[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins );
2296 : }
2297 : ELSE
2298 : {
2299 889701 : v_sub_fixed_no_hdrm( hReverb->preDelayBufferReal_fx[idx], inImag[ch][sample], hReverb->preDelayBufferReal_fx[idx], hReverb->numBins );
2300 889701 : v_add_fixed_no_hdrm( hReverb->preDelayBufferImag_fx[idx], inReal[ch][sample], hReverb->preDelayBufferImag_fx[idx], hReverb->numBins );
2301 : }
2302 : }
2303 873973 : idx = add( idx, 1 ) % hReverb->preDelayBufferLength;
2304 873973 : move16();
2305 : }
2306 219612 : hReverb->preDelayBufferIndex = idx;
2307 219612 : move16();
2308 :
2309 : /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */
2310 10225032 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
2311 : {
2312 30016260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2313 : {
2314 : /* These tap pointers have been determined to point to the loop buffer at sparse locations */
2315 20010840 : tapRealPr_fx = hReverb->tapPointersReal_fx[bin][ch];
2316 20010840 : tapImagPr_fx = hReverb->tapPointersImag_fx[bin][ch];
2317 :
2318 20010840 : phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch];
2319 :
2320 : /* Flush output */
2321 20010840 : set32_fx( hReverb->outputBufferReal_fx[bin][ch], 0, numSlots );
2322 20010840 : set32_fx( hReverb->outputBufferImag_fx[bin][ch], 0, numSlots );
2323 :
2324 : /* Add from temporally decaying sparse tap locations the audio to the output. */
2325 489931624 : FOR( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ )
2326 : {
2327 469920784 : SWITCH( phaseShiftTypePr[tapIdx] )
2328 : {
2329 115301180 : case 0: /* 0 degrees phase */
2330 115301180 : v_add_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
2331 115301180 : v_add_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
2332 115301180 : BREAK;
2333 122777730 : case 1: /* 90 degrees phase */
2334 122777730 : v_sub_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
2335 122777730 : v_add_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
2336 122777730 : BREAK;
2337 118016723 : case 2: /* 180 degrees phase */
2338 118016723 : v_sub_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
2339 118016723 : v_sub_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
2340 118016723 : BREAK;
2341 113825151 : default: /* 270 degrees phase */
2342 113825151 : v_add_fixed_no_hdrm( hReverb->outputBufferReal_fx[bin][ch], tapImagPr_fx[tapIdx], hReverb->outputBufferReal_fx[bin][ch], numSlots );
2343 113825151 : v_sub_fixed_no_hdrm( hReverb->outputBufferImag_fx[bin][ch], tapRealPr_fx[tapIdx], hReverb->outputBufferImag_fx[bin][ch], numSlots );
2344 113825151 : BREAK;
2345 : }
2346 : }
2347 : }
2348 :
2349 : /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */
2350 10005420 : IF( LE_16( bin, hReverb->highestBinauralCoherenceBin ) )
2351 : {
2352 1487634 : IF( hReverb->useBinauralCoherence )
2353 : {
2354 7408805 : FOR( sample = 0; sample < numSlots; sample++ )
2355 : {
2356 : Word32 leftRe_fx, rightRe_fx, leftIm_fx, rightIm_fx;
2357 :
2358 5921171 : leftRe_fx = Madd_32_32( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ),
2359 5921171 : hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ); // Q_in
2360 5921171 : rightRe_fx = Madd_32_32( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ),
2361 5921171 : hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ); // Q_in
2362 5921171 : leftIm_fx = Madd_32_32( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ),
2363 5921171 : hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ); // Q_in
2364 5921171 : rightIm_fx = Madd_32_32( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ),
2365 5921171 : hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ); // Q_in
2366 :
2367 5921171 : hReverb->outputBufferReal_fx[bin][0][sample] = leftRe_fx; // Q_in
2368 5921171 : move32();
2369 5921171 : hReverb->outputBufferReal_fx[bin][1][sample] = rightRe_fx; // Q_in
2370 5921171 : move32();
2371 5921171 : hReverb->outputBufferImag_fx[bin][0][sample] = leftIm_fx; // Q_in
2372 5921171 : move32();
2373 5921171 : hReverb->outputBufferImag_fx[bin][1][sample] = rightIm_fx; // Q_in
2374 5921171 : move32();
2375 : }
2376 : }
2377 : }
2378 : }
2379 :
2380 : /* 4) Write data to output */
2381 658836 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2382 : {
2383 2187170 : FOR( sample = 0; sample < numSlots; sample++ )
2384 : {
2385 : /* Audio was in the temporally inverted order for convolution, re-invert audio to output */
2386 1747946 : invertSampleIndex = sub( sub( numSlots, sample ), 1 );
2387 :
2388 81315146 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
2389 : {
2390 79567200 : outReal[ch][sample][bin] = hReverb->outputBufferReal_fx[bin][ch][invertSampleIndex]; // Q_in
2391 79567200 : move32();
2392 79567200 : outImag[ch][sample][bin] = hReverb->outputBufferImag_fx[bin][ch][invertSampleIndex]; // Q_in
2393 79567200 : move32();
2394 : }
2395 27057506 : FOR( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
2396 : {
2397 25309560 : outReal[ch][sample][bin] = 0;
2398 25309560 : move32();
2399 25309560 : outImag[ch][sample][bin] = 0;
2400 25309560 : move32();
2401 : }
2402 : }
2403 : }
2404 :
2405 219612 : pop_wmops();
2406 219612 : return;
2407 : }
2408 :
2409 : /*-------------------------------------------------------------------------
2410 : * ivas_binaural_reverb_open()
2411 : *
2412 : * Allocate and initialize binaural room reverberator handle
2413 : *------------------------------------------------------------------------*/
2414 477 : static ivas_error ivas_binaural_reverb_open_fx(
2415 : REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */
2416 : const Word16 numBins, /* i : Q0 number of CLDFB bins */
2417 : const Word16 numCldfbSlotsPerFrame, /* i : Q0 number of CLDFB slots per frame */
2418 : const Word32 sampling_rate, /* i : Q0 sampling rate */
2419 : const Word32 *revTimes_fx, /* i : Q26 reverberation times T60 for each CLDFB bin in seconds */
2420 : const Word32 *revEnes_fx, /* i : Q31 spectrum for reverberated sound at each CLDFB bin */
2421 : const Word16 preDelay /* i : Q0 reverb pre-delay in CLDFB slots */
2422 : )
2423 : {
2424 : Word16 bin, chIdx, k, len, scale, tmp;
2425 : REVERB_STRUCT_HANDLE hReverb;
2426 :
2427 477 : IF( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL )
2428 : {
2429 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2430 : }
2431 :
2432 477 : hReverb = *hReverbPr;
2433 :
2434 477 : hReverb->useBinauralCoherence = 1;
2435 477 : move16();
2436 477 : hReverb->preDelayBufferLength = 1;
2437 477 : move16();
2438 477 : hReverb->preDelayBufferIndex = 0;
2439 477 : move16();
2440 :
2441 477 : hReverb->numBins = numBins;
2442 477 : move16();
2443 477 : hReverb->blockSize = numCldfbSlotsPerFrame;
2444 477 : move16();
2445 :
2446 10494 : FOR( k = 0; k < REVERB_PREDELAY_MAX + 1; k++ )
2447 : {
2448 10017 : set32_fx( hReverb->preDelayBufferReal_fx[k], 0, hReverb->numBins );
2449 10017 : set32_fx( hReverb->preDelayBufferImag_fx[k], 0, hReverb->numBins );
2450 : }
2451 :
2452 20747 : FOR( bin = 0; bin < hReverb->numBins; bin++ )
2453 : {
2454 : /* Loop Buffer */
2455 :
2456 20270 : tmp = BASOP_Util_Divide1616_Scale( 500, add( bin, 1 ), &scale );
2457 20270 : tmp = shr( tmp, sub( 15, scale ) );
2458 20270 : hReverb->loopBufLengthMax[bin] = add( tmp, sub( CLDFB_NO_CHANNELS_MAX, bin ) );
2459 : // hReverb->loopBufLengthMax[bin] = (Word16) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) );
2460 :
2461 20270 : len = add( hReverb->loopBufLengthMax[bin], hReverb->blockSize );
2462 :
2463 20270 : IF( ( hReverb->loopBufReal_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
2464 : {
2465 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2466 : }
2467 :
2468 20270 : if ( ( hReverb->loopBufImag_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
2469 : {
2470 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2471 : }
2472 20270 : set32_fx( hReverb->loopBufReal_fx[bin], 0, len );
2473 20270 : set32_fx( hReverb->loopBufImag_fx[bin], 0, len );
2474 :
2475 : /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long
2476 : * but not excessively long loops to generate reverberation. */
2477 : /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */
2478 : // hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 );
2479 20270 : Word32 L_tmp_BufLength = L_shl( L_shr( Mpy_32_32( revTimes_fx[bin], 1258291200 /*150.0 in Q23*/ ), 18 ), 18 );
2480 20270 : L_tmp_BufLength = L_add( Mpy_32_32( 1556925645 /*1.45 in Q30*/, L_tmp_BufLength ), ONE_IN_Q17 );
2481 20270 : hReverb->loopBufLength[bin] = (Word16) L_shr( L_tmp_BufLength, 17 ); /*Q0*/
2482 20270 : move16();
2483 20270 : hReverb->loopBufLength[bin] = s_min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] );
2484 :
2485 : /* Sparse Filter Tap Locations */
2486 60810 : FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
2487 : {
2488 40540 : len = hReverb->loopBufLength[bin];
2489 40540 : move16();
2490 :
2491 40540 : IF( ( hReverb->tapPhaseShiftType[bin][chIdx] = (Word16 *) malloc( len * sizeof( Word16 ) ) ) == NULL )
2492 : {
2493 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2494 : }
2495 40540 : set16_fx( hReverb->tapPhaseShiftType[bin][chIdx], 0, len );
2496 :
2497 40540 : IF( ( hReverb->tapPointersReal_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL )
2498 : {
2499 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2500 : }
2501 :
2502 40540 : IF( ( hReverb->tapPointersImag_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL )
2503 : {
2504 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2505 : }
2506 :
2507 40540 : len = hReverb->blockSize;
2508 40540 : move16();
2509 40540 : IF( ( hReverb->outputBufferReal_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
2510 : {
2511 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2512 : }
2513 :
2514 40540 : IF( ( hReverb->outputBufferImag_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL )
2515 : {
2516 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) );
2517 : }
2518 40540 : set32_fx( hReverb->outputBufferReal_fx[bin][chIdx], 0, len );
2519 40540 : set32_fx( hReverb->outputBufferImag_fx[bin][chIdx], 0, len );
2520 : }
2521 : }
2522 :
2523 477 : ivas_binaural_reverb_setReverbTimes_fx( hReverb, sampling_rate, revTimes_fx, revEnes_fx );
2524 :
2525 : /*free(revTimes_fx);
2526 : free(revEnes_fx);*/
2527 :
2528 477 : ivas_binaural_reverb_setPreDelay_fx( hReverb, preDelay );
2529 :
2530 477 : return IVAS_ERR_OK;
2531 : }
2532 :
2533 : /*-------------------------------------------------------------------------
2534 : * ivas_binaural_reverb_init()
2535 : *
2536 : * Allocate and initialize binaural room reverberator handle
2537 : * for CLDFB renderers
2538 : *------------------------------------------------------------------------*/
2539 477 : ivas_error ivas_binaural_reverb_init(
2540 : REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */
2541 : const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i : HRTF statistics handle */
2542 : const Word16 numBins, /* i : number of CLDFB bins */
2543 : const Word16 numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */
2544 : const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */
2545 : const Word32 sampling_rate, /* i : sampling rate */
2546 : const Word32 *defaultTimes, /* i : default reverberation times */
2547 : const Word32 *defaultEne /* i : default reverberation energies */
2548 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
2549 : ,
2550 : Word32 *earlyEne /* i/o: Early part energies to be modified */
2551 : #endif
2552 : )
2553 : {
2554 : ivas_error error;
2555 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
2556 : Word16 preDelay, bin;
2557 : Word32 revTimes[CLDFB_NO_CHANNELS_MAX];
2558 : Word32 revEne[CLDFB_NO_CHANNELS_MAX];
2559 : #else
2560 : const Word32 *revTimes;
2561 : const Word32 *revEne;
2562 : Word32 t60[CLDFB_NO_CHANNELS_MAX];
2563 : Word32 ene[CLDFB_NO_CHANNELS_MAX];
2564 : Word16 preDelay;
2565 : #endif
2566 : Word32 temp32;
2567 :
2568 477 : error = IVAS_ERR_OK;
2569 :
2570 : #ifdef FIX_587_DEFAULT_REVERB
2571 477 : IF( roomAcoustics != NULL )
2572 : #else
2573 : if ( ( roomAcoustics != NULL ) && roomAcoustics->override )
2574 : #endif
2575 : {
2576 : #ifndef FIX_1139_REV_COLORATION_SHORT_T60
2577 : revTimes = t60;
2578 : revEne = ene;
2579 : #endif
2580 :
2581 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
2582 245 : IF( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, revTimes, revEne ) ) != IVAS_ERR_OK )
2583 : #else
2584 : if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, t60, ene ) ) != IVAS_ERR_OK )
2585 : #endif
2586 : {
2587 0 : return error;
2588 : }
2589 :
2590 245 : temp32 = Mult_32_16( roomAcoustics->acousticPreDelay_fx, ( ( IVAS_48k / CLDFB_NO_CHANNELS_MAX ) >> 1 ) ); // Q11
2591 245 : preDelay = extract_l( L_shr( L_add( temp32, L_shl( 1, 10 ) ), 11 ) ); // Q0
2592 : }
2593 : ELSE
2594 : {
2595 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
2596 14152 : FOR( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
2597 : {
2598 13920 : revTimes[bin] = defaultTimes[bin];
2599 13920 : move32();
2600 13920 : revEne[bin] = defaultEne[bin];
2601 13920 : move32();
2602 : }
2603 : #else
2604 : revTimes = defaultTimes;
2605 : revEne = defaultEne;
2606 : #endif
2607 232 : preDelay = 10;
2608 : }
2609 :
2610 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
2611 29097 : FOR( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ )
2612 : {
2613 : /* Adjust the room effect parameters when the reverberation time is less than a threshold value, to avoid
2614 : spectral artefacts with the synthetic reverberator. */
2615 28620 : IF( LT_32( revTimes[bin], REV_TIME_THRESHOLD ) )
2616 : {
2617 : Word32 adjustedEarlyEne; /* Q28 to match earlyEne */
2618 : Word32 adjustedLateEne; /* Q31 to match revEne */
2619 : Word32 adjustedRevTime; /* Q26 to match revTime */
2620 : Word32 energyModifier; /* Q30 as range is [0,1] */
2621 : Word16 scale;
2622 :
2623 : /* Adjust reverberation times, higher towards a threshold */
2624 : /* Float code equivalent is:
2625 : * revTimeModifier = fmaxf( 0.0f, 1.0f - ( revTimes[bin] / REV_TIME_THRESHOLD ) );
2626 : * adjustedRevTime = ( 1.0f - revTimeModifier ) * revTimes[bin];
2627 : * adjustedRevTime += revTimeModifier * ( revTimes[bin] + REV_TIME_THRESHOLD ) * 0.5f; */
2628 6410 : adjustedRevTime = L_shl( revTimes[bin], 5 ); /* Store revTimes[bin] in Q31 for multiplication as it is under REV_TIME_THRESHOLD, i.e., smaller than 1 */
2629 : /* Do revTimes[bin]^2 in Q31, result in Q31, multiply with constant in Q29, shift result from Q29 to Q26 for addition and result. */
2630 6410 : adjustedRevTime = L_add( L_shr( Mpy_32_32( Mpy_32_32( adjustedRevTime, adjustedRevTime ), Q29_0_5_PER_REV_TIME_THRESHOLD ), 3 ), Q26_REV_TIME_THRESHOLD_TIMES_0_5 );
2631 :
2632 6410 : energyModifier = L_sub( adjustedRevTime, revTimes[bin] ); /* Q26 */
2633 6410 : IF( GT_32( energyModifier, 0 ) ) /* Very close to threshold, numeric accuracy is not sufficient and energyModifier would be negative. Correct way is to not adjust here. */
2634 : {
2635 6410 : energyModifier = BASOP_Util_Divide3232_Scale_newton( energyModifier, adjustedRevTime, &scale ); /* Inputs in Q26 */
2636 6410 : energyModifier = L_shl_sat( energyModifier, sub( scale, 1 ) ); /* Store in Q30 as range is [0,1] */
2637 :
2638 : /* Adjust early and late energies, by moving late energy to early energy */
2639 6410 : IF( earlyEne != NULL )
2640 : {
2641 5379 : adjustedEarlyEne = L_shr( Mpy_32_32( revEne[bin], energyModifier ), 2 ); /* Q31 * Q30 mult, shift from Q30 to Q28 */
2642 5379 : adjustedEarlyEne = L_add( adjustedEarlyEne, earlyEne[bin] ); /* Q28 */
2643 : }
2644 :
2645 6410 : adjustedLateEne = L_sub( ONE_IN_Q30, energyModifier ); /* Q30 */
2646 6410 : adjustedLateEne = L_shl_sat( Mpy_32_32( adjustedLateEne, revEne[bin] ), 1 ); /* Q30 * Q31 mult, shift back to Q31 */
2647 :
2648 : /* Store adjusted room effect parameters to be used in reverb processing */
2649 6410 : revTimes[bin] = adjustedRevTime;
2650 6410 : move32();
2651 6410 : revEne[bin] = adjustedLateEne;
2652 6410 : move32();
2653 6410 : IF( earlyEne != NULL )
2654 : {
2655 5379 : earlyEne[bin] = adjustedEarlyEne;
2656 5379 : move32();
2657 : }
2658 : }
2659 : }
2660 : }
2661 : #endif
2662 :
2663 477 : error = ivas_binaural_reverb_open_fx( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay );
2664 :
2665 477 : return error;
2666 : }
2667 : /*-------------------------------------------------------------------------
2668 : * ivas_binaural_reverb_close_fx()
2669 : *
2670 : * Close binaural room reverberator handle
2671 : *------------------------------------------------------------------------*/
2672 :
2673 477 : void ivas_binaural_reverb_close_fx(
2674 : REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */
2675 : )
2676 : {
2677 : Word16 bin, chIdx;
2678 :
2679 477 : test();
2680 477 : IF( hReverb == NULL || *hReverb == NULL )
2681 : {
2682 0 : return;
2683 : }
2684 :
2685 20747 : FOR( bin = 0; bin < ( *hReverb )->numBins; bin++ )
2686 : {
2687 60810 : FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
2688 : {
2689 40540 : free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] );
2690 40540 : free( ( *hReverb )->tapPointersReal_fx[bin][chIdx] );
2691 40540 : free( ( *hReverb )->tapPointersImag_fx[bin][chIdx] );
2692 40540 : free( ( *hReverb )->outputBufferReal_fx[bin][chIdx] );
2693 40540 : free( ( *hReverb )->outputBufferImag_fx[bin][chIdx] );
2694 : }
2695 20270 : free( ( *hReverb )->loopBufReal_fx[bin] );
2696 20270 : free( ( *hReverb )->loopBufImag_fx[bin] );
2697 : }
2698 :
2699 477 : free( ( *hReverb ) );
2700 477 : ( *hReverb ) = NULL;
2701 :
2702 477 : return;
2703 : }
|