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 <assert.h>
34 : #include <stdint.h>
35 : #include <math.h>
36 : #include "options.h"
37 : #include "ivas_cnst.h"
38 : #include "ivas_rom_com.h"
39 : #include "prot_fx.h"
40 : #include "cnst.h"
41 : #include "wmc_auto.h"
42 : #include "ivas_prot_fx.h"
43 :
44 :
45 : /*-----------------------------------------------------------------------*
46 : * Local constants
47 : *-----------------------------------------------------------------------*/
48 :
49 : #define MASA_DIR_RATIO_COMP_MAX_IDX_STEPS 2
50 :
51 : /*-----------------------------------------------------------------------*
52 : * Local function prototypes
53 : *-----------------------------------------------------------------------*/
54 :
55 : static void ivas_qmetadata_free_memory_fx( IVAS_QMETADATA_HANDLE hQMetaData );
56 :
57 :
58 : /*-----------------------------------------------------------------------*
59 : * ivas_qmetadata_open()
60 : *
61 : * Allocate Q Metadata handle
62 : *-----------------------------------------------------------------------*/
63 :
64 1289 : ivas_error ivas_qmetadata_open_fx(
65 : IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */
66 : )
67 : {
68 : /* allocate MetaData handle */
69 1289 : IF( ( *hQMetaData = (IVAS_QMETADATA_HANDLE) malloc( sizeof( IVAS_QMETADATA ) ) ) == NULL )
70 : {
71 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
72 : }
73 :
74 1289 : ( *hQMetaData )->q_direction = NULL;
75 1289 : ( *hQMetaData )->surcoh_band_data = NULL;
76 1289 : ( *hQMetaData )->bandMap = NULL;
77 :
78 1289 : return IVAS_ERR_OK;
79 : }
80 :
81 : /*-----------------------------------------------------------------------*
82 : * ivas_qmetadata_allocate_memory()
83 : *
84 : * Allocates dynamic memory for qmetadata. Also reallocates automatically
85 : * if relevant parameters have changed. To function properly, this function
86 : * assumes that qmetadata contains parameter values for nbands, ndirs and
87 : * coherence_flag corresponding to the currently reserved memory. This function
88 : * then compares them to provided new values given in call and allocates or
89 : * reallocates as necessary. The parameter values in qmetadata are updated
90 : * accordingly. In addition, parameters inside qdirection config are
91 : * set here to their default values out of practicality.
92 : *-----------------------------------------------------------------------*/
93 :
94 93639 : ivas_error ivas_qmetadata_allocate_memory_fx(
95 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
96 : const Word16 nbands, /* i : new number of frequency bands */
97 : const Word16 ndirs, /* i : new number of directions */
98 : const Word16 coherence_flag /* i : new coherence coding status */
99 : )
100 : {
101 : Word16 j, dir;
102 : UWord8 do_realloc;
103 :
104 :
105 : /* Check if we need to reallocate memory or do we need to do the first time allocation. */
106 93639 : IF( hQMetaData->q_direction != NULL )
107 : {
108 92350 : do_realloc = (UWord8) NE_16( nbands, hQMetaData->q_direction->cfg.nbands );
109 92350 : do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( ndirs, hQMetaData->no_directions ) );
110 92350 : do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( coherence_flag, hQMetaData->coherence_flag ) );
111 : }
112 : ELSE
113 : {
114 1289 : do_realloc = TRUE;
115 1289 : move16();
116 : }
117 :
118 93639 : IF( do_realloc )
119 : {
120 9203 : ivas_qmetadata_free_memory_fx( hQMetaData );
121 :
122 9203 : hQMetaData->numCodingBands = (UWord8) nbands;
123 9203 : move16();
124 9203 : hQMetaData->no_directions = ndirs;
125 9203 : move16();
126 9203 : hQMetaData->coherence_flag = coherence_flag;
127 9203 : move16();
128 :
129 9203 : IF( ( hQMetaData->q_direction = (IVAS_QDIRECTION *) malloc( sizeof( IVAS_QDIRECTION ) * ndirs ) ) == NULL )
130 : {
131 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
132 : }
133 :
134 19311 : FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
135 : {
136 10108 : hQMetaData->q_direction[dir].cfg.nbands = nbands;
137 10108 : move16();
138 10108 : IF( nbands == 0 )
139 : {
140 0 : hQMetaData->q_direction[dir].band_data = NULL;
141 : }
142 : ELSE
143 : {
144 10108 : IF( ( hQMetaData->q_direction[dir].band_data = (IVAS_QDIRECTION_BAND_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ) ) == NULL )
145 : {
146 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
147 : }
148 :
149 76344 : FOR( j = 0; j < nbands; j++ )
150 : {
151 66236 : set32_fx( hQMetaData->q_direction[dir].band_data[j].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
152 66236 : set32_fx( hQMetaData->q_direction[dir].band_data[j].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
153 66236 : set32_fx( hQMetaData->q_direction[dir].band_data[j].q_elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
154 66236 : set32_fx( hQMetaData->q_direction[dir].band_data[j].q_azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
155 66236 : set32_fx( hQMetaData->q_direction[dir].band_data[j].energy_ratio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
156 : }
157 : }
158 :
159 10108 : IF( coherence_flag )
160 : {
161 3473 : hQMetaData->q_direction[dir].coherence_band_data = (IVAS_QDIRECTION_BAND_COHERENCE_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_COHERENCE_DATA ) * hQMetaData->q_direction[dir].cfg.nbands );
162 : }
163 : ELSE
164 : {
165 6635 : hQMetaData->q_direction[dir].coherence_band_data = NULL;
166 : }
167 :
168 : /* These default values are set here to get them conveniently in one place */
169 10108 : hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES;
170 10108 : move16();
171 10108 : hQMetaData->q_direction[dir].cfg.search_effort = 3;
172 10108 : move16();
173 10108 : hQMetaData->q_direction[dir].cfg.start_band = 0;
174 10108 : move16();
175 10108 : hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
176 10108 : move32();
177 : }
178 :
179 9203 : IF( coherence_flag )
180 : {
181 2880 : IF( ( hQMetaData->surcoh_band_data = (IVAS_SURROUND_COHERENCE_BAND_DATA *) malloc( sizeof( IVAS_SURROUND_COHERENCE_BAND_DATA ) * hQMetaData->q_direction[0].cfg.nbands ) ) == NULL )
182 : {
183 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
184 : }
185 : }
186 : ELSE
187 : {
188 6323 : hQMetaData->surcoh_band_data = NULL;
189 : }
190 : }
191 :
192 :
193 93639 : return IVAS_ERR_OK;
194 : }
195 :
196 :
197 : /*-----------------------------------------------------------------------*
198 : * ivas_qmetadata_free_memory()
199 : *
200 : * free dynamic part of Q Metadata memory
201 : *-----------------------------------------------------------------------*/
202 :
203 10492 : static void ivas_qmetadata_free_memory_fx(
204 : IVAS_QMETADATA_HANDLE hQMetaData /* i/o: q_metadata handle */
205 : )
206 : {
207 : Word16 dir;
208 :
209 10492 : IF( hQMetaData == NULL )
210 : {
211 0 : return;
212 : }
213 :
214 10492 : IF( hQMetaData->q_direction != NULL )
215 : {
216 19311 : FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
217 : {
218 10108 : IF( hQMetaData->q_direction[dir].band_data != NULL )
219 : {
220 10108 : free( hQMetaData->q_direction[dir].band_data );
221 10108 : hQMetaData->q_direction[dir].band_data = NULL;
222 : }
223 10108 : IF( hQMetaData->q_direction[dir].coherence_band_data != NULL )
224 : {
225 3473 : free( hQMetaData->q_direction[dir].coherence_band_data );
226 3473 : hQMetaData->q_direction[dir].coherence_band_data = NULL;
227 : }
228 : }
229 :
230 9203 : free( hQMetaData->q_direction );
231 9203 : hQMetaData->q_direction = NULL;
232 : }
233 :
234 10492 : IF( hQMetaData->surcoh_band_data != NULL )
235 : {
236 2880 : free( hQMetaData->surcoh_band_data );
237 2880 : hQMetaData->surcoh_band_data = NULL;
238 : }
239 :
240 10492 : return;
241 : }
242 :
243 :
244 : /*-----------------------------------------------------------------------*
245 : * ivas_qmetadata_close()
246 : *
247 : * close Q Metadata
248 : *-----------------------------------------------------------------------*/
249 :
250 2540 : void ivas_qmetadata_close_fx(
251 : IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */
252 : )
253 : {
254 2540 : test();
255 2540 : IF( hQMetaData == NULL || *hQMetaData == NULL )
256 : {
257 1251 : return;
258 : }
259 :
260 1289 : ivas_qmetadata_free_memory_fx( *hQMetaData );
261 :
262 1289 : free( *hQMetaData );
263 1289 : *hQMetaData = NULL;
264 :
265 1289 : return;
266 : }
267 :
268 :
269 : /*-------------------------------------------------------------------------
270 : * masa_sq()
271 : *
272 : * scalar quantization using partition
273 : *------------------------------------------------------------------------*/
274 :
275 : /*! r: codeword index */
276 3047654 : Word16 masa_sq_fx(
277 : const Word32 in, /* i : input value Q30*/
278 : const Word32 *threshold, /* i : partition Q30*/
279 : const Word16 cb_sz /* i : codebook size */
280 : )
281 : {
282 : Word16 i;
283 :
284 19950286 : FOR( i = 0; i < cb_sz; i++ )
285 : {
286 19950286 : IF( LT_32( in, threshold[i + 1] ) )
287 : {
288 3047654 : return i;
289 : }
290 : }
291 :
292 0 : return -1;
293 : }
294 :
295 : /*-------------------------------------------------------------------------
296 : * only_reduce_bits_direction()
297 : *
298 : *
299 : *------------------------------------------------------------------------*/
300 :
301 17710 : ivas_error only_reduce_bits_direction_fx(
302 : Word16 *reduce_bits_out,
303 : IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */
304 : Word16 reduce_bits,
305 : const Word16 coding_subbands,
306 : const Word16 no_subframes,
307 : Word16 *ind_order )
308 : {
309 : Word16 j, k, red_times, rem, n;
310 : Word16 max_nb, delta;
311 : Word16 *bits_dir0;
312 :
313 : Word16 bits_sph_idx_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES];
314 : Word32 penalty[MASA_MAXIMUM_CODING_SUBBANDS];
315 : Word16 tmp;
316 100520 : FOR( j = 0; j < coding_subbands; j++ )
317 : {
318 306251 : FOR( k = 0; k < no_subframes; k++ )
319 : {
320 223441 : bits_sph_idx_orig[j][k] = q_direction->band_data[j].bits_sph_idx[k];
321 223441 : move16();
322 : }
323 : }
324 17710 : n = 0;
325 17710 : move16();
326 17710 : delta = 1;
327 17710 : move16();
328 :
329 17710 : IF( reduce_bits > 0 )
330 : {
331 16974 : red_times = idiv1616( reduce_bits, imult1616( coding_subbands, no_subframes ) ); /* number of complete reductions by 1 bit */
332 16974 : IF( red_times > 0 )
333 : {
334 77807 : FOR( j = 0; j < coding_subbands; j++ )
335 : {
336 64087 : bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
337 260933 : FOR( k = 0; k < no_subframes; k++ )
338 : {
339 196846 : bits_dir0[k] = sub( bits_dir0[k], red_times );
340 196846 : move16();
341 196846 : reduce_bits = sub( reduce_bits, red_times );
342 :
343 196846 : IF( LT_16( bits_dir0[k], MASA_MIN_BITS_TF ) )
344 : {
345 29542 : reduce_bits = add( reduce_bits, sub( MASA_MIN_BITS_TF, bits_dir0[k] ) );
346 29542 : bits_dir0[k] = MASA_MIN_BITS_TF;
347 29542 : move16();
348 : }
349 : }
350 : }
351 : }
352 :
353 16974 : rem = reduce_bits; /* -coding_subbands*no_subframes*red_times; */
354 16974 : move16();
355 37522 : WHILE( LT_16( n, rem ) )
356 : {
357 20548 : max_nb = 0;
358 20548 : move16();
359 110523 : FOR( j = 0; j < coding_subbands; j++ )
360 : {
361 89975 : bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
362 362575 : FOR( k = 0; k < no_subframes; k++ )
363 : {
364 272600 : test();
365 272600 : IF( LT_16( n, rem ) && GT_16( bits_dir0[k], sub( MASA_MIN_BITS_TF, delta ) ) )
366 : {
367 150759 : bits_dir0[k] = sub( bits_dir0[k], 1 );
368 150759 : move16();
369 150759 : n = add( n, 1 );
370 : }
371 :
372 272600 : if ( LT_16( max_nb, bits_dir0[k] ) )
373 : {
374 45542 : max_nb = bits_dir0[k];
375 45542 : move16();
376 : }
377 : }
378 : }
379 :
380 20548 : IF( LE_16( max_nb, MASA_MIN_BITS_TF ) )
381 : {
382 1728 : delta = add( delta, 1 );
383 : }
384 : }
385 :
386 16974 : reduce_bits = 0;
387 16974 : move16();
388 : }
389 :
390 17710 : IF( EQ_16( ind_order[0], -1 ) )
391 : {
392 25384 : FOR( j = 0; j < coding_subbands; j++ )
393 : {
394 18960 : ind_order[j] = j;
395 18960 : move16();
396 : }
397 : }
398 : ELSE
399 : {
400 :
401 : Word16 m, sorted, index1, index2;
402 :
403 75136 : FOR( j = 0; j < coding_subbands; j++ )
404 : {
405 63850 : ind_order[j] = j;
406 63850 : move16();
407 : }
408 11286 : sorted = 0;
409 11286 : move16();
410 40956 : FOR( m = coding_subbands - 1; m && !sorted; m-- )
411 : {
412 29670 : sorted = 1;
413 29670 : move16();
414 164580 : FOR( j = 0; j < m; j++ )
415 : {
416 134910 : index1 = ind_order[j];
417 134910 : move16();
418 134910 : index2 = ind_order[j + 1];
419 134910 : move16();
420 134910 : tmp = 0;
421 134910 : move16();
422 491829 : FOR( k = 0; k < no_subframes; k++ )
423 : {
424 356919 : tmp = add( tmp, sub( bits_sph_idx_orig[index1][k], q_direction->band_data[index1].bits_sph_idx[k] ) );
425 : }
426 134910 : penalty[0] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index2][0] ) ), 1 );
427 134910 : move32();
428 134910 : tmp = 0;
429 134910 : move16();
430 491829 : FOR( k = 0; k < no_subframes; k++ )
431 : {
432 356919 : tmp = add( tmp, sub( bits_sph_idx_orig[index2][k], q_direction->band_data[index2].bits_sph_idx[k] ) );
433 : }
434 134910 : penalty[1] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index1][0] ) ), 1 );
435 134910 : move32();
436 134910 : IF( LT_32( penalty[0], penalty[1] ) )
437 : {
438 40455 : sorted = 0;
439 40455 : move16();
440 40455 : ind_order[j] = index2;
441 40455 : move16();
442 40455 : ind_order[j + 1] = index1;
443 40455 : move16();
444 : }
445 : }
446 : }
447 : }
448 :
449 17710 : *reduce_bits_out = negate( reduce_bits );
450 17710 : move16();
451 :
452 17710 : return IVAS_ERR_OK;
453 : }
454 :
455 :
456 : /*---------------------------------------------------------------
457 : * update_bits_next_block()
458 : *
459 : * Transfer the saved bits to the next subbands
460 : *---------------------------------------------------------------*/
461 :
462 52732 : void update_bits_next_block_fx(
463 : IVAS_QDIRECTION *q_direction, /* i/o: qdirection */
464 : Word16 *p_diff, /* i/o: bits to be transferred */
465 : const Word16 j, /* i : subband to update bit alloc to*/
466 : const Word16 max_i, /* i : number of subbands */
467 : const Word16 max_k /* i : n umber of subframes */
468 : )
469 : {
470 : Word16 diff;
471 : Word16 k;
472 52732 : diff = *p_diff;
473 52732 : move16();
474 52732 : IF( diff < 0 )
475 : {
476 : /* increase bits for next subbands */
477 17394 : k = 0;
478 17394 : move16();
479 71123 : WHILE( diff < 0 && LT_16( j, max_i ) && LT_16( k, max_k ) )
480 : {
481 53729 : test();
482 53729 : test();
483 53729 : IF( LT_32( q_direction->band_data[j].bits_sph_idx[k], MASA_DIRECTION_MAX_BITS ) )
484 : {
485 53725 : q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_add( q_direction->band_data[j].bits_sph_idx[k], 1 );
486 53725 : move16();
487 53725 : diff = add( diff, 1 );
488 : }
489 53729 : k = add( k, 1 );
490 : }
491 : }
492 : ELSE
493 : {
494 35338 : k = 0;
495 35338 : move16();
496 54998 : WHILE( diff > 0 && LT_16( k, max_k ) )
497 : {
498 19660 : test();
499 19660 : IF( q_direction->band_data[j].bits_sph_idx[k] > 0 )
500 : {
501 19660 : q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_sub( q_direction->band_data[j].bits_sph_idx[k], 1 );
502 19660 : move16();
503 19660 : diff = sub( diff, 1 );
504 : }
505 : }
506 : }
507 52732 : *p_diff = diff;
508 52732 : move16();
509 :
510 52732 : return;
511 : }
512 :
513 :
514 : /*---------------------------------------------------------------
515 : * invdct4_transform()
516 : *
517 : * Inverse DCT transform for 4D vector
518 : *---------------------------------------------------------------*/
519 :
520 291226 : void invdct4_transform_fx(
521 : Word32 *v_fx, /* i : input vector q */
522 : UWord8 *invdct_v, /* o : inverse transformed vector */
523 : Word16 q )
524 : {
525 : Word32 a_fx, b_fx, c_fx, d_fx;
526 : Word16 i;
527 : Word32 f_invdct_v_fx[4];
528 :
529 291226 : a_fx = L_add( v_fx[0], v_fx[2] ); // q
530 291226 : b_fx = L_sub( v_fx[0], v_fx[2] ); // q
531 : // 1.306562964876376f * 2 ^ 30 -> 1402911360, 0.541196100146198f * 2 ^ 30 -> 581104896
532 291226 : c_fx = L_shl( L_add( Mpy_32_32( 1402911360, v_fx[1] ), Mpy_32_32( 581104896, v_fx[3] ) ), Q31 - Q30 ); // q
533 291226 : d_fx = L_shl( L_sub( Mpy_32_32( 581104896, v_fx[1] ), Mpy_32_32( 1402911360, v_fx[3] ) ), Q31 - Q30 ); // q
534 291226 : f_invdct_v_fx[0] = L_shl( L_add( a_fx, c_fx ), 7 ); // q
535 291226 : move32();
536 291226 : f_invdct_v_fx[1] = L_shl( L_add( b_fx, d_fx ), 7 ); // q
537 291226 : move32();
538 291226 : f_invdct_v_fx[2] = L_shl( L_sub( b_fx, d_fx ), 7 ); // q
539 291226 : move32();
540 291226 : f_invdct_v_fx[3] = L_shl( L_sub( a_fx, c_fx ), 7 ); // q
541 291226 : move32();
542 :
543 1456130 : FOR( i = 0; i < 4; i++ )
544 : {
545 1164904 : IF( f_invdct_v_fx[i] < 0 )
546 : {
547 125730 : invdct_v[i] = 0;
548 125730 : move16();
549 : }
550 : ELSE
551 : {
552 1039174 : IF( GT_32( f_invdct_v_fx[i], L_shl( 255, q ) ) )
553 : {
554 15 : f_invdct_v_fx[i] = L_shl( 255, q ); // q
555 15 : move32();
556 : }
557 1039174 : invdct_v[i] = (UWord8) L_shr( f_invdct_v_fx[i], q ); // Q0
558 1039174 : move16();
559 : }
560 : }
561 :
562 291226 : return;
563 : }
564 :
565 : /*---------------------------------------------------------------
566 : * masa_compensate_two_dir_energy_ratio_index()
567 : *
568 : * Calculated compensated direct-to-total ratios for direction
569 : * quantization with two directions. This allows maintaining
570 : * direction accuracy while reusing one direction quantizers
571 : * separately for both directions.
572 : *--------------------------------------------------------------*/
573 :
574 380724 : void masa_compensate_two_dir_energy_ratio_index_fx(
575 : const Word16 ratio_index_1, /* i : Input ratio for direction 1 */
576 : const Word16 ratio_index_2, /* i : Input ratio for direction 2 */
577 : Word16 *ratio_index_mod1, /* o : Output modified ratio for direction 1 */
578 : Word16 *ratio_index_mod2, /* o : Output modified ratio for direction 2 */
579 : const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */
580 : )
581 : {
582 380724 : IF( hodirac_flag )
583 : {
584 355278 : *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hordiac_ratio1;
585 355278 : move16();
586 355278 : *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hoardia_ratio2;
587 355278 : move16();
588 : }
589 : ELSE
590 : {
591 25446 : *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio1;
592 25446 : move16();
593 25446 : *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio2;
594 25446 : move16();
595 : }
596 :
597 380724 : return;
598 : }
599 :
600 : /*---------------------------------------------------------------
601 : * set_qmetadata_maxbit_req()
602 : *
603 : * Sets proper value for qmetadata_max_bit_req limit
604 : *--------------------------------------------------------------*/
605 :
606 93639 : void ivas_set_qmetadata_maxbit_req_fx(
607 : IVAS_QMETADATA_HANDLE hQMetaData, /* o : qmetadata structure where the requirement value is set */
608 : const IVAS_FORMAT ivas_format /* i : IVAS format */
609 : )
610 : {
611 93639 : IF( EQ_32( ivas_format, SBA_FORMAT ) )
612 : {
613 5069 : hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_SBA;
614 5069 : move16();
615 : }
616 : ELSE /* MASA_FORMAT */
617 : {
618 88570 : hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_MASA;
619 88570 : move16();
620 : }
621 :
622 93639 : return;
623 : }
624 :
625 :
626 : /*-------------------------------------------------------------------------
627 : * ivas_qmetadata_azimuth_elevation_to_direction_vector()
628 : *
629 : *
630 : *------------------------------------------------------------------------*/
631 :
632 3243040 : void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx(
633 : const Word32 az, /* i : azimuth Q22 */
634 : const Word32 el, /* i : elevation Q22 */
635 : Word32 *dv /* o : direction vector Q30 */
636 : )
637 : {
638 : Word16 radius_length;
639 : Word16 elevation_fx, azimuth_fx;
640 :
641 : // (2 ^ 31 - 1) / 360 -> 5965232
642 3243040 : elevation_fx = extract_l( L_shr( Mpy_32_32( el, ONE_BY_360_Q31 ), 7 ) ); // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
643 3243040 : azimuth_fx = extract_l( L_shr( Mpy_32_32( az, ONE_BY_360_Q31 ), 7 ) ); // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
644 :
645 3243040 : dv[2] = L_shl( getSineWord16R2( elevation_fx ), Q15 ); /* Q30 */
646 3243040 : move32();
647 3243040 : radius_length = getCosWord16R2( elevation_fx );
648 3243040 : dv[0] = L_mult0( radius_length, getCosWord16R2( azimuth_fx ) ); /* Q30 */
649 3243040 : move32();
650 3243040 : dv[1] = L_mult0( radius_length, getSineWord16R2( azimuth_fx ) ); /* Q30 */
651 3243040 : move32();
652 :
653 3243040 : return;
654 : }
655 :
656 : /*-------------------------------------------------------------------------
657 : * ivas_qmetadata_direction_vector_to_azimuth_elevation()
658 : *
659 : * azimuth between [-180, 180]
660 : * elevation between [-90 and 90]
661 : *------------------------------------------------------------------------*/
662 :
663 2649839 : void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx(
664 : const Word32 *dv, /* i : direction vector dv_q */
665 : const Word16 dv_q,
666 : Word32 *az, /* o : azimuth Q22 */
667 : Word32 *el /* o : elevation Q22 */
668 : )
669 : {
670 : /* note: dv does not need to have unit L_2 norm, because the conversion is scale invariant */
671 : Word32 L_tmp;
672 : Word16 e_tmp;
673 2649839 : L_tmp = L_add( Mpy_32_32( dv[0], dv[0] ), Mpy_32_32( dv[1], dv[1] ) ); /* 2 * dv_q - 31 */
674 2649839 : e_tmp = shl( sub( 31, dv_q ), 1 );
675 2649839 : L_tmp = Sqrt32( L_tmp, &e_tmp ); // e_tmp
676 : // 29335 -> 180 / PI in Q9
677 2649839 : *el = L_mult0( BASOP_util_atan2( dv[2], L_tmp, sub( sub( 31, dv_q ), e_tmp ) ), 29335 ); /* Q22 */
678 2649839 : move32();
679 : // 29335 -> 180 / PI in Q9
680 2649839 : *az = L_mult0( BASOP_util_atan2( dv[1], dv[0], 0 ), 29335 ); /* Q22 */
681 2649839 : move32();
682 2649839 : return;
683 : }
684 :
685 :
686 : /*-------------------------------------------------------------------------
687 : * ivas_get_df_ratio_bits_hodirac()
688 : *
689 : *
690 : *------------------------------------------------------------------------*/
691 :
692 : /*! r: bits to be used for quantizing ratio of ratios */
693 355278 : Word16 ivas_get_df_ratio_bits_hodirac_fx(
694 : const Word16 index_diff /* i : index of quantized diffuse-to-total ratio */
695 : )
696 : {
697 : Word16 dfRatio_bits;
698 :
699 355278 : IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
700 : {
701 177365 : dfRatio_bits = 1;
702 177365 : move16();
703 : }
704 177913 : ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX_HODIRAC ) )
705 : {
706 97503 : dfRatio_bits = 2;
707 97503 : move16();
708 : }
709 : ELSE
710 : {
711 80410 : dfRatio_bits = 3;
712 80410 : move16();
713 : }
714 :
715 355278 : return dfRatio_bits;
716 : }
717 :
718 : /*---------------------------------------------------------------
719 : * ivas_get_df_ratio_bits()
720 : *
721 : * Gives quantization accuracy for distribution factor of
722 : * direct-to-total ratios based on the diffuse-to-total ratio
723 : * index
724 : *--------------------------------------------------------------*/
725 :
726 : /*! r: bits to be used for quantizing ratio of ratios */
727 25446 : Word16 ivas_get_df_ratio_bits_fx(
728 : const Word16 index_diff /* i : index of quantized diffuse-to-total ratio */
729 : )
730 : {
731 : Word16 dfRatio_bits;
732 :
733 25446 : IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
734 : {
735 528 : dfRatio_bits = 1;
736 528 : move16();
737 : }
738 24918 : ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX ) )
739 : {
740 21327 : dfRatio_bits = 2;
741 21327 : move16();
742 : }
743 : ELSE
744 : {
745 3591 : dfRatio_bits = 3;
746 3591 : move16();
747 : }
748 :
749 25446 : return dfRatio_bits;
750 : }
|