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_rom_TdBinauralRenderer.h"
38 : #include "ivas_error.h"
39 : #include "wmc_auto.h"
40 : #include "ivas_rom_rend.h"
41 : #include "ivas_prot_fx.h"
42 :
43 : /*-------------------------------------------------------------------*
44 : * Local constants
45 : *-------------------------------------------------------------------*/
46 :
47 : #define RESAMPLE_FACTOR_16_48 ( 16.0f / 48.0f )
48 : #define RESAMPLE_FACTOR_32_48 ( 32.0f / 48.0f )
49 :
50 : #define RESAMPLE_FACTOR_16_48_FX ( 5461 ) // Q14
51 : #define RESAMPLE_FACTOR_32_48_FX ( 10922 ) // Q14
52 :
53 :
54 : /*-------------------------------------------------------------------------
55 : * Local functions
56 : *-------------------------------------------------------------------------*/
57 : static ivas_error DefaultBSplineModel_fx( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, const Word32 output_Fs );
58 :
59 : /*-------------------------------------------------------------------*
60 : * TDREND_MIX_LIST_SetPos()
61 : *
62 : * Sets the listener's position in the specified mixer unit.
63 : --------------------------------------------------------------------*/
64 :
65 664495 : void TDREND_MIX_LIST_SetPos_fx(
66 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
67 : const Word32 *Pos_p /* i : Listener's position */ // Q Pos_fx->q_fact
68 : )
69 : {
70 : TDREND_MIX_Listener_t *Listener_p;
71 :
72 664495 : Listener_p = hBinRendererTd->Listener_p;
73 664495 : test();
74 664495 : test();
75 664495 : IF( NE_32( Pos_p[0], Listener_p->Pos_fx[0] ) || NE_32( Pos_p[1], Listener_p->Pos_fx[1] ) || NE_32( Pos_p[2], Listener_p->Pos_fx[2] ) )
76 : {
77 : /* Set position */
78 6688 : Copy32( Pos_p, Listener_p->Pos_fx, 3 ); // Q Pos_fx->q_fact
79 :
80 : /* Set pose update flag */
81 6688 : Listener_p->PoseUpdated = TRUE;
82 6688 : move16();
83 : }
84 :
85 664495 : return;
86 : }
87 :
88 :
89 : /*-------------------------------------------------------------------*
90 : * TDREND_MIX_LIST_SetOrient()
91 : *
92 : * Sets the listener's orientation vectors in the specified mixer unit.
93 : --------------------------------------------------------------------*/
94 :
95 664495 : ivas_error TDREND_MIX_LIST_SetOrient_fx(
96 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
97 : const Word32 *FrontVec_p_fx,
98 : /* i : Listener's orientation front vector */ // orient_q
99 : const Word32 *UpVec_p_fx,
100 : /* i : Listener's orientation up vector */ // orient_q
101 : const Word16 orient_q /* i : Listener's orientation q-factor */
102 : )
103 : {
104 :
105 : TDREND_MIX_Listener_t *List_p;
106 : /* Value verification */
107 664495 : test();
108 664495 : test();
109 664495 : IF( ( FrontVec_p_fx[0] == 0 ) && ( FrontVec_p_fx[1] == 0 ) && ( FrontVec_p_fx[2] == 0 ) )
110 : {
111 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "Zero front vector. Command is ignored!\n" ) );
112 : }
113 :
114 664495 : IF( ( UpVec_p_fx[0] == 0 ) && ( UpVec_p_fx[1] == 0 ) && ( UpVec_p_fx[2] == 0 ) )
115 : {
116 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "Zero up vector. Command is ignored!\n" ) );
117 : }
118 :
119 664495 : test();
120 664495 : test();
121 : /* Get listener */
122 664495 : List_p = hBinRendererTd->Listener_p;
123 :
124 : /* Evaluate the normalized orientation vectors and set pose update flag */
125 664495 : List_p->PoseUpdated = TDREND_SPATIAL_EvalOrthonormOrient_fx( List_p->Front_fx, List_p->Up_fx, List_p->Right_fx, FrontVec_p_fx, UpVec_p_fx, orient_q ); // Q0
126 664495 : move16();
127 :
128 664495 : return IVAS_ERR_OK;
129 : }
130 :
131 :
132 : /*-------------------------------------------------------------------*
133 : * TDREND_MIX_Dealloc()
134 : *
135 : * Deallocates the TDREND_MIX_t variable
136 : --------------------------------------------------------------------*/
137 :
138 513 : void TDREND_MIX_Dealloc_fx(
139 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */
140 : )
141 : {
142 : Word16 i;
143 :
144 : /* Deallocate source list */
145 1509 : FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ )
146 : {
147 996 : TDREND_SRC_Dealloc( hBinRendererTd->Sources[i] );
148 : }
149 : /* Deallocate Listener and RendListener */
150 513 : IF( hBinRendererTd->Listener_p != NULL )
151 : {
152 513 : free( hBinRendererTd->Listener_p );
153 513 : hBinRendererTd->Listener_p = NULL;
154 : }
155 : /* Dealloc HR filter set */
156 513 : IF( hBinRendererTd->HrFiltSet_p != NULL )
157 : {
158 513 : IF( EQ_16( hBinRendererTd->HrFiltSet_p->FilterMethod, TDREND_HRFILT_Method_BSplineModel ) )
159 : {
160 513 : BSplineModelEvalDealloc_fx( &hBinRendererTd->HrFiltSet_p->ModelParams, &hBinRendererTd->HrFiltSet_p->ModelEval );
161 : }
162 : ELSE
163 : {
164 0 : IF( hBinRendererTd->HrFiltSet_p->Elev_p_fx != NULL )
165 : {
166 0 : free( hBinRendererTd->HrFiltSet_p->Elev_p_fx );
167 0 : hBinRendererTd->HrFiltSet_p->Elev_p_fx = NULL;
168 : }
169 0 : IF( hBinRendererTd->HrFiltSet_p->Azim_p_fx != NULL )
170 : {
171 0 : free( hBinRendererTd->HrFiltSet_p->Azim_p_fx );
172 0 : hBinRendererTd->HrFiltSet_p->Azim_p_fx = NULL;
173 : }
174 0 : IF( hBinRendererTd->HrFiltSet_p->LeftFiltSet_p_fx != NULL )
175 : {
176 0 : free( hBinRendererTd->HrFiltSet_p->LeftFiltSet_p_fx );
177 0 : hBinRendererTd->HrFiltSet_p->LeftFiltSet_p_fx = NULL;
178 : }
179 0 : IF( hBinRendererTd->HrFiltSet_p->RightFiltSet_p_fx != NULL )
180 : {
181 0 : free( hBinRendererTd->HrFiltSet_p->RightFiltSet_p_fx );
182 0 : hBinRendererTd->HrFiltSet_p->RightFiltSet_p_fx = NULL;
183 : }
184 : }
185 513 : free( hBinRendererTd->HrFiltSet_p );
186 513 : hBinRendererTd->HrFiltSet_p = NULL;
187 : }
188 :
189 513 : return;
190 : }
191 :
192 :
193 : /*-------------------------------------------------------------------*
194 : * TDREND_MIX_Init()
195 : *
196 : * Initializes the mixer and sets HRTF
197 : --------------------------------------------------------------------*/
198 513 : ivas_error TDREND_MIX_Init_fx(
199 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
200 : TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HRTF data (initialized in case of NULL) */
201 : const TDREND_MixSpatSpec_t *MixSpatSpec_p, /* i : Mixer spatial specification */
202 : const Word32 output_Fs /* i : Output sampling rate */ // Q0
203 : )
204 : {
205 : ivas_error error;
206 513 : hBinRendererTd->Gain_fx = ONE_IN_Q14;
207 513 : move16();
208 : /* Init source list */
209 : /* Spatial settings */
210 513 : IF( MixSpatSpec_p != NULL )
211 : {
212 513 : hBinRendererTd->UseCommonDistAttenModel = MixSpatSpec_p->UseCommonDistAttenModel; // Q0
213 513 : move16();
214 513 : hBinRendererTd->DistAttenModel = MixSpatSpec_p->DistAttenModel; // Q0
215 513 : move16();
216 : }
217 : ELSE
218 : {
219 0 : hBinRendererTd->UseCommonDistAttenModel = TRUE; // Q0
220 0 : move16();
221 0 : hBinRendererTd->DistAttenModel = 0x0000; /* Distance attenuation not activated; */ // Q0
222 0 : move16();
223 : }
224 : /* Init virtual and rendering listeners for spatial mixers */
225 513 : TDREND_SPATIAL_VecInit_fx( hBinRendererTd->Listener_p->Pos_fx, 0, 0, 0 );
226 513 : hBinRendererTd->Listener_p->Pos_q = Q25;
227 513 : move16();
228 513 : TDREND_SPATIAL_VecInit_fx( hBinRendererTd->Listener_p->Vel_fx, 0, 0, 0 );
229 513 : TDREND_SPATIAL_VecInit_fx( hBinRendererTd->Listener_p->Front_fx, 0, 0, -ONE_IN_Q30 );
230 513 : TDREND_SPATIAL_VecInit_fx( hBinRendererTd->Listener_p->Up_fx, 0, ONE_IN_Q30, 0 );
231 513 : TDREND_SPATIAL_VecInit_fx( hBinRendererTd->Listener_p->Right_fx, ONE_IN_Q30, 0, 0 );
232 : /* Init HR filter set */
233 513 : IF( *hHrtfTD == NULL )
234 : {
235 504 : IF( ( hBinRendererTd->HrFiltSet_p = (TDREND_HRFILT_FiltSet_t *) malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ) ) == NULL )
236 : {
237 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
238 : }
239 :
240 504 : IF( NE_32( ( error = DefaultBSplineModel_fx( hBinRendererTd->HrFiltSet_p, output_Fs ) ), IVAS_ERR_OK ) )
241 : {
242 0 : return error;
243 : }
244 504 : *hHrtfTD = hBinRendererTd->HrFiltSet_p;
245 : }
246 : ELSE
247 : {
248 9 : hBinRendererTd->HrFiltSet_p = *hHrtfTD;
249 : }
250 513 : IF( NE_32( hBinRendererTd->HrFiltSet_p->SampleRate, output_Fs ) )
251 : {
252 0 : return ( IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "The sampling rate for the HR filter set does not match the output sampling rate.\n" ) );
253 : }
254 513 : return IVAS_ERR_OK;
255 : }
256 :
257 : /*-------------------------------------------------------------------*
258 : * TDREND_MIX_SetDistAttenModel()
259 : *
260 : * Set the distance attenuation model of the mixer
261 : --------------------------------------------------------------------*/
262 :
263 513 : ivas_error TDREND_MIX_SetDistAttenModel(
264 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
265 : const TDREND_DistAttenModel_t DistAttenModel /* i : Distance attenuation model */
266 : )
267 : {
268 : /* Value validation */
269 513 : test();
270 513 : IF( LT_16( DistAttenModel, TDREND_DIST_ATTEN_MODEL_INV_DIST ) || GT_16( DistAttenModel, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) )
271 : {
272 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid distance attenuation model!\n" ) );
273 : }
274 : ELSE
275 : {
276 : /* Set the common distance attenuation model */
277 513 : hBinRendererTd->DistAttenModel = DistAttenModel; // Q0
278 513 : move32();
279 :
280 : /* If using common distance attenuation model, set it. */
281 513 : IF( hBinRendererTd->UseCommonDistAttenModel )
282 : {
283 513 : hBinRendererTd->DistAttenEnabled = TRUE; // Q0
284 513 : move16();
285 513 : hBinRendererTd->DistAttenModel = DistAttenModel; // Q0
286 513 : move32();
287 : }
288 : }
289 513 : return IVAS_ERR_OK;
290 : }
291 :
292 :
293 : /*-------------------------------------------------------------------*
294 : * TDREND_MIX_AddSrc()
295 : *
296 : * Adds the specified input source unit to the specified mixer unit.
297 : --------------------------------------------------------------------*/
298 996 : ivas_error TDREND_MIX_AddSrc_fx(
299 : BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */
300 : Word16 *SrcInd,
301 : /* o : Source index */ // Q0
302 : const TDREND_PosType_t PosType /* i : Position type (absolute/relative) */
303 : )
304 : {
305 : TDREND_SRC_t *Src_p;
306 : ivas_error error;
307 :
308 996 : error = IVAS_ERR_OK;
309 996 : move32();
310 : /* Get unique source index */
311 996 : *SrcInd = add( hBinRendererTd->MaxSrcInd, 1 ); // Q0
312 996 : move16();
313 996 : hBinRendererTd->MaxSrcInd = add( hBinRendererTd->MaxSrcInd, 1 ); // Q0
314 996 : move16();
315 996 : hBinRendererTd->NumOfSrcs = add( hBinRendererTd->NumOfSrcs, 1 ); // Q0
316 996 : move16();
317 :
318 996 : IF( GT_16( hBinRendererTd->NumOfSrcs, MAX_NUM_TDREND_CHANNELS ) )
319 : {
320 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "Maximum number of sources exceeded!\n" ) );
321 : }
322 : ELSE
323 : {
324 996 : test();
325 996 : IF( LT_16( PosType, TDREND_POSTYPE_ABSOLUTE ) || GT_16( PosType, TDREND_POSTYPE_NON_DIEGETIC ) )
326 : {
327 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid position type!\n" ) );
328 : }
329 : ELSE
330 : {
331 : /* Alloc and init a complete source: signal+spatial+rend components */
332 996 : IF( NE_32( ( error = TDREND_SRC_Alloc( &Src_p ) ), IVAS_ERR_OK ) )
333 : {
334 0 : return error;
335 : }
336 :
337 996 : TDREND_SRC_Init_fx( Src_p, PosType );
338 :
339 : /* Special OpenAL initialization due to a common distance attenuation model */
340 996 : IF( NE_16( hBinRendererTd->DistAttenModel, 0 ) )
341 : {
342 996 : Src_p->SrcSpatial_p->DistAttenEnabled = TRUE; // Q0
343 996 : move16();
344 996 : Src_p->SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel; // Q0
345 996 : move32();
346 : }
347 : /* Add source to mixer */
348 996 : hBinRendererTd->Sources[*SrcInd] = Src_p;
349 : }
350 : }
351 :
352 996 : return error;
353 : }
354 :
355 : /*-------------------------------------------------------------------*
356 : * BSplineModelEvalAlloc()
357 : *
358 : * Allocate the B Spline HR Filter model.
359 : --------------------------------------------------------------------*/
360 :
361 504 : static ivas_error BSplineModelEvalAlloc_fx(
362 : ModelParams_t *model, /* i : Model parameters */
363 : ModelEval_t *modelEval /* i/o: Model evaluation structure */
364 : )
365 : {
366 504 : IF( ( modelEval->hrfModL_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ) ) == NULL )
367 : {
368 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
369 : }
370 :
371 504 : IF( ( modelEval->hrfModR_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ) ) == NULL )
372 : {
373 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
374 : }
375 :
376 504 : return IVAS_ERR_OK;
377 : }
378 :
379 :
380 : /*-------------------------------------------------------------------*
381 : * DefaultBSplineModel()
382 : *
383 : * Init default HRTF model
384 : --------------------------------------------------------------------*/
385 :
386 504 : static ivas_error DefaultBSplineModel_fx(
387 : TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* o : Loaded HR filter set */
388 : const Word32 output_Fs /* i : Output sampling rate */ // Q0
389 : )
390 : {
391 : ModelParams_t *model;
392 : ModelParamsITD_t *modelITD;
393 : Word16 i, j;
394 : ivas_error error;
395 504 : HrFiltSet_p->FilterMethod = TDREND_HRFILT_Method_BSplineModel;
396 504 : move16();
397 504 : model = &( HrFiltSet_p->ModelParams );
398 504 : modelITD = &( HrFiltSet_p->ModelParamsITD );
399 :
400 504 : SWITCH( output_Fs )
401 : {
402 487 : case 48000:
403 487 : HrFiltSet_p->lr_energy_and_iac_fx[0] = defaultHRIR_left_avg_power_48kHz_fx; // Q23
404 487 : HrFiltSet_p->lr_energy_and_iac_fx[1] = defaultHRIR_right_avg_power_48kHz_fx; // Q23
405 487 : HrFiltSet_p->lr_energy_and_iac_fx[2] = defaultHRIR_coherence_48kHz_fx; // Q23
406 487 : BREAK;
407 17 : case 32000:
408 17 : HrFiltSet_p->lr_energy_and_iac_fx[0] = defaultHRIR_left_avg_power_32kHz_fx; // Q23
409 17 : HrFiltSet_p->lr_energy_and_iac_fx[1] = defaultHRIR_right_avg_power_32kHz_fx; // Q23
410 17 : HrFiltSet_p->lr_energy_and_iac_fx[2] = defaultHRIR_coherence_32kHz_fx; // Q23
411 17 : BREAK;
412 0 : case 16000:
413 0 : HrFiltSet_p->lr_energy_and_iac_fx[0] = defaultHRIR_left_avg_power_16kHz_fx; // Q23
414 0 : HrFiltSet_p->lr_energy_and_iac_fx[1] = defaultHRIR_right_avg_power_16kHz_fx; // Q23
415 0 : HrFiltSet_p->lr_energy_and_iac_fx[2] = defaultHRIR_coherence_16kHz_fx; // Q23
416 0 : BREAK;
417 : }
418 :
419 : /* Set ROM flag for correct deallocation */
420 504 : model->modelROM = TRUE;
421 504 : move16();
422 :
423 : /* int16_t parameters */
424 504 : model->UseItdModel = 1; // Q0
425 504 : move16();
426 504 : model->SplineDegree = 4; // Q0
427 504 : move16();
428 504 : model->elevDim2 = 17; // Q0
429 504 : move16();
430 504 : model->elevDim3 = 15; // Q0
431 504 : move16();
432 504 : model->AlphaN = 470; // Q0
433 504 : move16();
434 504 : model->num_unique_azim_splines = 1; // Q0
435 504 : move16();
436 504 : model->elevSegSamples = 4; // Q0
437 504 : move16();
438 504 : model->elevBsLen[0] = 5; // Q0
439 504 : move16();
440 504 : model->elevBsLen[1] = 9; // Q0
441 504 : move16();
442 504 : model->elevBsLen[2] = 13; // Q0
443 504 : move16();
444 504 : model->elevBsLen[3] = 9; // Q0
445 504 : move16();
446 504 : model->elevBsStart[0] = 0; // Q0
447 504 : move16();
448 504 : model->elevBsStart[1] = 5; // Q0
449 504 : move16();
450 504 : model->elevBsStart[2] = 14; // Q0
451 504 : move16();
452 504 : model->elevBsStart[3] = 27; // Q0
453 504 : move16();
454 :
455 504 : model->azimDim2 = defaultHRIR_rom_azimDim2; // Q0
456 504 : model->azimDim3 = defaultHRIR_rom_azimDim3; // Q0
457 504 : model->azim_start_idx = defaultHRIR_rom_azim_start_idx; // Q0
458 504 : model->azimSegSamples = defaultHRIR_rom_azimSegSamples; // Q0
459 504 : model->azimShapeIdx = defaultHRIR_rom_azimShapeIdx; // Q0
460 504 : model->azimShapeSampFactor = defaultHRIR_rom_azimShapeSampFactor; // Q0
461 :
462 504 : model->elevKSeq_fx = defaultHRIR_rom_elevKSeq_fx; // Q22
463 504 : model->elevBsShape_fx = (const Word32 *) defaultHRIR_rom_elevBsShape_fx; // Q30
464 :
465 504 : IF( ( model->azimBsShape_fx = (const Word32 **) malloc( model->num_unique_azim_splines * sizeof( Word32 * ) ) ) == NULL )
466 : {
467 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
468 : }
469 504 : model->azimBsShape_fx[0] = defaultHRIR_rom_azimBsShape_fx; // Q30
470 504 : IF( ( model->azimKSeq_fx = (Word32 **) malloc( 18 * sizeof( Word32 * ) ) ) == NULL )
471 : {
472 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
473 : }
474 504 : IF( ( model->azimKSeq_fx[0] = (Word32 *) malloc( 2 * sizeof( Word32 * ) ) ) == NULL )
475 : {
476 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
477 : }
478 504 : IF( ( model->azimKSeq_fx[model->elevDim3 - 1] = (Word32 *) malloc( 2 * sizeof( Word32 * ) ) ) == NULL )
479 : {
480 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
481 : }
482 504 : model->azimKSeq_fx[0][0] = 0;
483 504 : model->azimKSeq_fx[model->elevDim3 - 1][0] = 0;
484 504 : model->azimKSeq_fx[0][1] = 360 << Q22; // Q22
485 504 : model->azimKSeq_fx[model->elevDim3 - 1][1] = 360 << Q22; // Q22
486 504 : move32();
487 504 : move32();
488 504 : move32();
489 504 : move32();
490 :
491 7056 : FOR( i = 1; i < sub( model->elevDim3, 1 ); i++ )
492 : {
493 6552 : IF( ( model->azimKSeq_fx[i] = (Word32 *) malloc( model->azimDim2[i] * sizeof( Word32 * ) ) ) == NULL ) /* azimDim2[i] = 91, i=2..15 */
494 : {
495 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) );
496 : }
497 248976 : FOR( j = 0; j < model->azimDim2[i]; j++ )
498 : {
499 242424 : model->azimKSeq_fx[i][j] = L_shl( L_mult0( defaultHRIR_rom_azimSegSamples[0], j ), Q22 ); // Q22
500 242424 : move32();
501 : }
502 : }
503 :
504 504 : SWITCH( output_Fs )
505 : {
506 487 : case 48000:
507 487 : model->AlphaL_fx = (const Word32 *) defaultHRIR_rom_AlphaL48_fx; // Q30
508 487 : model->AlphaL_e = 1;
509 487 : move16();
510 487 : model->AlphaR_fx = (const Word32 *) defaultHRIR_rom_AlphaR48_fx; // Q30
511 487 : model->AlphaR_e = 1;
512 487 : move16();
513 487 : model->EL_fx = (const Word32 *) defaultHRIR_rom_EL48_fx; // Q28
514 487 : model->EL_e = 3;
515 487 : move16();
516 487 : model->ER_fx = (const Word32 *) defaultHRIR_rom_ER48_fx; // Q28
517 487 : model->ER_e = 3;
518 487 : move16();
519 487 : model->K = 128; // Q0
520 487 : move16();
521 487 : IF( HrFiltSet_p->ModelParams.UseItdModel )
522 : {
523 487 : modelITD->resamp_factor_fx = ONE_IN_Q14; // Q14
524 487 : move16();
525 : }
526 487 : BREAK;
527 17 : case 32000:
528 17 : model->AlphaL_fx = (const Word32 *) defaultHRIR_rom_AlphaL32_fx; // Q30
529 17 : model->AlphaL_e = 1;
530 17 : move16();
531 17 : model->AlphaR_fx = (const Word32 *) defaultHRIR_rom_AlphaR32_fx; // Q30
532 17 : model->AlphaR_e = 1;
533 17 : move16();
534 17 : model->EL_fx = (const Word32 *) defaultHRIR_rom_EL32_fx; // Q28
535 17 : model->EL_e = 3;
536 17 : move16();
537 17 : model->ER_fx = (const Word32 *) defaultHRIR_rom_ER32_fx; // Q28
538 17 : model->ER_e = 3;
539 17 : move16();
540 17 : model->K = 86; // Q0
541 17 : move16();
542 17 : IF( HrFiltSet_p->ModelParams.UseItdModel )
543 : {
544 17 : modelITD->resamp_factor_fx = RESAMPLE_FACTOR_32_48_FX; // Q14
545 17 : move16();
546 : }
547 17 : BREAK;
548 0 : case 16000:
549 0 : model->AlphaL_fx = (const Word32 *) defaultHRIR_rom_AlphaL16_fx; // Q30
550 0 : model->AlphaL_e = 1;
551 0 : move16();
552 0 : model->AlphaR_fx = (const Word32 *) defaultHRIR_rom_AlphaR16_fx; // Q30
553 0 : model->AlphaR_e = 1;
554 0 : move16();
555 0 : model->EL_fx = (const Word32 *) defaultHRIR_rom_EL16_fx; // Q28
556 0 : model->EL_e = 3;
557 0 : move16();
558 0 : model->ER_fx = (const Word32 *) defaultHRIR_rom_ER16_fx; // Q28
559 0 : model->ER_e = 3;
560 0 : move16();
561 0 : model->K = 43; // Q0
562 0 : move16();
563 0 : IF( HrFiltSet_p->ModelParams.UseItdModel )
564 : {
565 0 : modelITD->resamp_factor_fx = RESAMPLE_FACTOR_16_48_FX; // Q14
566 0 : move16();
567 : }
568 0 : BREAK;
569 0 : default:
570 0 : BREAK;
571 : }
572 :
573 504 : modelITD->N = 4; // Q0
574 504 : move16();
575 504 : modelITD->elevDim2 = 20; // Q0
576 504 : move16();
577 504 : modelITD->elevDim3 = 18; // Q0
578 504 : move16();
579 504 : modelITD->azimDim2 = 41; // Q0
580 504 : move16();
581 504 : modelITD->azimDim3 = 41; // Q0
582 504 : move16();
583 504 : modelITD->elevSegSamples = 3; // Q0
584 504 : move16();
585 504 : modelITD->elevBsLen[0] = 4; // Q0
586 504 : move16();
587 504 : modelITD->elevBsLen[1] = 7; // Q0
588 504 : move16();
589 504 : modelITD->elevBsLen[2] = 10; // Q0
590 504 : move16();
591 504 : modelITD->elevBsLen[3] = 7; // Q0
592 504 : move16();
593 504 : modelITD->elevBsStart[0] = 0; // Q0
594 504 : move16();
595 504 : modelITD->elevBsStart[1] = 4; // Q0
596 504 : move16();
597 504 : modelITD->elevBsStart[2] = 11; // Q0
598 504 : move16();
599 504 : modelITD->elevBsStart[3] = 21; // Q0
600 504 : move16();
601 504 : modelITD->elevKSeq_fx = defaultHRIR_rom_ITD_elevKSeq_fx; // Q22
602 :
603 504 : modelITD->azimBsLen[0] = 11; // Q0
604 504 : move16();
605 504 : modelITD->azimBsLen[1] = 21; // Q0
606 504 : move16();
607 504 : modelITD->azimBsLen[2] = 31; // Q0
608 504 : move16();
609 504 : modelITD->azimBsLen[3] = 21; // Q0
610 504 : move16();
611 504 : modelITD->azimBsStart[0] = 0; // Q0
612 504 : move16();
613 504 : modelITD->azimBsStart[1] = 11; // Q0
614 504 : move16();
615 504 : modelITD->azimBsStart[2] = 32; // Q0
616 504 : move16();
617 504 : modelITD->azimBsStart[3] = 63; // Q0
618 504 : move16();
619 :
620 504 : modelITD->azimSegSamples = 10; // Q0
621 504 : move16();
622 504 : modelITD->azimKSeq_fx = defaultHRIR_rom_ITD_azimKSeq_fx; // Q22
623 504 : modelITD->W_fx = (const Word32 *) defaultHRIR_rom_ITD_W_fx; // Q25
624 504 : modelITD->W_e = 6;
625 504 : move16();
626 504 : modelITD->azimBsShape_fx = defaultHRIR_rom_ITD_azimBsShape_fx; // Q30
627 504 : modelITD->elevBsShape_fx = defaultHRIR_rom_ITD_elevBsShape_fx; // Q30
628 :
629 504 : HRTF_model_precalc( model );
630 :
631 504 : HrFiltSet_p->latency_s_fx = defaultHRIR_rom_latency_s_fx; // Q31
632 504 : move32();
633 504 : HrFiltSet_p->SampleRate = output_Fs; // Q0
634 504 : move32();
635 504 : HrFiltSet_p->FiltLength = HrFiltSet_p->ModelParams.K; // Q0
636 504 : move16();
637 :
638 504 : IF( NE_32( ( error = BSplineModelEvalAlloc_fx( &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ) ), IVAS_ERR_OK ) )
639 : {
640 0 : return error;
641 : }
642 :
643 504 : return IVAS_ERR_OK;
644 : }
|