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