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 <math.h>
36 : #include "prot_fx.h"
37 : #include "ivas_prot_rend_fx.h"
38 : #include "cnst.h"
39 : #include "ivas_cnst.h"
40 : #include "ivas_rom_rend.h"
41 : #include "ivas_rom_dec.h"
42 : #include "ivas_rom_com.h"
43 : #include "ivas_rom_binauralRenderer.h"
44 : #include "wmc_auto.h"
45 : #include "ivas_prot_fx.h"
46 : #include "debug.h"
47 :
48 :
49 : /*----------------------------------------------------------------------------------*
50 : * Local constants
51 : *----------------------------------------------------------------------------------*/
52 :
53 : #define NUM_TAPS_F0_6 ( Word16 )( 58 ) // (Word16) ceil( 0.6f * hBinRenConvModule->numTaps )
54 : #define NUM_TAPS_F0_5 ( Word16 )( 48 ) // (Word16) ceil( 0.5f * hBinRenConvModule->numTaps )
55 : #define NUM_TAPS_F0_4 ( Word16 )( 39 ) // (Word16) ceil( 0.4f * hBinRenConvModule->numTaps )
56 : #define NUM_TAPS_F0_3 ( Word16 )( 29 ) // (Word16) ceil( 0.3f * hBinRenConvModule->numTaps )
57 :
58 : #define REVERB_INPUT_DOWNMIX_CHANNELS ( 11 )
59 :
60 : #define NUM_TAPS_F0_6 ( Word16 )( 58 ) // (Word16) ceil( 0.6f * hBinRenConvModule->numTaps )
61 : #define NUM_TAPS_F0_5 ( Word16 )( 48 ) // (Word16) ceil( 0.5f * hBinRenConvModule->numTaps )
62 : #define NUM_TAPS_F0_4 ( Word16 )( 39 ) // (Word16) ceil( 0.4f * hBinRenConvModule->numTaps )
63 : #define NUM_TAPS_F0_3 ( Word16 )( 29 ) // (Word16) ceil( 0.3f * hBinRenConvModule->numTaps )
64 :
65 : /* Downmix table for sparse frequency domain reverberator*/
66 : static const Word32 dmxmtx_table_fx[BINAURAL_CHANNELS][REVERB_INPUT_DOWNMIX_CHANNELS] = {
67 : // Q31
68 : { 0x7fffffff, 0, 1518485623, 0x7fffffff, 0, 0x7fffffff, 0, 0x7fffffff, 0, 0x7fffffff, 0 },
69 : { 0, 0x7fffffff, 1518485623, 0, 0x7fffffff, 0, 0x7fffffff, 0, 0x7fffffff, 0, 0x7fffffff },
70 : };
71 :
72 :
73 : /*-------------------------------------------------------------------------
74 : * ivas_binRenderer_filterModule_fx()
75 : *
76 : *
77 : *-------------------------------------------------------------------------*/
78 :
79 161174 : static void ivas_binRenderer_filterModule_fx(
80 : Word32 out_Conv_CLDFB_real[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : real part of Binaural signals Q6 */
81 : Word32 out_Conv_CLDFB_imag[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : imag part of Binaural signals Q6 */
82 : Word32 CLDFB_real[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : real part of LS signals Q_curr*/
83 : Word32 CLDFB_imag[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : imag part of LS signals Q_curr*/
84 : const Word16 numTimeSlots, /* i : number of time slots to process */
85 : BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */
86 : const Word16 pos_idx, /* i : pose index */
87 : Word16 Q_curr )
88 : {
89 : Word16 bandIdx, k, chIdx, tapIdx;
90 : Word32 *filterStatesLeftRealPtr_fx, *filterStatesLeftImagPtr_fx;
91 : Word16 Q_filterStates;
92 : const Word32 *filterTapsLeftRealPtr_fx, *filterTapsLeftImagPtr_fx, *filterTapsRightRealPtr_fx, *filterTapsRightImagPtr_fx;
93 : Word16 shift_q;
94 161174 : Word16 shift_q6 = sub( -29 + 6, Q_curr );
95 161174 : Q_filterStates = hBinRenderer->hBinRenConvModule->Q_filterStates[pos_idx];
96 161174 : move16();
97 :
98 161174 : shift_q = add( sub( Q_filterStates, Q_curr ), 1 );
99 161174 : hBinRenderer->hBinRenConvModule->Q_filterStates[pos_idx] = Q_curr;
100 :
101 7520604 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
102 : {
103 36768310 : FOR( k = 0; k < numTimeSlots; k++ )
104 : {
105 29408880 : Word64 outRealLeft_fx = 0, outRealRight_fx = 0, outImagLeft_fx = 0, outImagRight_fx = 0;
106 29408880 : move64();
107 29408880 : move64();
108 29408880 : move64();
109 29408880 : move64();
110 29408880 : Word64 outRealLeft = 0, outRealRight = 0, outImagLeft = 0, outImagRight = 0;
111 29408880 : move64();
112 29408880 : move64();
113 29408880 : move64();
114 29408880 : move64();
115 :
116 418772560 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
117 : {
118 389363680 : filterStatesLeftRealPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx][0] );
119 389363680 : filterStatesLeftImagPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx][0] );
120 :
121 389363680 : filterTapsLeftRealPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsLeftReal_fx[bandIdx][chIdx]; // Q29
122 389363680 : filterTapsLeftImagPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsLeftImag_fx[bandIdx][chIdx]; // Q29
123 389363680 : filterTapsRightRealPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsRightReal_fx[bandIdx][chIdx]; // Q29
124 389363680 : filterTapsRightImagPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsRightImag_fx[bandIdx][chIdx]; // Q29
125 :
126 5246429120 : FOR( tapIdx = hBinRenderer->hBinRenConvModule->numTapsArray[bandIdx] - 1; tapIdx > 0; tapIdx-- )
127 : {
128 4857065440 : filterStatesLeftRealPtr_fx[tapIdx] = filterStatesLeftRealPtr_fx[tapIdx - 1];
129 4857065440 : move32();
130 4857065440 : filterStatesLeftImagPtr_fx[tapIdx] = filterStatesLeftImagPtr_fx[tapIdx - 1];
131 4857065440 : move32();
132 4857065440 : Word32 neg_filterStatesLeftImagPtr_fx = L_negate( filterStatesLeftImagPtr_fx[tapIdx] );
133 :
134 :
135 4857065440 : outRealLeft_fx = W_mac_32_32( outRealLeft_fx, filterStatesLeftRealPtr_fx[tapIdx], filterTapsLeftRealPtr_fx[tapIdx] ); // Q30 + Q_filterStates
136 4857065440 : outRealLeft_fx = W_mac_32_32( outRealLeft_fx, neg_filterStatesLeftImagPtr_fx, filterTapsLeftImagPtr_fx[tapIdx] ); // Q30 + Q_filterStates
137 :
138 4857065440 : outImagLeft_fx = W_mac_32_32( outImagLeft_fx, filterStatesLeftRealPtr_fx[tapIdx], filterTapsLeftImagPtr_fx[tapIdx] ); // Q30 + Q_filterStates
139 4857065440 : outImagLeft_fx = W_mac_32_32( outImagLeft_fx, filterStatesLeftImagPtr_fx[tapIdx], filterTapsLeftRealPtr_fx[tapIdx] ); // Q30 + Q_filterStates
140 :
141 4857065440 : outRealRight_fx = W_mac_32_32( outRealRight_fx, filterStatesLeftRealPtr_fx[tapIdx], filterTapsRightRealPtr_fx[tapIdx] ); // Q30 + Q_filterStates
142 4857065440 : outRealRight_fx = W_mac_32_32( outRealRight_fx, neg_filterStatesLeftImagPtr_fx, filterTapsRightImagPtr_fx[tapIdx] ); // Q30 + Q_filterStates
143 :
144 4857065440 : outImagRight_fx = W_mac_32_32( outImagRight_fx, filterStatesLeftRealPtr_fx[tapIdx], filterTapsRightImagPtr_fx[tapIdx] ); // Q30 + Q_filterStates
145 4857065440 : outImagRight_fx = W_mac_32_32( outImagRight_fx, filterStatesLeftImagPtr_fx[tapIdx], filterTapsRightRealPtr_fx[tapIdx] ); // Q30 + Q_filterStates
146 : }
147 :
148 389363680 : filterStatesLeftRealPtr_fx[0] = CLDFB_real[chIdx][k][bandIdx];
149 389363680 : move32();
150 389363680 : filterStatesLeftImagPtr_fx[0] = CLDFB_imag[chIdx][k][bandIdx];
151 389363680 : move32();
152 :
153 : /* Left Real and Imag */
154 389363680 : Word32 neg_temp2 = L_negate( filterStatesLeftImagPtr_fx[0] ); // Q_curr
155 :
156 389363680 : outRealLeft = W_mac_32_32( W_mac_32_32( outRealLeft, filterStatesLeftRealPtr_fx[0], filterTapsLeftRealPtr_fx[0] ), neg_temp2, filterTapsLeftImagPtr_fx[0] );
157 389363680 : outImagLeft = W_mac_32_32( W_mac_32_32( outImagLeft, filterStatesLeftImagPtr_fx[0], filterTapsLeftRealPtr_fx[0] ), filterStatesLeftRealPtr_fx[0], filterTapsLeftImagPtr_fx[0] );
158 :
159 : /* Right Real and Imag */
160 389363680 : outRealRight = W_mac_32_32( W_mac_32_32( outRealRight, neg_temp2, filterTapsRightImagPtr_fx[0] ), filterStatesLeftRealPtr_fx[0], filterTapsRightRealPtr_fx[0] );
161 389363680 : outImagRight = W_mac_32_32( W_mac_32_32( outImagRight, filterStatesLeftImagPtr_fx[0], filterTapsRightRealPtr_fx[0] ), filterStatesLeftRealPtr_fx[0], filterTapsRightImagPtr_fx[0] );
162 : }
163 29408880 : out_Conv_CLDFB_real[0][k][bandIdx] = W_shl_sat_l( W_add( W_shr( outRealLeft_fx, shift_q ), W_shr( outRealLeft, 1 ) ), shift_q6 );
164 29408880 : out_Conv_CLDFB_real[1][k][bandIdx] = W_shl_sat_l( W_add( W_shr( outRealRight_fx, shift_q ), W_shr( outRealRight, 1 ) ), shift_q6 );
165 29408880 : out_Conv_CLDFB_imag[0][k][bandIdx] = W_shl_sat_l( W_add( W_shr( outImagLeft_fx, shift_q ), W_shr( outImagLeft, 1 ) ), shift_q6 );
166 29408880 : out_Conv_CLDFB_imag[1][k][bandIdx] = W_shl_sat_l( W_add( W_shr( outImagRight_fx, shift_q ), W_shr( outImagRight, 1 ) ), shift_q6 );
167 29408880 : move32();
168 29408880 : move32();
169 29408880 : move32();
170 29408880 : move32();
171 : }
172 : }
173 :
174 :
175 161174 : return;
176 : }
177 :
178 :
179 : /*-------------------------------------------------------------------------
180 : * ivas_binRenderer_convModuleOpen()
181 : *
182 : * Open convolution module handle of fastconv binaural renderer
183 : *-------------------------------------------------------------------------*/
184 :
185 355 : static ivas_error ivas_binRenderer_convModuleOpen(
186 : BINAURAL_RENDERER_HANDLE hBinRenderer,
187 : const Word16 renderer_type,
188 : const Word16 isLoudspeaker,
189 : const AUDIO_CONFIG input_config,
190 : const HRTFS_FASTCONV_HANDLE hHrtf,
191 : const Word16 num_poses )
192 : {
193 : Word16 bandIdx, chIdx;
194 : Word16 pos_idx;
195 :
196 : BINRENDERER_CONV_MODULE_HANDLE_FX hBinRenConvModule;
197 :
198 : /*-----------------------------------------------------------------*
199 : * prepare library opening
200 : *-----------------------------------------------------------------*/
201 :
202 355 : IF( ( hBinRenConvModule = (BINRENDERER_CONV_MODULE_HANDLE_FX) malloc( sizeof( BINRENDERER_CONV_MODULE_FX ) ) ) == NULL )
203 : {
204 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
205 : }
206 :
207 355 : IF( !isLoudspeaker )
208 : {
209 201 : hBinRenderer->nInChannels = audioCfg2channels( input_config );
210 201 : move16();
211 : }
212 : ELSE
213 : {
214 : /* Note: needs to be revisited if multiple LFE support is required */
215 154 : hBinRenderer->nInChannels = sub( audioCfg2channels( input_config ), isLoudspeaker );
216 154 : move16();
217 : }
218 :
219 355 : hBinRenConvModule->numTaps = hHrtf->ntaps;
220 355 : move16();
221 :
222 355 : IF( EQ_16( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) )
223 : {
224 : /* Use variable order filtering */
225 70 : bandIdx = 0;
226 70 : move16();
227 420 : FOR( ; bandIdx < 5; bandIdx++ )
228 : {
229 350 : hBinRenConvModule->numTapsArray[bandIdx] = hBinRenConvModule->numTaps;
230 350 : move16();
231 : }
232 420 : FOR( ; bandIdx < 10; bandIdx++ )
233 : {
234 350 : hBinRenConvModule->numTapsArray[bandIdx] = NUM_TAPS_F0_6;
235 350 : move16();
236 : }
237 770 : FOR( ; bandIdx < 20; bandIdx++ )
238 : {
239 700 : hBinRenConvModule->numTapsArray[bandIdx] = NUM_TAPS_F0_5;
240 700 : move16();
241 : }
242 770 : FOR( ; bandIdx < 30; bandIdx++ )
243 : {
244 700 : hBinRenConvModule->numTapsArray[bandIdx] = NUM_TAPS_F0_4;
245 700 : move16();
246 : }
247 1340 : FOR( ; bandIdx < hBinRenderer->conv_band; bandIdx++ )
248 : {
249 1270 : hBinRenConvModule->numTapsArray[bandIdx] = NUM_TAPS_F0_3;
250 1270 : move16();
251 : }
252 : }
253 : ELSE
254 : {
255 : /* Use fixed order filtering */
256 285 : bandIdx = 0;
257 285 : move16();
258 11695 : FOR( ; bandIdx < hBinRenderer->conv_band; bandIdx++ )
259 : {
260 11410 : hBinRenConvModule->numTapsArray[bandIdx] = hBinRenConvModule->numTaps;
261 11410 : move16();
262 : }
263 : }
264 :
265 : /* allocate memory for filter states */
266 355 : IF( ( hBinRenConvModule->filterTapsLeftReal_fx = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
267 : {
268 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
269 : }
270 :
271 355 : IF( ( hBinRenConvModule->filterTapsLeftImag_fx = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
272 : {
273 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
274 : }
275 :
276 355 : IF( ( hBinRenConvModule->filterTapsRightReal_fx = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
277 : {
278 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
279 : }
280 :
281 355 : IF( ( hBinRenConvModule->filterTapsRightImag_fx = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
282 : {
283 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
284 : }
285 :
286 15105 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
287 : {
288 14750 : IF( ( hBinRenConvModule->filterTapsLeftReal_fx[bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
289 : {
290 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
291 : }
292 :
293 14750 : IF( ( hBinRenConvModule->filterTapsLeftImag_fx[bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
294 : {
295 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
296 : }
297 :
298 14750 : IF( ( hBinRenConvModule->filterTapsRightReal_fx[bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
299 : {
300 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
301 : }
302 :
303 14750 : IF( ( hBinRenConvModule->filterTapsRightImag_fx[bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
304 : {
305 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
306 : }
307 : }
308 :
309 355 : IF( ( hBinRenConvModule->filterStatesLeftReal_fx = (Word32 ****) malloc( num_poses * sizeof( Word32 *** ) ) ) == NULL )
310 : {
311 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
312 : }
313 :
314 355 : IF( ( hBinRenConvModule->filterStatesLeftImag_fx = (Word32 ****) malloc( num_poses * sizeof( Word32 *** ) ) ) == NULL )
315 : {
316 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
317 : }
318 :
319 355 : IF( ( hBinRenConvModule->Q_filterStates = (Word16 *) malloc( num_poses * sizeof( Word16 ) ) ) == NULL )
320 : {
321 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
322 : }
323 :
324 710 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
325 : {
326 355 : IF( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx] = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
327 : {
328 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
329 : }
330 :
331 355 : IF( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx] = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL )
332 : {
333 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
334 : }
335 :
336 15105 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
337 : {
338 14750 : IF( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
339 : {
340 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
341 : }
342 :
343 14750 : IF( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL )
344 : {
345 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
346 : }
347 :
348 :
349 190730 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
350 : {
351 175980 : IF( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx] = (Word32 *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( Word32 ) ) ) == NULL )
352 : {
353 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
354 : }
355 :
356 175980 : IF( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx] = (Word32 *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( Word32 ) ) ) == NULL )
357 : {
358 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) );
359 : }
360 : }
361 : }
362 : }
363 :
364 : /* set memories */
365 15105 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
366 : {
367 190730 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
368 : {
369 : Word16 tmp;
370 175980 : tmp = chIdx;
371 175980 : move16();
372 :
373 175980 : IF( isLoudspeaker )
374 : {
375 34700 : IF( EQ_16( input_config, IVAS_AUDIO_CONFIG_5_1 ) )
376 : {
377 25150 : tmp = channelIndex_CICP6[chIdx];
378 25150 : move16();
379 : }
380 9550 : ELSE IF( EQ_16( input_config, IVAS_AUDIO_CONFIG_7_1 ) )
381 : {
382 0 : tmp = channelIndex_CICP12[chIdx];
383 0 : move16();
384 : }
385 9550 : ELSE IF( EQ_16( input_config, IVAS_AUDIO_CONFIG_5_1_2 ) )
386 : {
387 420 : tmp = channelIndex_CICP14[chIdx];
388 420 : move16();
389 : }
390 9130 : ELSE IF( EQ_16( input_config, IVAS_AUDIO_CONFIG_5_1_4 ) )
391 : {
392 0 : tmp = channelIndex_CICP16[chIdx];
393 0 : move16();
394 : }
395 9130 : ELSE IF( EQ_16( input_config, IVAS_AUDIO_CONFIG_7_1_4 ) )
396 : {
397 9130 : tmp = channelIndex_CICP19[chIdx];
398 9130 : move16();
399 : }
400 : }
401 :
402 175980 : hBinRenConvModule->filterTapsLeftReal_fx[bandIdx][chIdx] = hHrtf->leftReal_fx[bandIdx][tmp];
403 175980 : hBinRenConvModule->filterTapsLeftImag_fx[bandIdx][chIdx] = hHrtf->leftImag_fx[bandIdx][tmp];
404 175980 : hBinRenConvModule->filterTapsRightReal_fx[bandIdx][chIdx] = hHrtf->rightReal_fx[bandIdx][tmp];
405 175980 : hBinRenConvModule->filterTapsRightImag_fx[bandIdx][chIdx] = hHrtf->rightImag_fx[bandIdx][tmp];
406 : }
407 : }
408 :
409 355 : IF( EQ_16( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) )
410 : {
411 140 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
412 : {
413 70 : hBinRenConvModule->Q_filterStates[pos_idx] = 31;
414 70 : move16();
415 3410 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
416 : {
417 23040 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
418 : {
419 : /* set the memories to zero */
420 19700 : set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] );
421 19700 : set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] );
422 : }
423 : }
424 : }
425 : }
426 : ELSE
427 : {
428 570 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
429 : {
430 285 : hBinRenConvModule->Q_filterStates[pos_idx] = 31;
431 285 : move16();
432 11695 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
433 : {
434 167690 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
435 : {
436 : /* set the memories to zero */
437 156280 : set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTaps );
438 156280 : set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTaps );
439 : }
440 : }
441 : }
442 : }
443 :
444 355 : hBinRenderer->hBinRenConvModule = hBinRenConvModule;
445 :
446 355 : return IVAS_ERR_OK;
447 : }
448 :
449 :
450 : /*-------------------------------------------------------------------------*
451 : * ivas_init_binaural_hrtf()
452 : *
453 : * initialize memory for HrtfFastConv structure elements
454 : *-------------------------------------------------------------------------*/
455 :
456 114 : void ivas_init_binaural_hrtf_fx(
457 : HRTFS_FASTCONV *HrtfFastConv /* i/o: FASTCONV HRTF structure */
458 : )
459 : {
460 : Word16 i;
461 :
462 114 : HrtfFastConv->leftReal_fx = NULL;
463 114 : HrtfFastConv->leftImag_fx = NULL;
464 114 : HrtfFastConv->rightReal_fx = NULL;
465 114 : HrtfFastConv->rightImag_fx = NULL;
466 114 : HrtfFastConv->FASTCONV_latency_s_fx = 0x00;
467 114 : move32();
468 114 : HrtfFastConv->n_channels = 0;
469 114 : move16();
470 114 : HrtfFastConv->allocate_init_flag = 0;
471 114 : move16();
472 114 : HrtfFastConv->ntaps = 0;
473 114 : move16();
474 114 : HrtfFastConv->FASTCONV_latency_s_Q_fx = 0;
475 114 : move16();
476 114 : HrtfFastConv->FASTCONV_taps_s_Q_fx = 0;
477 114 : move16();
478 114 : HrtfFastConv->FASTCONV_reverbTime_s_Q_fx = 0;
479 114 : move16();
480 114 : HrtfFastConv->FASTCONV_reverbEne_s_Q_fx = 0;
481 114 : move16();
482 :
483 6954 : FOR( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ )
484 : {
485 6840 : HrtfFastConv->fastconvReverberationTimes_fx[i] = 0;
486 6840 : move32();
487 6840 : HrtfFastConv->fastconvReverberationEneCorrections_fx[i] = 0;
488 6840 : move32();
489 : }
490 :
491 114 : return;
492 : }
493 :
494 :
495 : /*-------------------------------------------------------------------------*
496 : * ivas_alloc_pppMem()
497 : *
498 : * Allocate memory for tripple pointer elements
499 : *-------------------------------------------------------------------------*/
500 :
501 456 : static ivas_error ivas_alloc_pppMem_fx(
502 : Word32 ****pppMem, /*Qx*/
503 : const Word16 dim1,
504 : const Word16 dim2,
505 : const Word16 dim3,
506 : const Word16 allocate_init_flag )
507 : {
508 : Word16 i, j;
509 456 : Word32 ***localMem = NULL;
510 :
511 456 : IF( ( localMem = (Word32 ***) malloc( dim1 * sizeof( Word32 ** ) ) ) == NULL )
512 : {
513 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" );
514 : }
515 :
516 23256 : FOR( i = 0; i < dim1; i++ ){
517 22800 : IF( ( localMem[i] = (Word32 **) malloc( dim2 * sizeof( Word32 * ) ) ) == NULL ){
518 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" );
519 : }
520 22800 : IF( allocate_init_flag == 0 )
521 : {
522 382400 : FOR( j = 0; j < dim2; j++ )
523 : {
524 359600 : IF( ( localMem[i][j] = (Word32 *) malloc( dim3 * sizeof( Word32 ) ) ) == NULL )
525 : {
526 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" );
527 : }
528 : }
529 : }
530 : }
531 :
532 456 : *pppMem = localMem;
533 :
534 456 : return IVAS_ERR_OK;
535 : }
536 :
537 :
538 : /*-------------------------------------------------------------------------*
539 : * ivas_allocate_binaural_hrtf()
540 : *
541 : * Allocate memory for HrtfFastConv structure elements
542 : *-------------------------------------------------------------------------*/
543 :
544 119 : ivas_error ivas_allocate_binaural_hrtf_fx(
545 : HRTFS_FASTCONV *HrtfFastConv, /* i/o: FASTCONV HRTF structure */
546 : const int16_t n_channels, /* i : number of input channels */
547 : const Word16 allocate_init_flag /* i : Memory allocation flag */
548 : )
549 : {
550 119 : HrtfFastConv->n_channels = n_channels;
551 119 : move16();
552 :
553 119 : test();
554 119 : test();
555 119 : test();
556 119 : IF( ( HrtfFastConv->leftReal_fx != NULL ) && ( HrtfFastConv->leftImag_fx != NULL ) && ( HrtfFastConv->rightReal_fx != NULL ) && ( HrtfFastConv->rightImag_fx != NULL ) )
557 : {
558 5 : return IVAS_ERR_OK;
559 : }
560 : ELSE
561 : {
562 114 : IF( IVAS_ERR_OK != ivas_alloc_pppMem_fx( &HrtfFastConv->leftReal_fx, BINAURAL_CONVBANDS, n_channels, HrtfFastConv->ntaps, allocate_init_flag ) )
563 : {
564 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HrtfFastConv->leftReal" );
565 : }
566 114 : IF( IVAS_ERR_OK != ivas_alloc_pppMem_fx( &HrtfFastConv->leftImag_fx, BINAURAL_CONVBANDS, n_channels, HrtfFastConv->ntaps, allocate_init_flag ) )
567 : {
568 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HrtfFastConv->leftImag" );
569 : }
570 114 : IF( IVAS_ERR_OK != ivas_alloc_pppMem_fx( &HrtfFastConv->rightReal_fx, BINAURAL_CONVBANDS, n_channels, HrtfFastConv->ntaps, allocate_init_flag ) )
571 : {
572 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HrtfFastConv->rightReal" );
573 : }
574 114 : IF( IVAS_ERR_OK != ivas_alloc_pppMem_fx( &HrtfFastConv->rightImag_fx, BINAURAL_CONVBANDS, n_channels, HrtfFastConv->ntaps, allocate_init_flag ) )
575 : {
576 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HrtfFastConv->rightImag" );
577 : }
578 : }
579 :
580 114 : return IVAS_ERR_OK;
581 : }
582 :
583 :
584 : /*-------------------------------------------------------------------------*
585 : * ivas_binaural_hrtf_open()
586 : *
587 : *
588 : *-------------------------------------------------------------------------*/
589 :
590 355 : static ivas_error ivas_binaural_hrtf_open_fx(
591 : HRTFS_FASTCONV_HANDLE *hHrtfFastConv, /* i : fastconv HRTF handle */
592 : const AUDIO_CONFIG input_config, /* i : output configuration */
593 : const RENDERER_TYPE renderer_type /* i : renderer type */
594 : )
595 : {
596 : Word16 i, j;
597 : ivas_error error;
598 : Word16 n_channels;
599 :
600 355 : test();
601 355 : IF( hHrtfFastConv != NULL && *hHrtfFastConv != NULL )
602 : {
603 : /* Tables already loaded from file */
604 309 : return IVAS_ERR_OK;
605 : }
606 : ELSE
607 : {
608 : /* Initialise tables from ROM */
609 : HRTFS_FASTCONV *HrtfFastConv;
610 :
611 46 : IF( ( HrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL )
612 : {
613 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for FastConv HRTF tables" );
614 : }
615 :
616 46 : ivas_init_binaural_hrtf_fx( HrtfFastConv );
617 :
618 46 : test();
619 46 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV ) )
620 : {
621 32 : HrtfFastConv->FASTCONV_latency_s_fx = FASTCONV_HRIR_latency_s_fx;
622 32 : move32();
623 32 : HrtfFastConv->FASTCONV_latency_s_Q_fx = Q31 - FASTCONV_factor_Q_HRIR_latency_s_fx;
624 32 : move16();
625 32 : HrtfFastConv->FASTCONV_taps_s_Q_fx = Q15 - FASTCONV_factor_Q_HRIR_fx;
626 32 : move16();
627 32 : HrtfFastConv->ntaps = BINAURAL_NTAPS;
628 32 : move16();
629 : }
630 :
631 46 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA2 ) )
632 : {
633 0 : HrtfFastConv->FASTCONV_latency_s_fx = FASTCONV_HOA2_latency_s_fx;
634 0 : move32();
635 0 : HrtfFastConv->FASTCONV_latency_s_Q_fx = Q31 - FASTCONV_factor_Q_HOA2_latency_s_fx;
636 0 : move16();
637 0 : HrtfFastConv->FASTCONV_taps_s_Q_fx = Q15 - FASTCONV_factor_Q_HOA2_fx;
638 0 : move16();
639 0 : HrtfFastConv->ntaps = BINAURAL_NTAPS_SBA;
640 0 : move16();
641 : }
642 46 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA3 ) )
643 : {
644 34 : HrtfFastConv->FASTCONV_latency_s_fx = FASTCONV_HOA3_latency_s_fx;
645 34 : move32();
646 34 : HrtfFastConv->FASTCONV_latency_s_Q_fx = Q31 - FASTCONV_factor_Q_HOA3_latency_s_fx;
647 34 : move16();
648 34 : HrtfFastConv->FASTCONV_taps_s_Q_fx = Q15 - FASTCONV_factor_Q_HOA3_fx;
649 34 : move16();
650 34 : HrtfFastConv->ntaps = BINAURAL_NTAPS_SBA;
651 34 : move16();
652 : }
653 46 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_FOA ) )
654 : {
655 0 : HrtfFastConv->FASTCONV_latency_s_fx = FASTCONV_FOA_latency_s_fx;
656 0 : move32();
657 0 : HrtfFastConv->FASTCONV_latency_s_Q_fx = Q31 - FASTCONV_factor_Q_FOA_latency_s_fx;
658 0 : move16();
659 0 : HrtfFastConv->FASTCONV_taps_s_Q_fx = Q15 - FASTCONV_factor_Q_FOA_fx;
660 0 : move16();
661 0 : HrtfFastConv->ntaps = BINAURAL_NTAPS_SBA;
662 0 : move16();
663 : }
664 :
665 46 : test();
666 46 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) )
667 : {
668 14 : HrtfFastConv->FASTCONV_latency_s_fx = FASTCONV_BRIR_latency_s_fx;
669 14 : move32();
670 14 : HrtfFastConv->FASTCONV_latency_s_Q_fx = Q31 - FASTCONV_factor_Q_BRIR_latency_s_fx;
671 14 : move16();
672 14 : HrtfFastConv->FASTCONV_taps_s_Q_fx = Q15 - FASTCONV_factor_Q_BRIR_fx;
673 14 : move16();
674 14 : HrtfFastConv->FASTCONV_reverbTime_s_Q_fx = Q15 - FASTCONV_factor_Q_reverberationTimes_fx;
675 14 : move16();
676 14 : HrtfFastConv->FASTCONV_reverbEne_s_Q_fx = Q15 - FASTCONV_factor_Q_reverberationEneCorrections_fx;
677 14 : move16();
678 14 : HrtfFastConv->ntaps = BINAURAL_NTAPS_MAX;
679 14 : move16();
680 : }
681 :
682 46 : HrtfFastConv->allocate_init_flag = 0;
683 46 : move16();
684 :
685 46 : n_channels = 0;
686 46 : move16();
687 :
688 46 : test();
689 46 : test();
690 46 : IF( ( EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) && NE_32( input_config, IVAS_AUDIO_CONFIG_INVALID ) )
691 : {
692 46 : n_channels = HRTF_LS_CHANNELS;
693 46 : move16();
694 : }
695 :
696 46 : IF( EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV ) )
697 : {
698 32 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA3 ) )
699 : {
700 27 : n_channels = HOA3_CHANNELS;
701 27 : move16();
702 : }
703 5 : ELSE IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA2 ) )
704 : {
705 0 : n_channels = HOA2_CHANNELS;
706 0 : move16();
707 : }
708 5 : ELSE IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_FOA ) )
709 : {
710 0 : n_channels = FOA_CHANNELS;
711 0 : move16();
712 : }
713 : }
714 :
715 46 : IF( NE_32( ( error = ivas_allocate_binaural_hrtf_fx( HrtfFastConv, n_channels, HrtfFastConv->allocate_init_flag ) ), IVAS_ERR_OK ) )
716 : {
717 0 : return error;
718 : }
719 :
720 2346 : FOR( i = 0; i < BINAURAL_CONVBANDS; i++ )
721 : {
722 2300 : test();
723 2300 : test();
724 2300 : IF( EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV ) && EQ_32( HrtfFastConv->n_channels, HRTF_LS_CHANNELS ) )
725 : {
726 4000 : FOR( j = 0; j < HRTF_LS_CHANNELS; j++ )
727 : {
728 3750 : Copy_Scale_sig_16_32_r( leftHRIRReal_fx[i][j], HrtfFastConv->leftReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HRIR_fx );
729 3750 : Copy_Scale_sig_16_32_r( leftHRIRImag_fx[i][j], HrtfFastConv->leftImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HRIR_fx );
730 3750 : Copy_Scale_sig_16_32_r( rightHRIRReal_fx[i][j], HrtfFastConv->rightReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HRIR_fx );
731 3750 : Copy_Scale_sig_16_32_r( rightHRIRImag_fx[i][j], HrtfFastConv->rightImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HRIR_fx );
732 : }
733 : }
734 2050 : ELSE IF( EQ_32( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) && EQ_32( HrtfFastConv->n_channels, HRTF_LS_CHANNELS ) )
735 : {
736 11200 : FOR( j = 0; j < HRTF_LS_CHANNELS; j++ )
737 : {
738 10500 : Copy_Scale_sig_16_32_r( leftBRIRReal_fx[i][j], HrtfFastConv->leftReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_BRIR_fx );
739 10500 : Copy_Scale_sig_16_32_r( leftBRIRImag_fx[i][j], HrtfFastConv->leftImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_BRIR_fx );
740 10500 : Copy_Scale_sig_16_32_r( rightBRIRReal_fx[i][j], HrtfFastConv->rightReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_BRIR_fx );
741 10500 : Copy_Scale_sig_16_32_r( rightBRIRImag_fx[i][j], HrtfFastConv->rightImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_BRIR_fx );
742 : }
743 : }
744 :
745 2300 : test();
746 2300 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA3 ) && EQ_32( HrtfFastConv->n_channels, HOA3_CHANNELS ) )
747 : {
748 22950 : FOR( j = 0; j < HOA3_CHANNELS; j++ )
749 : {
750 21600 : Copy_Scale_sig_16_32_r( leftHRIRReal_HOA3_fx[i][j], HrtfFastConv->leftReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA3_fx );
751 21600 : Copy_Scale_sig_16_32_r( leftHRIRImag_HOA3_fx[i][j], HrtfFastConv->leftImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA3_fx );
752 21600 : Copy_Scale_sig_16_32_r( rightHRIRReal_HOA3_fx[i][j], HrtfFastConv->rightReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA3_fx );
753 21600 : Copy_Scale_sig_16_32_r( rightHRIRImag_HOA3_fx[i][j], HrtfFastConv->rightImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA3_fx );
754 : }
755 : }
756 :
757 : /* Note: IVAS_AUDIO_CONFIG_HOA2 and IVAS_AUDIO_CONFIG_FOA input configs. are not relevant in internal renderer
758 : as SBA to binaural always synthesizes HOA3 output for binauralization. However, the external renderer can use them. */
759 2300 : test();
760 2300 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_HOA2 ) && EQ_32( HrtfFastConv->n_channels, HOA2_CHANNELS ) )
761 : {
762 0 : FOR( j = 0; j < HOA2_CHANNELS; j++ )
763 : {
764 0 : Copy_Scale_sig_16_32_r( leftHRIRReal_HOA2_fx[i][j], HrtfFastConv->leftReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA2_fx );
765 0 : Copy_Scale_sig_16_32_r( leftHRIRImag_HOA2_fx[i][j], HrtfFastConv->leftImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA2_fx );
766 0 : Copy_Scale_sig_16_32_r( rightHRIRReal_HOA2_fx[i][j], HrtfFastConv->rightReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA2_fx );
767 0 : Copy_Scale_sig_16_32_r( rightHRIRImag_HOA2_fx[i][j], HrtfFastConv->rightImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_HOA2_fx );
768 : }
769 : }
770 :
771 2300 : test();
772 2300 : IF( EQ_32( input_config, IVAS_AUDIO_CONFIG_FOA ) && EQ_32( HrtfFastConv->n_channels, FOA_CHANNELS ) )
773 : {
774 0 : FOR( j = 0; j < FOA_CHANNELS; j++ )
775 : {
776 0 : Copy_Scale_sig_16_32_r( leftHRIRReal_FOA_fx[i][j], HrtfFastConv->leftReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_FOA_fx );
777 0 : Copy_Scale_sig_16_32_r( leftHRIRImag_FOA_fx[i][j], HrtfFastConv->leftImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_FOA_fx );
778 0 : Copy_Scale_sig_16_32_r( rightHRIRReal_FOA_fx[i][j], HrtfFastConv->rightReal_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_FOA_fx );
779 0 : Copy_Scale_sig_16_32_r( rightHRIRImag_FOA_fx[i][j], HrtfFastConv->rightImag_fx[i][j], HrtfFastConv->ntaps, Q29 - FASTCONV_factor_Q_FOA_fx );
780 : }
781 : }
782 : }
783 :
784 46 : Copy_Scale_sig_16_32_r( fastconvReverberationTimes_fx, HrtfFastConv->fastconvReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX, Q26 - FASTCONV_factor_Q_reverberationTimes_fx );
785 46 : Copy_Scale_sig_16_32_r( fastconvReverberationEneCorrections_fx, HrtfFastConv->fastconvReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX, Q31 - FASTCONV_factor_Q_reverberationTimes_fx );
786 :
787 46 : *hHrtfFastConv = HrtfFastConv;
788 :
789 46 : return IVAS_ERR_OK;
790 : }
791 : }
792 :
793 :
794 : /*-------------------------------------------------------------------------*
795 : * ivas_binaural_obtain_DMX()
796 : *
797 : *
798 : *-------------------------------------------------------------------------*/
799 :
800 104850 : static void ivas_binaural_obtain_DMX_fx(
801 : const Word16 numTimeSlots,
802 : BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */
803 : Word32 RealBuffer[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Contains the LS signals Q_in_out */
804 : Word32 ImagBuffer[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i : Contains the LS signals Q_in_out */
805 : Word32 realDMX[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* Q_in_out */
806 : Word32 imagDMX[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* Q_in_out */
807 : Word16 *Q_in_out ) /* i/o: input and output Q */
808 : {
809 : Word16 chIdx, bandIdx, k;
810 :
811 104850 : test();
812 104850 : IF( EQ_32( hBinRenderer->ivas_format, MC_FORMAT ) )
813 : {
814 : /* Obtain the downmix */
815 : Word32 P_in_fx[CLDFB_NO_CHANNELS_MAX];
816 : Word32 P_out_fx, factEQ_fx;
817 : Word16 chOutIdx;
818 : Word32 temp1_fx, temp2_fx;
819 :
820 157200 : FOR( k = 0; k < numTimeSlots; k++ )
821 : {
822 377280 : FOR( chOutIdx = 0; chOutIdx < BINAURAL_CHANNELS; chOutIdx++ )
823 : {
824 251520 : set32_fx( realDMX[chOutIdx][k], 0, CLDFB_NO_CHANNELS_MAX );
825 251520 : set32_fx( imagDMX[chOutIdx][k], 0, CLDFB_NO_CHANNELS_MAX );
826 : }
827 : }
828 :
829 94320 : FOR( chOutIdx = 0; chOutIdx < BINAURAL_CHANNELS; chOutIdx++ )
830 : {
831 62880 : set32_fx( P_in_fx, 0, hBinRenderer->conv_band );
832 :
833 576960 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
834 : {
835 514080 : Word32 dmxConst = dmxmtx_table_fx[chOutIdx][chIdx];
836 :
837 24879680 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
838 : {
839 121828000 : FOR( k = 0; k < numTimeSlots; k++ )
840 : {
841 97462400 : temp1_fx = Mpy_32_32( RealBuffer[chIdx][k][bandIdx], dmxConst ); // Q_in_out
842 97462400 : temp2_fx = Mpy_32_32( ImagBuffer[chIdx][k][bandIdx], dmxConst ); // Q_in_out
843 97462400 : realDMX[chOutIdx][k][bandIdx] = L_add( realDMX[chOutIdx][k][bandIdx], temp1_fx ); // Q_in_out
844 97462400 : move32();
845 97462400 : imagDMX[chOutIdx][k][bandIdx] = L_add( imagDMX[chOutIdx][k][bandIdx], temp2_fx ); // Q_in_out
846 97462400 : move32();
847 97462400 : P_in_fx[bandIdx] = L_add( P_in_fx[bandIdx], L_add( Mpy_32_32( temp1_fx, temp1_fx ), Mpy_32_32( temp2_fx, temp2_fx ) ) ); // Q31-2*Q_in_out
848 97462400 : move32();
849 : }
850 : }
851 : }
852 :
853 3038080 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
854 : {
855 2975200 : P_out_fx = 0;
856 2975200 : move32();
857 14876000 : FOR( k = 0; k < numTimeSlots; k++ )
858 : {
859 11900800 : temp1_fx = realDMX[chOutIdx][k][bandIdx];
860 11900800 : move32();
861 11900800 : temp2_fx = imagDMX[chOutIdx][k][bandIdx];
862 11900800 : move32();
863 11900800 : P_out_fx = L_add( P_out_fx, L_add( Mpy_32_32( temp1_fx, temp1_fx ), Mpy_32_32( temp2_fx, temp2_fx ) ) ); // Q31-2*Q_in_out
864 : }
865 2975200 : test();
866 2975200 : IF( ( P_in_fx[bandIdx] <= 0 ) || ( P_out_fx <= 0 ) )
867 : {
868 1723494 : factEQ_fx = 0x40000000; // 1.0f in Q30
869 1723494 : move32();
870 : }
871 : ELSE
872 : {
873 1251706 : Word16 div = divide3232( P_in_fx[bandIdx], P_out_fx );
874 1251706 : Word16 exp = 16; // divide3232 returns Q15
875 1251706 : factEQ_fx = Sqrt32( div, &exp );
876 1251706 : factEQ_fx = L_shl( factEQ_fx, sub( exp, 1 ) ); // Q30
877 : }
878 2975200 : if ( factEQ_fx <= 0 )
879 : {
880 0 : factEQ_fx = 0x40000000; // 1.0f in Q30
881 0 : move32();
882 : }
883 :
884 2975200 : factEQ_fx = L_max( L_min( factEQ_fx, 0x7fffffff ), 0x20000000 ); // Q30 , 0x7fffffff -> (1.0f in Q31)-1, 0x20000000 ->1.0f in Q29
885 14876000 : FOR( k = 0; k < numTimeSlots; k++ )
886 : {
887 11900800 : realDMX[chOutIdx][k][bandIdx] = Mpy_32_32( realDMX[chOutIdx][k][bandIdx], factEQ_fx ); // Q_in_out - 1
888 11900800 : move32();
889 11900800 : imagDMX[chOutIdx][k][bandIdx] = Mpy_32_32( imagDMX[chOutIdx][k][bandIdx], factEQ_fx ); // Q_in_out - 1
890 11900800 : move32();
891 : }
892 : }
893 : }
894 31440 : *Q_in_out = sub( *Q_in_out, 1 );
895 : }
896 73410 : ELSE IF( EQ_32( hBinRenderer->ivas_format, SBA_FORMAT ) || EQ_32( hBinRenderer->ivas_format, MASA_FORMAT ) )
897 : {
898 : Word32 *outRealLeftPtr_fx, *outImagLeftPtr_fx, *outRealRightPtr_fx, *outImagRightPtr_fx;
899 : Word32 *inRealPtr_fx, *inImagPtr_fx;
900 :
901 : /*compute DMX */
902 366449 : FOR( k = 0; k < numTimeSlots; k++ )
903 : {
904 293039 : outRealLeftPtr_fx = realDMX[0][k];
905 293039 : outImagLeftPtr_fx = imagDMX[0][k];
906 293039 : outRealRightPtr_fx = realDMX[1][k];
907 293039 : outImagRightPtr_fx = imagDMX[1][k];
908 293039 : set32_fx( outRealLeftPtr_fx, 0, CLDFB_NO_CHANNELS_MAX );
909 293039 : set32_fx( outImagLeftPtr_fx, 0, CLDFB_NO_CHANNELS_MAX );
910 293039 : set32_fx( outRealRightPtr_fx, 0, CLDFB_NO_CHANNELS_MAX );
911 293039 : set32_fx( outImagRightPtr_fx, 0, CLDFB_NO_CHANNELS_MAX );
912 :
913 : /*Ambisonics input requires different processing*/
914 293039 : IF( EQ_16( hBinRenderer->nInChannels, HOA3_CHANNELS ) )
915 : {
916 : Word32 *inRealPtr_W, *inImagPtr_W;
917 : Word32 *inRealPtr_Y, *inImagPtr_Y;
918 :
919 181055 : inRealPtr_W = (Word32 *) &( RealBuffer[0][k][0] );
920 181055 : inImagPtr_W = (Word32 *) &( ImagBuffer[0][k][0] );
921 :
922 181055 : inRealPtr_Y = (Word32 *) &( RealBuffer[1][k][0] );
923 181055 : inImagPtr_Y = (Word32 *) &( ImagBuffer[1][k][0] );
924 :
925 8032175 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
926 : {
927 7851120 : outRealLeftPtr_fx[bandIdx] = L_add( inRealPtr_W[bandIdx], inRealPtr_Y[bandIdx] );
928 7851120 : outImagLeftPtr_fx[bandIdx] = L_add( inImagPtr_W[bandIdx], inImagPtr_Y[bandIdx] );
929 :
930 7851120 : outRealRightPtr_fx[bandIdx] = L_sub( inRealPtr_W[bandIdx], inRealPtr_Y[bandIdx] );
931 7851120 : outImagRightPtr_fx[bandIdx] = L_sub( inImagPtr_W[bandIdx], inImagPtr_Y[bandIdx] );
932 : }
933 : }
934 : ELSE
935 : {
936 1343808 : FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ )
937 : {
938 1231824 : Word32 foa_const_fx = L_shl( hBinRenderer->hReverb->foa_enc_fx[chIdx][1], 1 ); // Q30
939 : Word32 one_add_foa_const, one_sub_foa_const;
940 :
941 1231824 : one_add_foa_const = L_add( ONE_IN_Q30, foa_const_fx ); // Q30
942 1231824 : one_sub_foa_const = L_sub_sat( ONE_IN_Q30, foa_const_fx ); // Q30
943 :
944 1231824 : inRealPtr_fx = (Word32 *) &( RealBuffer[chIdx][k][0] );
945 1231824 : inImagPtr_fx = (Word32 *) &( ImagBuffer[chIdx][k][0] );
946 :
947 52263024 : FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ )
948 : {
949 51031200 : outRealLeftPtr_fx[bandIdx] = L_add( outRealLeftPtr_fx[bandIdx], Mpy_32_32( inRealPtr_fx[bandIdx], one_add_foa_const ) ); // Q_in - 1
950 51031200 : move32();
951 51031200 : outImagLeftPtr_fx[bandIdx] = L_add( outImagLeftPtr_fx[bandIdx], Mpy_32_32( inImagPtr_fx[bandIdx], one_add_foa_const ) ); // Q_in - 1
952 51031200 : move32();
953 :
954 51031200 : outRealRightPtr_fx[bandIdx] = L_add( outRealRightPtr_fx[bandIdx], Mpy_32_32( inRealPtr_fx[bandIdx], one_sub_foa_const ) ); // Q_in - 1
955 51031200 : move32();
956 51031200 : outImagRightPtr_fx[bandIdx] = L_add( outImagRightPtr_fx[bandIdx], Mpy_32_32( inImagPtr_fx[bandIdx], one_sub_foa_const ) ); // Q_in - 1
957 51031200 : move32();
958 : }
959 : }
960 : }
961 : }
962 :
963 73410 : IF( NE_16( hBinRenderer->nInChannels, HOA3_CHANNELS ) )
964 : {
965 27996 : *Q_in_out = sub( *Q_in_out, 1 );
966 : }
967 : }
968 :
969 104850 : return;
970 : }
971 :
972 :
973 : /*-------------------------------------------------------------------------
974 : * ivas_rend_openCldfbRend()
975 : *
976 : * Allocate and initialize CLDFB fast conv renderer handle
977 : *------------------------------------------------------------------------*/
978 :
979 0 : ivas_error ivas_rend_openCldfbRend(
980 : CLDFB_REND_WRAPPER *pCldfbRend,
981 : const AUDIO_CONFIG inConfig,
982 : const AUDIO_CONFIG outConfig,
983 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
984 : const Word32 output_Fs )
985 : {
986 : BINAURAL_RENDERER_HANDLE hBinRenderer;
987 : Word16 convBand;
988 : ivas_error error;
989 :
990 : /*-----------------------------------------------------------------*
991 : * prepare library opening
992 : *-----------------------------------------------------------------*/
993 :
994 0 : IF( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL )
995 : {
996 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Renderer\n" ) );
997 : }
998 :
999 0 : IF( ( hBinRenderer->hInputSetup = (IVAS_OUTPUT_SETUP_HANDLE) malloc( sizeof( IVAS_OUTPUT_SETUP ) ) ) == NULL )
1000 : {
1001 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for output setup Binaural Renderer\n" ) );
1002 : }
1003 :
1004 0 : hBinRenderer->rotInCldfb = 1;
1005 0 : hBinRenderer->ivas_format = SBA_FORMAT;
1006 :
1007 0 : hBinRenderer->max_band = extract_l( Mpy_32_32( Mpy_32_32( BINAURAL_MAXBANDS_Q25, L_shl( output_Fs, Q6 ) ), ONE_BY_48000_Q31 ) );
1008 0 : move16();
1009 :
1010 0 : convBand = hBinRenderer->max_band;
1011 0 : move16();
1012 :
1013 0 : hBinRenderer->timeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; /* Corresponds to 5 msec sound to motion latency */
1014 0 : move16();
1015 :
1016 0 : IF( GT_16( convBand, BINAURAL_CONVBANDS ) )
1017 : {
1018 0 : hBinRenderer->conv_band = BINAURAL_CONVBANDS;
1019 0 : move16();
1020 : }
1021 : ELSE
1022 : {
1023 0 : hBinRenderer->conv_band = convBand;
1024 0 : move16();
1025 : }
1026 :
1027 0 : ivas_output_init( hBinRenderer->hInputSetup, inConfig );
1028 :
1029 0 : IF( ( error = getAudioConfigNumChannels( inConfig, &hBinRenderer->hInputSetup->nchan_out_woLFE ) ) != IVAS_ERR_OK )
1030 : {
1031 0 : return error;
1032 : }
1033 :
1034 0 : IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
1035 : {
1036 0 : hBinRenderer->numPoses = pMultiBinPoseData->num_poses;
1037 0 : move16();
1038 : }
1039 : ELSE
1040 : {
1041 0 : hBinRenderer->numPoses = 1;
1042 0 : move16();
1043 : }
1044 :
1045 : /*LFE rendering switched off by default*/
1046 0 : hBinRenderer->render_lfe = 0;
1047 0 : move16();
1048 :
1049 :
1050 : /* Load HRTF tables */
1051 0 : IF( NE_32( ( error = ivas_binaural_hrtf_open_fx( &pCldfbRend->hHrtfFastConv, hBinRenderer->hInputSetup->output_config, RENDERER_BINAURAL_FASTCONV ) ), IVAS_ERR_OK ) )
1052 : {
1053 0 : return error;
1054 : }
1055 :
1056 : /* Allocate memories and buffers needed for convolutional module in CICP19 */
1057 0 : IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, RENDERER_BINAURAL_FASTCONV, hBinRenderer->hInputSetup->is_loudspeaker_setup, inConfig, pCldfbRend->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) )
1058 : {
1059 0 : return error;
1060 : }
1061 :
1062 0 : pCldfbRend->binaural_latency_ns = L_shr_r( Mpy_32_32_r( pCldfbRend->hHrtfFastConv->FASTCONV_latency_s_fx, (Word32) 1000000000 ), pCldfbRend->hHrtfFastConv->FASTCONV_latency_s_Q_fx );
1063 0 : move32();
1064 0 : hBinRenderer->hReverb = NULL;
1065 0 : move32();
1066 0 : hBinRenderer->hEFAPdata = NULL;
1067 0 : move32();
1068 0 : pCldfbRend->hCldfbRend = hBinRenderer;
1069 0 : move32();
1070 :
1071 0 : return IVAS_ERR_OK;
1072 : }
1073 :
1074 :
1075 : /*-------------------------------------------------------------------------
1076 : * ivas_binRenderer_open()
1077 : *
1078 : * Open fastconv binaural renderer handle
1079 : *-------------------------------------------------------------------------*/
1080 :
1081 355 : ivas_error ivas_binRenderer_open_fx(
1082 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
1083 : )
1084 : {
1085 : BINAURAL_RENDERER_HANDLE hBinRenderer;
1086 : Word16 convBand, k;
1087 : ivas_error error;
1088 : const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
1089 :
1090 : /*-----------------------------------------------------------------*
1091 : * prepare library opening
1092 : *-----------------------------------------------------------------*/
1093 :
1094 355 : IF( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL )
1095 : {
1096 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Renderer\n" ) );
1097 : }
1098 :
1099 355 : hBinRenderer->hInputSetup = &st_ivas->hIntSetup;
1100 :
1101 : /* Define of head rotation has to be done in binRendeder in CLDFB*/
1102 355 : hBinRenderer->rotInCldfb = 0;
1103 355 : move16();
1104 :
1105 355 : test();
1106 355 : test();
1107 355 : IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) || EQ_32( st_ivas->ivas_format, SBA_FORMAT ) || EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) )
1108 : {
1109 355 : hBinRenderer->rotInCldfb = 1;
1110 355 : move16();
1111 : }
1112 :
1113 355 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
1114 : {
1115 0 : hBinRenderer->numPoses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
1116 0 : move16();
1117 : }
1118 : ELSE
1119 : {
1120 355 : hBinRenderer->numPoses = 1;
1121 355 : move16();
1122 : }
1123 :
1124 : /* Declare some common variables needed for renderer */
1125 : /* Which format used for binaural rendering (needed for late reverb) ? MC or SBA */
1126 355 : IF( st_ivas->hIntSetup.is_loudspeaker_setup )
1127 : {
1128 147 : hBinRenderer->ivas_format = MC_FORMAT;
1129 147 : move32();
1130 : }
1131 : ELSE
1132 : {
1133 208 : hBinRenderer->ivas_format = SBA_FORMAT;
1134 208 : move32();
1135 : }
1136 355 : hBinRenderer->max_band = extract_l( Mpy_32_32( Mpy_32_32( BINAURAL_MAXBANDS_Q25, L_shl( st_ivas->hDecoderConfig->output_Fs, Q6 ) ), ONE_BY_48000_Q31 ) );
1137 355 : move16();
1138 :
1139 355 : convBand = hBinRenderer->max_band;
1140 355 : move16();
1141 :
1142 355 : hBinRenderer->timeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; /* Corresponds to 5 msec sound to motion latency */
1143 355 : move16();
1144 :
1145 355 : IF( GT_16( convBand, BINAURAL_CONVBANDS ) )
1146 : {
1147 227 : hBinRenderer->conv_band = BINAURAL_CONVBANDS;
1148 227 : move16();
1149 : }
1150 : ELSE
1151 : {
1152 128 : hBinRenderer->conv_band = convBand;
1153 128 : move16();
1154 : }
1155 :
1156 : /*LFE rendering switched off by default*/
1157 355 : hBinRenderer->render_lfe = 0;
1158 355 : move16();
1159 :
1160 355 : test();
1161 355 : if ( NE_32( st_ivas->ivas_format, ISM_FORMAT ) && st_ivas->hIntSetup.is_loudspeaker_setup )
1162 : {
1163 147 : hBinRenderer->render_lfe = 1;
1164 147 : move16();
1165 : }
1166 :
1167 355 : test();
1168 355 : IF( st_ivas->hHrtfFastConv == NULL && st_ivas->hDecoderConfig->Opt_HRTF_binary )
1169 : {
1170 0 : return IVAS_ERROR( IVAS_ERR_INTERNAL, "HRTF binary file present but not used in FastConv renderer" );
1171 : }
1172 :
1173 : /* Load HRTF tables */
1174 355 : IF( NE_32( ( error = ivas_binaural_hrtf_open_fx( &st_ivas->hHrtfFastConv, st_ivas->hIntSetup.output_config, st_ivas->renderer_type ) ), IVAS_ERR_OK ) )
1175 : {
1176 0 : return error;
1177 : }
1178 :
1179 355 : test();
1180 355 : IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) && ( st_ivas->hIntSetup.is_loudspeaker_setup == 0 ) )
1181 7 : {
1182 : IVAS_OUTPUT_SETUP out_setup;
1183 :
1184 : /* Allocate memories and buffers needed for convolutional module in CICP19 */
1185 7 : IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, IVAS_AUDIO_CONFIG_7_1_4, st_ivas->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) )
1186 : {
1187 0 : return error;
1188 : }
1189 7 : ivas_output_init( &out_setup, IVAS_AUDIO_CONFIG_7_1_4 );
1190 :
1191 7 : IF( st_ivas->hoa_dec_mtx == NULL )
1192 : {
1193 7 : IF( NE_32( ( error = ivas_sba_get_hoa_dec_matrix_fx( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ), IVAS_ERR_OK ) )
1194 : {
1195 0 : return error;
1196 : }
1197 : }
1198 :
1199 7 : hBinRenderer->hoa_dec_mtx = st_ivas->hoa_dec_mtx;
1200 7 : move32();
1201 7 : st_ivas->binaural_latency_ns = L_shr_r( Mpy_32_32_r( st_ivas->hHrtfFastConv->FASTCONV_latency_s_fx, (Word32) 1000000000 ), st_ivas->hHrtfFastConv->FASTCONV_latency_s_Q_fx );
1202 : }
1203 : ELSE
1204 : {
1205 : /* Allocate memories and buffers needed for convolutional module */
1206 348 : IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) )
1207 : {
1208 0 : return error;
1209 : }
1210 :
1211 348 : st_ivas->binaural_latency_ns = L_shr_r( Mpy_32_32_r( st_ivas->hHrtfFastConv->FASTCONV_latency_s_fx, (Word32) 1000000000 ), st_ivas->hHrtfFastConv->FASTCONV_latency_s_Q_fx );
1212 : }
1213 :
1214 : /* Allocate memories needed for reverb module */
1215 355 : test();
1216 355 : IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) && EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) )
1217 : {
1218 193 : pRoomAcoustics = NULL;
1219 193 : IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
1220 : {
1221 123 : pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
1222 : }
1223 :
1224 193 : IF( NE_32( ( error = ivas_binaural_reverb_init_fx( &( hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, hBinRenderer->conv_band, hBinRenderer->timeSlots, pRoomAcoustics, st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv->fastconvReverberationTimes_fx, st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections_fx, NULL ) ), IVAS_ERR_OK ) )
1225 : {
1226 0 : return error;
1227 : }
1228 : }
1229 : ELSE
1230 : {
1231 162 : hBinRenderer->hReverb = NULL;
1232 : }
1233 :
1234 355 : hBinRenderer->hEFAPdata = NULL;
1235 :
1236 355 : IF( hBinRenderer->hReverb != NULL && NE_16( hBinRenderer->nInChannels, HOA3_CHANNELS ) )
1237 : {
1238 126 : test();
1239 126 : test();
1240 126 : IF( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 )
1241 : {
1242 84 : FOR( k = 0; k < 11; k++ )
1243 : {
1244 77 : ivas_dirac_dec_get_response_fx( extract_l( L_shr_r( ls_azimuth_CICP19_fx[k], 22 ) ), extract_l( L_shr_r( ls_elevation_CICP19_fx[k], 22 ) ), hBinRenderer->hReverb->foa_enc_fx[k], 1, Q29 );
1245 : // Q29: hBinRenderer->hReverb->foa_enc_fx[k]
1246 : }
1247 : }
1248 119 : ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) )
1249 : {
1250 2 : IF( NE_32( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) )
1251 : {
1252 0 : return error;
1253 : }
1254 :
1255 : /* Copy handles to bin renderer handle*/
1256 2 : hBinRenderer->hEFAPdata = st_ivas->hEFAPdata;
1257 : }
1258 : }
1259 :
1260 : /* Copy the handles to main handle */
1261 355 : st_ivas->hBinRenderer = hBinRenderer;
1262 :
1263 355 : return IVAS_ERR_OK;
1264 : }
1265 :
1266 :
1267 : /*-------------------------------------------------------------------------
1268 : * ivas_binRenderer_convModuleClose()
1269 : *
1270 : * Close convolution module handle of fastconv binaural renderer
1271 : *------------------------------------------------------------------------*/
1272 :
1273 355 : static void ivas_binRenderer_convModuleClose_fx(
1274 : BINAURAL_RENDERER_HANDLE *hBinRenderer, /* i/o: fastconv binaural renderer handle */
1275 : const Word16 num_poses /* i : number of poses */
1276 : )
1277 : {
1278 : Word16 bandIdx, chIdx;
1279 : Word16 posIdx;
1280 :
1281 : BINRENDERER_CONV_MODULE_HANDLE_FX hBinRenConvModule;
1282 :
1283 355 : hBinRenConvModule = ( *hBinRenderer )->hBinRenConvModule;
1284 :
1285 355 : IF( hBinRenConvModule == NULL )
1286 : {
1287 0 : return;
1288 : }
1289 :
1290 15105 : FOR( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ )
1291 : {
1292 14750 : free( hBinRenConvModule->filterTapsLeftReal_fx[bandIdx] );
1293 14750 : hBinRenConvModule->filterTapsLeftReal_fx[bandIdx] = NULL;
1294 :
1295 14750 : free( hBinRenConvModule->filterTapsLeftImag_fx[bandIdx] );
1296 14750 : hBinRenConvModule->filterTapsLeftImag_fx[bandIdx] = NULL;
1297 :
1298 14750 : free( hBinRenConvModule->filterTapsRightReal_fx[bandIdx] );
1299 14750 : hBinRenConvModule->filterTapsRightReal_fx[bandIdx] = NULL;
1300 :
1301 14750 : free( hBinRenConvModule->filterTapsRightImag_fx[bandIdx] );
1302 14750 : hBinRenConvModule->filterTapsRightImag_fx[bandIdx] = NULL;
1303 : }
1304 :
1305 355 : free( hBinRenConvModule->filterTapsLeftReal_fx );
1306 355 : hBinRenConvModule->filterTapsLeftReal_fx = NULL;
1307 :
1308 355 : free( hBinRenConvModule->filterTapsLeftImag_fx );
1309 355 : hBinRenConvModule->filterTapsLeftImag_fx = NULL;
1310 :
1311 355 : free( hBinRenConvModule->filterTapsRightReal_fx );
1312 355 : hBinRenConvModule->filterTapsRightReal_fx = NULL;
1313 :
1314 355 : free( hBinRenConvModule->filterTapsRightImag_fx );
1315 355 : hBinRenConvModule->filterTapsRightImag_fx = NULL;
1316 :
1317 710 : FOR( posIdx = 0; posIdx < num_poses; posIdx++ )
1318 : {
1319 15105 : FOR( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ )
1320 : {
1321 190730 : FOR( chIdx = 0; chIdx < ( *hBinRenderer )->nInChannels; chIdx++ )
1322 : {
1323 175980 : free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx][chIdx] );
1324 175980 : hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx][chIdx] = NULL;
1325 :
1326 175980 : free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx][chIdx] );
1327 175980 : hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx][chIdx] = NULL;
1328 : }
1329 :
1330 14750 : free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx] );
1331 14750 : hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx] = NULL;
1332 :
1333 14750 : free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx] );
1334 14750 : hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx] = NULL;
1335 : }
1336 355 : free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx] );
1337 355 : hBinRenConvModule->filterStatesLeftReal_fx[posIdx] = NULL;
1338 :
1339 355 : free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx] );
1340 355 : hBinRenConvModule->filterStatesLeftImag_fx[posIdx] = NULL;
1341 : }
1342 355 : free( hBinRenConvModule->filterStatesLeftReal_fx );
1343 355 : hBinRenConvModule->filterStatesLeftReal_fx = NULL;
1344 :
1345 355 : free( hBinRenConvModule->filterStatesLeftImag_fx );
1346 355 : hBinRenConvModule->filterStatesLeftImag_fx = NULL;
1347 :
1348 355 : free( hBinRenConvModule->Q_filterStates );
1349 355 : hBinRenConvModule->Q_filterStates = NULL;
1350 :
1351 355 : free( ( *hBinRenderer )->hBinRenConvModule );
1352 355 : ( *hBinRenderer )->hBinRenConvModule = NULL;
1353 :
1354 355 : return;
1355 : }
1356 :
1357 :
1358 : /*-------------------------------------------------------------------------
1359 : * ivas_binRenderer_close()
1360 : *
1361 : * Close fastconv binaural renderer memories
1362 : *------------------------------------------------------------------------*/
1363 :
1364 935 : void ivas_binRenderer_close_fx(
1365 : BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: fastconv binaural renderer handle */
1366 : )
1367 : {
1368 935 : test();
1369 935 : IF( hBinRenderer == NULL || *hBinRenderer == NULL )
1370 : {
1371 580 : return;
1372 : }
1373 :
1374 355 : IF( ( *hBinRenderer )->hBinRenConvModule != NULL )
1375 : {
1376 355 : ivas_binRenderer_convModuleClose_fx( hBinRenderer, ( *hBinRenderer )->numPoses );
1377 : }
1378 :
1379 355 : IF( ( *hBinRenderer )->hReverb != NULL )
1380 : {
1381 193 : ivas_binaural_reverb_close_fx( &( ( *hBinRenderer )->hReverb ) );
1382 : }
1383 :
1384 355 : free( *hBinRenderer );
1385 355 : *hBinRenderer = NULL;
1386 :
1387 355 : return;
1388 : }
1389 :
1390 :
1391 : /*-------------------------------------------------------------------------
1392 : * ivas_free_pppHrtfMem()
1393 : *
1394 : * Free fastconv binaural renderer hrtf memories
1395 : *------------------------------------------------------------------------*/
1396 :
1397 456 : static void ivas_free_pppHrtfMem_fx(
1398 : Word32 ****ppppHRIR, /*Qx*/
1399 : const Word16 dim,
1400 : const Word16 alloc_init )
1401 : {
1402 : Word16 i, j;
1403 :
1404 456 : IF( *ppppHRIR != NULL )
1405 : {
1406 23256 : FOR( i = 0; i < BINAURAL_CONVBANDS; i++ )
1407 : {
1408 22800 : IF( alloc_init == 0 )
1409 : {
1410 382400 : FOR( j = 0; j < dim; j++ )
1411 : {
1412 359600 : free( ( *ppppHRIR )[i][j] );
1413 359600 : ( *ppppHRIR )[i][j] = NULL;
1414 : }
1415 : }
1416 22800 : free( ( *ppppHRIR )[i] );
1417 22800 : ( *ppppHRIR )[i] = NULL;
1418 : }
1419 456 : free( *ppppHRIR );
1420 456 : *ppppHRIR = NULL;
1421 : }
1422 :
1423 456 : return;
1424 : }
1425 :
1426 :
1427 : /*-------------------------------------------------------------------------
1428 : * ivas_binaural_hrtf_close()
1429 : *
1430 : * Close fastconv binaural renderer hrtf memories
1431 : *------------------------------------------------------------------------*/
1432 :
1433 1442 : void ivas_binaural_hrtf_close_fx(
1434 : HRTFS_FASTCONV_HANDLE *hHrtfFastConv /* i : fastconv HRTF handle */
1435 : )
1436 : {
1437 : Word16 allocate_init_flag;
1438 : Word16 n_channels;
1439 :
1440 1442 : test();
1441 1442 : IF( hHrtfFastConv == NULL || *hHrtfFastConv == NULL )
1442 : {
1443 1328 : return;
1444 : }
1445 :
1446 114 : allocate_init_flag = ( *hHrtfFastConv )->allocate_init_flag;
1447 114 : move16();
1448 :
1449 114 : n_channels = ( *hHrtfFastConv )->n_channels;
1450 114 : move16();
1451 :
1452 114 : ivas_free_pppHrtfMem_fx( &( *hHrtfFastConv )->leftReal_fx, n_channels, allocate_init_flag );
1453 114 : ivas_free_pppHrtfMem_fx( &( *hHrtfFastConv )->leftImag_fx, n_channels, allocate_init_flag );
1454 114 : ivas_free_pppHrtfMem_fx( &( *hHrtfFastConv )->rightReal_fx, n_channels, allocate_init_flag );
1455 114 : ivas_free_pppHrtfMem_fx( &( *hHrtfFastConv )->rightImag_fx, n_channels, allocate_init_flag );
1456 :
1457 114 : return;
1458 : }
1459 :
1460 :
1461 : /*-------------------------------------------------------------------------*
1462 : * ivas_binaural_add_LFE()
1463 : *
1464 : * The functions adds the LFE to the left and right channels after binaural rendering
1465 : *-------------------------------------------------------------------------*/
1466 :
1467 16761 : void ivas_binaural_add_LFE_fx(
1468 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
1469 : Word16 output_frame, /* i : length of input frame */
1470 : Word32 *input_fx[], /* i : transport channels Q11*/
1471 : Word32 *output_fx[] /* o : synthesized core-coder transport channels/DirAC output Q11*/
1472 : )
1473 : {
1474 : Word16 render_lfe, idx_lfe, gain_fx, idx;
1475 : Word32 lfe_tc[L_FRAME48k];
1476 :
1477 16761 : IF( st_ivas->hBinRenderer != NULL )
1478 : {
1479 160 : render_lfe = st_ivas->hBinRenderer->render_lfe;
1480 160 : move16();
1481 : }
1482 : ELSE
1483 : {
1484 16601 : render_lfe = TRUE;
1485 16601 : move16();
1486 : }
1487 :
1488 :
1489 16761 : IF( render_lfe )
1490 : {
1491 16761 : IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) )
1492 : {
1493 3144 : gain_fx = GAIN_LFE_FX;
1494 3144 : move16();
1495 : }
1496 : ELSE
1497 : {
1498 13617 : test();
1499 13617 : IF( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hHrtfCrend != NULL ) )
1500 : {
1501 13456 : gain_fx = st_ivas->hCrendWrapper->hHrtfCrend->gain_lfe_fx;
1502 13456 : move16();
1503 : }
1504 : ELSE
1505 : {
1506 161 : gain_fx = GAIN_LFE_FX;
1507 161 : move16();
1508 : }
1509 : }
1510 33372 : FOR( idx_lfe = 0; idx_lfe < st_ivas->hIntSetup.num_lfe; idx_lfe++ )
1511 : {
1512 16611 : v_multc_fx_16( input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain_fx, lfe_tc, output_frame ); // q_input_fx - 1
1513 :
1514 : /* copy LFE to left and right channels */
1515 14805171 : FOR( idx = 0; idx < output_frame; idx++ )
1516 : {
1517 14788560 : lfe_tc[idx] = L_shl_sat( lfe_tc[idx], 1 ); // saturating to keep same q
1518 14788560 : move32();
1519 14788560 : output_fx[0][idx] = L_add_sat( output_fx[0][idx], lfe_tc[idx] );
1520 14788560 : move32();
1521 14788560 : output_fx[1][idx] = L_add_sat( output_fx[1][idx], lfe_tc[idx] );
1522 14788560 : move32();
1523 : }
1524 : }
1525 : }
1526 :
1527 16761 : return;
1528 : }
1529 :
1530 :
1531 : /*-------------------------------------------------------------------------
1532 : * ivas_binRenderer_fx()
1533 : *
1534 : * Fastconv binaural renderer main function
1535 : *-------------------------------------------------------------------------*/
1536 :
1537 161174 : void ivas_binRenderer_fx(
1538 : BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */
1539 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
1540 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle*/
1541 : const Word16 numTimeSlots, /* i : number of time slots to render */
1542 : Word32 Cldfb_RealBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */
1543 : Word32 Cldfb_ImagBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */
1544 : Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/
1545 : Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/
1546 : Word16 *Q_in /* i : LS signals exp */
1547 : )
1548 : {
1549 : Word16 chIdx, i, j, k;
1550 : Word16 pos_idx, num_poses;
1551 : Word32 RealBuffer_local[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1552 : Word32 ImagBuffer_local[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1553 :
1554 161174 : push_wmops( "fastconv_binaural_rendering" );
1555 :
1556 161174 : num_poses = hBinRenderer->numPoses;
1557 :
1558 : /* Compute Convolution */
1559 : /* memory reset for the binaural output */
1560 :
1561 : /* Note: on main, this nested for loop was removed under a "bit-exact optimization" under switch OPT_SBA_DEC_V2_BE */
1562 : /* this was found to clash with split rendering, so kept here. WMOPS impact should be assessed */
1563 2436422 : FOR( chIdx = 0; chIdx < hBinRenderer->hInputSetup->nchan_out_woLFE; chIdx++ )
1564 : {
1565 11366624 : FOR( k = 0; k < numTimeSlots; k++ )
1566 : {
1567 9091376 : Copy32( RealBuffer_fx[chIdx][k], RealBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX );
1568 9091376 : Copy32( ImagBuffer_fx[chIdx][k], ImagBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX );
1569 : }
1570 : }
1571 :
1572 : /* Head rotation in HOA3 or CICPx */
1573 161174 : test();
1574 161174 : test();
1575 161174 : IF( hCombinedOrientationData != NULL && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] && hBinRenderer->rotInCldfb )
1576 : {
1577 64111 : IF( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 )
1578 : {
1579 : /* Rotation in SHD (HOA3) */
1580 56111 : IF( EQ_16( hCombinedOrientationData->shd_rot_max_order, -1 ) )
1581 : {
1582 18911 : rotateFrame_shd_cldfb_fx( RealBuffer_fx, ImagBuffer_fx, hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 );
1583 18911 : *Q_in = sub( *Q_in, 1 ); //( Q_in + 14 - 15 )
1584 18911 : move16();
1585 : }
1586 37200 : ELSE IF( hCombinedOrientationData->shd_rot_max_order > 0 )
1587 : {
1588 400 : rotateFrame_shd_cldfb_fx( RealBuffer_fx, ImagBuffer_fx, hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, hCombinedOrientationData->shd_rot_max_order );
1589 400 : *Q_in = sub( *Q_in, 1 ); //( Q_in + 14 - 15 )
1590 400 : move16();
1591 : }
1592 : }
1593 : ELSE
1594 : {
1595 : /* Rotation in SD (CICPx) */
1596 8000 : rotateFrame_sd_cldfb_fx( hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx], RealBuffer_fx, ImagBuffer_fx,
1597 8000 : hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band );
1598 : }
1599 : }
1600 :
1601 : /* HOA decoding to CICP19 if needed*/
1602 161174 : test();
1603 161174 : test();
1604 161174 : test();
1605 161174 : IF( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 &&
1606 : ( NE_16( hBinRenderer->nInChannels, HOA3_CHANNELS ) && NE_16( hBinRenderer->nInChannels, HOA2_CHANNELS ) && NE_16( hBinRenderer->nInChannels, FOA_CHANNELS ) ) )
1607 : {
1608 27996 : ivas_sba2mc_cldfb_fx( *( hBinRenderer->hInputSetup ), RealBuffer_fx, ImagBuffer_fx,
1609 27996 : hBinRenderer->nInChannels, hBinRenderer->conv_band, numTimeSlots, hBinRenderer->hoa_dec_mtx );
1610 : }
1611 :
1612 161174 : ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_fx[0], Cldfb_ImagBuffer_Binaural_fx[0], RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, 0, *Q_in );
1613 :
1614 161174 : IF( pMultiBinPoseData != NULL )
1615 : {
1616 0 : IF( GT_16( pMultiBinPoseData->num_poses, 1 ) )
1617 : {
1618 : IVAS_QUATERNION Quaternions_abs, Quaternions_ref, Quaternions_ref2;
1619 : Word32 Rmat_local[3][3];
1620 : Word16 q_fact_orig;
1621 :
1622 0 : IF( hCombinedOrientationData && hBinRenderer->rotInCldfb )
1623 : {
1624 0 : Quaternions_ref = hCombinedOrientationData->Quaternions[0];
1625 0 : q_fact_orig = Quaternions_ref.q_fact;
1626 :
1627 0 : modify_Quat_q_fx( &Quaternions_ref, &Quaternions_ref, Q22 );
1628 :
1629 0 : Quaternions_ref2.w_fx = L_negate( 12582912 ); // Q22
1630 0 : IF( EQ_16( hCombinedOrientationData->shd_rot_max_order, 0 ) )
1631 : {
1632 : /*HOA signal already rotated by DirAC*/
1633 0 : Quaternions_ref2.x_fx = 0;
1634 0 : Quaternions_ref2.y_fx = 0;
1635 0 : Quaternions_ref2.z_fx = 0;
1636 0 : *Q_in = sub( *Q_in, 1 );
1637 : }
1638 : ELSE
1639 : {
1640 : /*euler*/
1641 0 : Quat2EulerDegree_fx( Quaternions_ref, &Quaternions_ref2.z_fx, &Quaternions_ref2.y_fx, &Quaternions_ref2.x_fx ); /*order in Quat2Euler seems to be reversed ?*/
1642 : }
1643 :
1644 0 : FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
1645 : {
1646 0 : FOR( chIdx = 0; chIdx < hBinRenderer->hInputSetup->nchan_out_woLFE; chIdx++ )
1647 : {
1648 0 : FOR( k = 0; k < numTimeSlots; k++ )
1649 : {
1650 0 : Copy32( RealBuffer_local[chIdx][k], RealBuffer_fx[chIdx][k], CLDFB_NO_CHANNELS_MAX );
1651 0 : Copy32( ImagBuffer_local[chIdx][k], ImagBuffer_fx[chIdx][k], CLDFB_NO_CHANNELS_MAX );
1652 : }
1653 : }
1654 :
1655 0 : Quaternions_abs.x_fx = L_add( Quaternions_ref2.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
1656 0 : Quaternions_abs.y_fx = L_add( Quaternions_ref2.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
1657 0 : Quaternions_abs.z_fx = L_add( Quaternions_ref2.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
1658 0 : Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22
1659 :
1660 0 : Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs );
1661 :
1662 0 : modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig );
1663 :
1664 0 : QuatToRotMat_fx( Quaternions_abs, Rmat_local );
1665 :
1666 0 : modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( q_fact_orig, 1 ), 32 ), Q30 );
1667 :
1668 0 : IF( hBinRenderer->hInputSetup->is_loudspeaker_setup )
1669 : {
1670 0 : rotateFrame_sd_cldfb_fx( Rmat_local, RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band );
1671 : }
1672 : ELSE
1673 : {
1674 0 : rotateFrame_shd_cldfb_fx( RealBuffer_fx, ImagBuffer_fx, Rmat_local, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, hBinRenderer->hInputSetup->ambisonics_order );
1675 : }
1676 :
1677 0 : ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_fx[pos_idx], Cldfb_ImagBuffer_Binaural_fx[pos_idx], RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, pos_idx, *Q_in );
1678 : }
1679 : }
1680 : }
1681 : }
1682 :
1683 : /* Obtain the binaural dmx and compute the reverb */
1684 161174 : IF( hBinRenderer->hReverb != NULL )
1685 : {
1686 : Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
1687 : Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
1688 : Word32 inRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
1689 : Word32 inIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
1690 : Word16 shift_q;
1691 : Word16 q_in_out;
1692 104850 : q_in_out = *Q_in;
1693 :
1694 104850 : ivas_binaural_obtain_DMX_fx( numTimeSlots, hBinRenderer, RealBuffer_fx, ImagBuffer_fx, inRe_fx, inIm_fx, &q_in_out );
1695 :
1696 314550 : FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
1697 : {
1698 1047298 : FOR( k = 0; k < numTimeSlots; k++ )
1699 : {
1700 837598 : set32_fx( reverbRe_fx[chIdx][k], 0, hBinRenderer->max_band );
1701 837598 : set32_fx( reverbIm_fx[chIdx][k], 0, hBinRenderer->max_band );
1702 : }
1703 : }
1704 :
1705 104850 : ivas_binaural_reverb_processSubframe_fx( hBinRenderer->hReverb, BINAURAL_CHANNELS, numTimeSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx );
1706 104850 : shift_q = sub( Q6, q_in_out );
1707 314550 : FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
1708 : {
1709 1047298 : FOR( j = 0; j < numTimeSlots; j++ )
1710 : {
1711 37719038 : FOR( k = 0; k < hBinRenderer->hReverb->numBins; k++ )
1712 : {
1713 36881440 : reverbRe_fx[i][j][k] = L_shl( reverbRe_fx[i][j][k], shift_q ); // Q6
1714 36881440 : move32();
1715 36881440 : reverbIm_fx[i][j][k] = L_shl( reverbIm_fx[i][j][k], shift_q ); // Q6
1716 36881440 : move32();
1717 : }
1718 : }
1719 : }
1720 :
1721 : /* Add the conv module and reverb module output */
1722 314550 : FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ )
1723 : {
1724 1047298 : FOR( k = 0; k < numTimeSlots; k++ )
1725 : {
1726 1675196 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
1727 : {
1728 : /* Combine first and second parts to generate binaural output signal with room effect */
1729 837598 : v_add_32( Cldfb_RealBuffer_Binaural_fx[pos_idx][chIdx][k], reverbRe_fx[chIdx][k], Cldfb_RealBuffer_Binaural_fx[pos_idx][chIdx][k], hBinRenderer->conv_band ); // Q6
1730 837598 : v_add_32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][chIdx][k], reverbIm_fx[chIdx][k], Cldfb_ImagBuffer_Binaural_fx[pos_idx][chIdx][k], hBinRenderer->conv_band ); // Q6
1731 : }
1732 : }
1733 : }
1734 : }
1735 :
1736 161174 : Word16 len = sub( CLDFB_NO_CHANNELS_MAX, hBinRenderer->conv_band );
1737 :
1738 322348 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
1739 : {
1740 805269 : FOR( k = 0; k < numTimeSlots; k++ )
1741 : {
1742 644095 : set32_fx( &Cldfb_RealBuffer_Binaural_fx[pos_idx][0][k][hBinRenderer->conv_band], 0, len );
1743 644095 : set32_fx( &Cldfb_RealBuffer_Binaural_fx[pos_idx][1][k][hBinRenderer->conv_band], 0, len );
1744 644095 : set32_fx( &Cldfb_ImagBuffer_Binaural_fx[pos_idx][0][k][hBinRenderer->conv_band], 0, len );
1745 644095 : set32_fx( &Cldfb_ImagBuffer_Binaural_fx[pos_idx][1][k][hBinRenderer->conv_band], 0, len );
1746 : }
1747 : }
1748 :
1749 161174 : pop_wmops();
1750 161174 : return;
1751 : }
1752 :
1753 :
1754 : /*-------------------------------------------------------------------------
1755 : * ivas_rend_CldfbMultiBinRendProcess()
1756 : *
1757 : *
1758 : *-------------------------------------------------------------------------*/
1759 :
1760 0 : void ivas_rend_CldfbMultiBinRendProcess(
1761 : const BINAURAL_RENDERER_HANDLE hCldfbRend,
1762 : const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData,
1763 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
1764 : Word32 Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
1765 : Word32 Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
1766 : Word32 Cldfb_Out_Real[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */
1767 : Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
1768 : const Word16 low_res_pre_rend_rot,
1769 : const Word16 num_subframes,
1770 : const Word16 Q_in /* i : LS signals exp */
1771 : )
1772 : {
1773 : Word16 slot_idx, ch_idx, idx, pose_idx, i, j;
1774 : Word16 sf_idx;
1775 : Word32 Cldfb_RealBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1776 : Word32 Cldfb_ImagBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1777 : Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1778 : Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX];
1779 : Word16 Q_in_orig;
1780 :
1781 0 : FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ )
1782 : {
1783 0 : Q_in_orig = Q_in;
1784 0 : move16();
1785 0 : FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ )
1786 : {
1787 0 : idx = sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES + slot_idx;
1788 0 : FOR( ch_idx = 0; ch_idx < hCldfbRend->nInChannels; ch_idx++ )
1789 : {
1790 0 : Copy32( &Cldfb_In_Real[ch_idx][idx][0], &Cldfb_RealBuffer_sfIn[ch_idx][slot_idx][0], hCldfbRend->max_band );
1791 0 : Copy32( &Cldfb_In_Imag[ch_idx][idx][0], &Cldfb_ImagBuffer_sfIn[ch_idx][slot_idx][0], hCldfbRend->max_band );
1792 : }
1793 : }
1794 :
1795 0 : IF( ( *pCombinedOrientationData ) != NULL )
1796 : {
1797 0 : IF( ( low_res_pre_rend_rot ) && ( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) )
1798 : {
1799 0 : Copy_Quat_fx( &( *pCombinedOrientationData )->Quaternions[0], &( *pCombinedOrientationData )->Quaternions[sf_idx] );
1800 :
1801 0 : FOR( i = 0; i < 3; i++ )
1802 : {
1803 0 : FOR( j = 0; j < 3; j++ )
1804 : {
1805 0 : ( *pCombinedOrientationData )->Rmat_fx[sf_idx][i][j] = ( *pCombinedOrientationData )->Rmat_fx[0][i][j];
1806 0 : move32();
1807 : }
1808 : }
1809 : }
1810 0 : ( *pCombinedOrientationData )->shd_rot_max_order = -1;
1811 0 : move16();
1812 : }
1813 :
1814 0 : ivas_binRenderer_fx( hCldfbRend, pMultiBinPoseData, *pCombinedOrientationData, MAX_PARAM_SPATIAL_SUBFRAMES, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer_sfIn, Cldfb_ImagBuffer_sfIn, &Q_in_orig );
1815 :
1816 0 : FOR( pose_idx = 0; pose_idx < hCldfbRend->numPoses; pose_idx++ )
1817 : {
1818 0 : FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ )
1819 : {
1820 0 : idx = sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES + slot_idx;
1821 0 : FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ )
1822 : {
1823 0 : Copy32( &Cldfb_RealBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band );
1824 0 : Copy32( &Cldfb_ImagBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band );
1825 :
1826 0 : Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in, Q6 ) ); // Q_in
1827 0 : Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in, Q6 ) ); // Q_in
1828 : }
1829 : }
1830 : }
1831 : }
1832 :
1833 0 : return;
1834 : }
|