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 "options.h"
36 : #include <math.h>
37 : #include "prot_fx.h"
38 : #include "ivas_cnst.h"
39 : #include "ivas_rom_com.h"
40 : #include "ivas_stat_dec.h"
41 : #include "wmc_auto.h"
42 : #include "ivas_prot_fx.h"
43 :
44 :
45 : /*---------------------------------------------------------------
46 : * Local constants
47 : *---------------------------------------------------------------*/
48 :
49 : #define MASA_EXTRA_BAND_META_BITS 40
50 :
51 : #define MASA_SMALL_INC_META_BITS 10
52 :
53 :
54 : /*---------------------------------------------------------------
55 : * Local prototypes
56 : *---------------------------------------------------------------*/
57 :
58 : static Word16 quantize_theta_masa_fx(
59 : const Word32 x_fx, /* i : theta value to be quantized Q22*/
60 : const Word16 no_cb, /* i : number of codewords */
61 : Word32 *xhat_fx /* o : quantized value Q22*/
62 : );
63 :
64 : static Word16 quantize_phi_masa_fx(
65 : const Word32 phi_fx, /* i : azimuth value Q22 */
66 : const Word16 flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */
67 : Word32 *phi_hat_fx, /* o : quantized azimuth Q22 */
68 : const Word16 n /* i : azimuth codebook size */
69 : );
70 :
71 : static Word32 estim_round[MASA_NO_CIRCLES + 1] = {
72 : /* Q0 */
73 : -423,
74 : 0,
75 : 422,
76 : 845,
77 : 1267,
78 : 1689,
79 : 2111,
80 : 2532,
81 : 2953,
82 : 3373,
83 : 3793,
84 : 4212,
85 : 4630,
86 : 5047,
87 : 5464,
88 : 5880,
89 : 6294,
90 : 6708,
91 : 7120,
92 : 7532,
93 : 7941,
94 : 8350,
95 : 8757,
96 : 9163,
97 : 9567,
98 : 9969,
99 : 10370,
100 : 10769,
101 : 11166,
102 : 11561,
103 : 11955,
104 : 12346,
105 : 12735,
106 : 13122,
107 : 13507,
108 : 13890,
109 : 14270,
110 : 14648,
111 : 15023,
112 : 15396,
113 : 15766,
114 : 16134,
115 : 16499,
116 : 16861,
117 : 17220,
118 : 17576,
119 : 17930,
120 : 18280,
121 : 18627,
122 : 18971,
123 : 19312,
124 : 19650,
125 : 19984,
126 : 20315,
127 : 20643,
128 : 20967,
129 : 21288,
130 : 21605,
131 : 21918,
132 : 22228,
133 : 22534,
134 : 22836,
135 : 23135,
136 : 23429,
137 : 23720,
138 : 24007,
139 : 24289,
140 : 24568,
141 : 24842,
142 : 25112,
143 : 25378,
144 : 25640,
145 : 25898,
146 : 26151,
147 : 26400,
148 : 26644,
149 : 26884,
150 : 27119,
151 : 27350,
152 : 27576,
153 : 27798,
154 : 28015,
155 : 28227,
156 : 28435,
157 : 28637,
158 : 28835,
159 : 29029,
160 : 29217,
161 : 29400,
162 : 29579,
163 : 29752,
164 : 29921,
165 : 30084,
166 : 30243,
167 : 30396,
168 : 30544,
169 : 30688,
170 : 30826,
171 : 30959,
172 : 31086,
173 : 31209,
174 : 31326,
175 : 31438,
176 : 31545,
177 : 31647,
178 : 31743,
179 : 31834,
180 : 31919,
181 : 32000,
182 : 32075,
183 : 32144,
184 : 32208,
185 : 32267,
186 : 32320,
187 : 32368,
188 : 32411,
189 : 32448,
190 : 32480,
191 : 32506,
192 : 32527,
193 : 32542,
194 : 32552
195 : };
196 :
197 : static Word32 estim_ceil[MASA_NO_CIRCLES + 1] = {
198 : /* Q0 */
199 : -422,
200 : 0,
201 : 423,
202 : 845,
203 : 1268,
204 : 1690,
205 : 2111,
206 : 2532,
207 : 2953,
208 : 3374,
209 : 3793,
210 : 4212,
211 : 4630,
212 : 5048,
213 : 5465,
214 : 5880,
215 : 6295,
216 : 6708,
217 : 7121,
218 : 7532,
219 : 7942,
220 : 8350,
221 : 8758,
222 : 9163,
223 : 9567,
224 : 9970,
225 : 10371,
226 : 10770,
227 : 11167,
228 : 11562,
229 : 11955,
230 : 12347,
231 : 12736,
232 : 13123,
233 : 13508,
234 : 13890,
235 : 14270,
236 : 14648,
237 : 15024,
238 : 15396,
239 : 15767,
240 : 16134,
241 : 16499,
242 : 16861,
243 : 17220,
244 : 17577,
245 : 17930,
246 : 18280,
247 : 18628,
248 : 18972,
249 : 19313,
250 : 19650,
251 : 19985,
252 : 20316,
253 : 20644,
254 : 20968,
255 : 21288,
256 : 21605,
257 : 21919,
258 : 22229,
259 : 22535,
260 : 22837,
261 : 23135,
262 : 23430,
263 : 23720,
264 : 24007,
265 : 24290,
266 : 24568,
267 : 24843,
268 : 25113,
269 : 25379,
270 : 25641,
271 : 25898,
272 : 26151,
273 : 26400,
274 : 26644,
275 : 26884,
276 : 27120,
277 : 27350,
278 : 27577,
279 : 27798,
280 : 28015,
281 : 28228,
282 : 28435,
283 : 28638,
284 : 28836,
285 : 29029,
286 : 29217,
287 : 29401,
288 : 29579,
289 : 29753,
290 : 29921,
291 : 30085,
292 : 30243,
293 : 30397,
294 : 30545,
295 : 30688,
296 : 30826,
297 : 30959,
298 : 31087,
299 : 31210,
300 : 31327,
301 : 31439,
302 : 31546,
303 : 31647,
304 : 31743,
305 : 31834,
306 : 31920,
307 : 32000,
308 : 32075,
309 : 32145,
310 : 32209,
311 : 32268,
312 : 32321,
313 : 32369,
314 : 32411,
315 : 32449,
316 : 32480,
317 : 32506,
318 : 32527,
319 : 32543,
320 : 32552
321 : };
322 :
323 :
324 : /*---------------------------------------------------------------
325 : * ivas_masa_setup()
326 : *
327 : * Set-up MASA coding elements and bitrates
328 : *---------------------------------------------------------------*/
329 :
330 94049 : void ivas_masa_set_elements_fx(
331 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
332 : const Word16 mc_mode, /* i : MC format mode */
333 : const Word16 nchan_transport, /* i : number of MASA input/transport channels */
334 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
335 : Word16 *element_mode, /* o : element mode */
336 : Word16 *nSCE, /* o : number of SCEs */
337 : Word16 *nCPE, /* o : number of CPEs */
338 : const Word16 ivas_format, /* i : IVAS format */
339 : const ISM_MODE ism_mode, /* i : ISM mode */
340 : const Word32 ism_total_brate /* i : initial ISM total bitrate */
341 : )
342 : {
343 : Word16 tmp;
344 :
345 94049 : IF( EQ_16( nchan_transport, 2 ) )
346 : {
347 54295 : test();
348 54295 : test();
349 54295 : IF( GE_32( ivas_total_brate, MCMASA_SEPARATE_BRATE ) && EQ_16( mc_mode, MC_MODE_MCMASA ) )
350 : {
351 663 : *nCPE = 1;
352 663 : move16();
353 663 : *nSCE = 1;
354 663 : move16();
355 :
356 663 : *element_mode = IVAS_SCE; /* This is needed for the initialization phase to initialize codec mode to SCE, since it is written first to the file*/
357 663 : move16();
358 : }
359 53632 : ELSE IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) && ism_mode != ISM_MODE_NONE )
360 : {
361 15244 : *nCPE = 1;
362 15244 : move16();
363 :
364 15244 : if ( EQ_16( *element_mode, -1 ) )
365 : {
366 6944 : *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */
367 6944 : move16();
368 : }
369 15244 : IF( GT_32( ivas_total_brate, MIN_BRATE_MDCT_STEREO ) )
370 : {
371 10166 : *element_mode = IVAS_CPE_MDCT;
372 10166 : move16();
373 10166 : test();
374 10166 : test();
375 10166 : test();
376 10166 : if ( ( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) && LT_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) )
377 : {
378 1105 : *element_mode = IVAS_CPE_DFT;
379 1105 : move16();
380 : }
381 : }
382 : }
383 : ELSE
384 : {
385 38388 : *nCPE = 1;
386 38388 : move16();
387 38388 : *nSCE = 0;
388 38388 : move16();
389 :
390 38388 : if ( GT_32( ivas_total_brate, MIN_BRATE_MDCT_STEREO ) )
391 : {
392 17860 : *element_mode = IVAS_CPE_MDCT;
393 17860 : move16();
394 : }
395 : }
396 : /* hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ); */
397 54295 : hQMetaData->bits_frame_nominal = extract_l( Mpy_32_32( ivas_total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
398 54295 : test();
399 54295 : test();
400 54295 : test();
401 54295 : if ( EQ_16( ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_DISC ) ) )
402 : {
403 : /* hQMetaData->bits_frame_nominal -= (int16_t) ( ism_total_brate / FRAMES_PER_SEC ); */
404 15244 : tmp = extract_l( Mpy_32_32( ism_total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
405 15244 : hQMetaData->bits_frame_nominal = sub( hQMetaData->bits_frame_nominal, tmp );
406 : }
407 : }
408 39754 : ELSE IF( GE_16( nchan_transport, 1 ) )
409 : {
410 39754 : *nCPE = 0;
411 39754 : move16();
412 39754 : *nSCE = 1;
413 39754 : move16();
414 :
415 39754 : IF( EQ_32( ivas_total_brate, IVAS_13k2 ) )
416 : {
417 7491 : hQMetaData->bits_frame_nominal = ACELP_9k60 / FRAMES_PER_SEC;
418 7491 : move16();
419 : }
420 32263 : ELSE IF( LE_32( ivas_total_brate, IVAS_16k4 ) )
421 : {
422 2503 : hQMetaData->bits_frame_nominal = ACELP_13k20 / FRAMES_PER_SEC;
423 2503 : move16();
424 : }
425 29760 : ELSE IF( LE_32( ivas_total_brate, IVAS_24k4 ) )
426 : {
427 11614 : hQMetaData->bits_frame_nominal = ACELP_16k40 / FRAMES_PER_SEC;
428 11614 : move16();
429 : }
430 18146 : ELSE IF( LE_32( ivas_total_brate, IVAS_32k ) )
431 : {
432 4547 : hQMetaData->bits_frame_nominal = ACELP_24k40 / FRAMES_PER_SEC;
433 4547 : move16();
434 : }
435 : ELSE
436 : {
437 13599 : hQMetaData->bits_frame_nominal = extract_l( Mpy_32_32( ivas_total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) );
438 : }
439 39754 : *element_mode = IVAS_SCE;
440 39754 : move16();
441 : }
442 : ELSE
443 : {
444 0 : assert( !"MASA number of transport channels must be 1, or 2" );
445 : }
446 :
447 94049 : return;
448 : }
449 :
450 :
451 : /*---------------------------------------------------------------
452 : * generate_gridEq()
453 : *
454 : * generate Spherical grid
455 : *---------------------------------------------------------------*/
456 :
457 635 : void generate_gridEq_fx(
458 : SPHERICAL_GRID_DATA *data /* o : data structure for grid */
459 : )
460 : {
461 : /***************************************************************/
462 : /* NOTE: created LUT from float code. The lookup table depends */
463 : /* on the following macros: */
464 : /* - MASA_NO_CIRCLES */
465 : /* - MASA_NO_POINTS_EQUATOR */
466 : /* - MASA_ANGLE_AT_EQUATOR */
467 : /* - MASA_NTOT2_FAC */
468 : /* - MASA_ASIN_OFFSET */
469 : /***************************************************************/
470 :
471 635 : Copy( gridEq_Table, data->no_phi, NO_THETA16_MAX );
472 :
473 635 : data->no_theta = NO_THETA16_MAX;
474 635 : move16();
475 :
476 635 : return;
477 : }
478 :
479 :
480 : /*---------------------------------------------------------------
481 : * ivas_masa_set_coding_config()
482 : *
483 : * Sets MASA codec parameters based on bitrate, number of directions,
484 : * and other metadata properties.
485 : *---------------------------------------------------------------*/
486 :
487 89040 : void ivas_masa_set_coding_config_fx(
488 : MASA_CODEC_CONFIG *config, /* i/o: MASA coding config structure */
489 : Word16 *band_mapping, /* o : Band mapping used */
490 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
491 : const Word16 nchan_transport, /* i : number of transport channels (mono/stereo) */
492 : const UWord8 isMcMasa /* i : toggle for selecting mcMASA specific config */
493 : )
494 : {
495 : Word16 i;
496 : UWord8 nbands;
497 : UWord8 nTwoDirBands;
498 : const Word16 *masa_bits_table;
499 :
500 : /* When coming into this function, these values should be already set:
501 : * joinedSubframes;
502 : * useCoherence;
503 : * numberOfDirections;
504 : */
505 :
506 : /* Setup coding parameters based on the bitrate, transport channel count, subframe metadata information,
507 : * and number of directions in metadata. */
508 89040 : nbands = 0;
509 89040 : move16();
510 89040 : nTwoDirBands = 0;
511 89040 : move16();
512 89040 : i = 0;
513 89040 : move16();
514 :
515 : /* First select correct bit budget table */
516 89040 : masa_bits_table = masa_bits;
517 :
518 89040 : test();
519 89040 : IF( isMcMasa )
520 : {
521 11790 : masa_bits_table = mcmasa_bits;
522 : }
523 77250 : ELSE IF( LT_32( ivas_total_brate, IVAS_48k ) && EQ_16( nchan_transport, 2 ) )
524 : {
525 23253 : masa_bits_table = masa_bits_LR_stereo;
526 : }
527 :
528 567433 : WHILE( nbands == 0 && LT_16( i, IVAS_NUM_ACTIVE_BRATES ) )
529 : {
530 478393 : test();
531 478393 : IF( LE_32( ivas_total_brate, ivas_brate_tbl[i + SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES] ) )
532 : {
533 : Word16 idx_bands;
534 :
535 89040 : test();
536 89040 : test();
537 89040 : if ( LT_32( ivas_total_brate, IVAS_48k ) && EQ_16( nchan_transport, 2 ) && GT_16( i, 3 ) )
538 : {
539 : /* because it uses the bitallocation for the lower bit rates from 'masa_bits_LR_stereo' and it has 4 elements */
540 750 : i = 3;
541 750 : move16();
542 : }
543 89040 : idx_bands = i;
544 89040 : move16();
545 :
546 89040 : IF( GT_16( config->numberOfDirections, 1 ) )
547 : {
548 15664 : IF( config->joinedSubframes )
549 : {
550 2764 : nTwoDirBands = masa_twodir_bands_joined[i];
551 2764 : move16();
552 : }
553 : ELSE
554 : {
555 12900 : nTwoDirBands = masa_twodir_bands[i];
556 12900 : move16();
557 : }
558 :
559 15664 : test();
560 15664 : test();
561 15664 : test();
562 15664 : if ( ( GT_32( ivas_total_brate, IVAS_96k ) && !config->joinedSubframes ) || ( GT_32( ivas_total_brate, IVAS_80k ) && config->joinedSubframes ) )
563 : {
564 7761 : idx_bands = sub( idx_bands, 1 );
565 : }
566 : }
567 :
568 89040 : IF( config->joinedSubframes )
569 : {
570 10980 : nbands = masa_joined_nbands[idx_bands];
571 10980 : move16();
572 : }
573 : ELSE
574 : {
575 78060 : nbands = masa_nbands[idx_bands];
576 78060 : move16();
577 : }
578 :
579 89040 : config->max_metadata_bits = (UWord16) masa_bits_table[i];
580 89040 : move16();
581 :
582 89040 : test();
583 89040 : if ( EQ_32( ivas_total_brate, IVAS_64k ) && GT_16( config->numberOfDirections, 1 ) )
584 : {
585 : /* At 64k, we increase metadata bit budget when there is two directions present. */
586 1094 : config->max_metadata_bits = (UWord16) add( config->max_metadata_bits, MASA_EXTRA_BAND_META_BITS );
587 1094 : move16();
588 : }
589 :
590 89040 : test();
591 89040 : test();
592 89040 : test();
593 89040 : if ( ( ( EQ_32( ivas_total_brate, IVAS_32k ) && EQ_16( nchan_transport, 2 ) ) || EQ_32( ivas_total_brate, IVAS_48k ) ) && config->joinedSubframes )
594 : {
595 : /* At 32k and 48k, we increase metadata bit budget when joinedSubframes. */
596 2241 : config->max_metadata_bits = (UWord16) add( config->max_metadata_bits, MASA_SMALL_INC_META_BITS );
597 2241 : move16();
598 : }
599 : }
600 478393 : i = add( i, 1 );
601 : }
602 89040 : config->numCodingBands = nbands;
603 89040 : move16();
604 89040 : config->numTwoDirBands = nTwoDirBands;
605 89040 : move16();
606 :
607 89040 : IF( EQ_16( config->joinedSubframes, TRUE ) )
608 : {
609 10980 : config->mergeRatiosOverSubframes = FALSE;
610 10980 : move16();
611 : }
612 : ELSE
613 : {
614 78060 : config->mergeRatiosOverSubframes = TRUE;
615 78060 : move16();
616 : }
617 :
618 : /* Setup frequency band mapping based on the number of used coding bands */
619 89040 : SWITCH( config->numCodingBands )
620 : {
621 66578 : case 5:
622 66578 : Copy( MASA_band_mapping_24_to_5, band_mapping, 5 + 1 );
623 66578 : BREAK;
624 6855 : case 8:
625 6855 : Copy( MASA_band_mapping_24_to_8, band_mapping, 8 + 1 );
626 6855 : BREAK;
627 3996 : case 12:
628 3996 : Copy( MASA_band_mapping_24_to_12, band_mapping, 12 + 1 );
629 3996 : BREAK;
630 4375 : case 18:
631 4375 : Copy( MASA_band_mapping_24_to_18, band_mapping, 18 + 1 );
632 4375 : BREAK;
633 7236 : case MASA_FREQUENCY_BANDS:
634 : /* With input count of bands, no mapping is needed but for unified processing later, we store normal mapping */
635 188136 : FOR( i = 0; i < MASA_FREQUENCY_BANDS + 1; i++ )
636 : {
637 180900 : band_mapping[i] = i;
638 180900 : move16();
639 : }
640 7236 : BREAK;
641 0 : default:
642 0 : assert( 0 && "Error: The number of MASA coding bands is not supported" );
643 : }
644 :
645 89040 : config->useCoherence = TRUE;
646 89040 : move16();
647 89040 : test();
648 89040 : test();
649 89040 : test();
650 89040 : if ( ( !isMcMasa && LT_32( ivas_total_brate, IVAS_48k ) ) || ( isMcMasa && LT_32( ivas_total_brate, IVAS_16k4 ) ) )
651 : {
652 38951 : config->useCoherence = FALSE;
653 38951 : move16();
654 : }
655 :
656 89040 : return;
657 : }
658 :
659 :
660 : /*---------------------------------------------------------------
661 : * masa_sample_rate_band_correction()
662 : *
663 : *
664 : *---------------------------------------------------------------*/
665 :
666 89040 : void masa_sample_rate_band_correction_fx(
667 : MASA_CODEC_CONFIG *config, /* i/o: MASA codec config */
668 : Word16 *band_mapping, /* i/o: Band mapping used and modified */
669 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */
670 : const UWord8 maxBand, /* i : max band */
671 : UWord8 is_encoder, /* i : signals if called at encoder */
672 : MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */
673 : )
674 : {
675 : UWord8 band, sf;
676 : Word16 highBand;
677 : UWord8 numBands48k;
678 :
679 89040 : numBands48k = config->numCodingBands;
680 89040 : move16();
681 :
682 684663 : FOR( band = 1; band < config->numCodingBands + 1; band++ )
683 : {
684 684663 : highBand = band_mapping[band];
685 684663 : move16();
686 :
687 684663 : IF( GE_16( highBand, (Word16) maxBand ) )
688 : {
689 89040 : config->numCodingBands = band;
690 89040 : move16();
691 89040 : hQMetaData->numCodingBands = band;
692 89040 : move16();
693 :
694 89040 : IF( is_encoder )
695 : {
696 2276 : if ( GT_16( hQMetaData->q_direction->cfg.nbands, (Word16) band ) )
697 : {
698 300 : hQMetaData->q_direction->cfg.nbands = band;
699 300 : move16();
700 : }
701 2276 : test();
702 2276 : if ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) && GT_16( hQMetaData->q_direction[1].cfg.nbands, (Word16) band ) )
703 : {
704 300 : hQMetaData->q_direction[1].cfg.nbands = band;
705 300 : move16();
706 : }
707 : }
708 :
709 89040 : band_mapping[band] = maxBand;
710 89040 : move16();
711 :
712 89040 : BREAK;
713 : }
714 : }
715 :
716 : /* Set rest of the bands to zero in qmetadata. */
717 92473 : FOR( ; band < numBands48k; band++ )
718 : {
719 17165 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
720 : {
721 13732 : hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = 0;
722 13732 : move32();
723 13732 : hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = 0;
724 13732 : move32();
725 13732 : hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = 0;
726 13732 : move32();
727 :
728 13732 : test();
729 13732 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL )
730 : {
731 13732 : hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u;
732 13732 : move16();
733 : }
734 :
735 13732 : IF( EQ_16( (Word16) hQMetaData->no_directions, 2 ) )
736 : {
737 2304 : hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf] = 0;
738 2304 : move32();
739 2304 : hQMetaData->q_direction[1].band_data[band].elevation_fx[sf] = 0;
740 2304 : move32();
741 2304 : hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[sf] = 0;
742 2304 : move32();
743 :
744 2304 : test();
745 2304 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL )
746 : {
747 2304 : hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = 0u;
748 2304 : move16();
749 : }
750 : }
751 :
752 13732 : test();
753 13732 : if ( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL )
754 : {
755 13732 : hQMetaData->surcoh_band_data[band].surround_coherence[sf] = 0u;
756 13732 : move16();
757 : }
758 : }
759 :
760 3433 : if ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) )
761 : {
762 576 : hQMetaData->twoDirBands[band] = 0;
763 576 : move16();
764 : }
765 : }
766 :
767 89040 : IF( hExtOutMeta != NULL )
768 : {
769 : /* in decoder, zero the EXT out MASA meta buffer */
770 26525 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
771 : {
772 350868 : FOR( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ )
773 : {
774 329648 : hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT;
775 329648 : move16();
776 329648 : hExtOutMeta->directToTotalRatio[0][sf][band] = 0u;
777 329648 : move16();
778 329648 : hExtOutMeta->spreadCoherence[0][sf][band] = 0u;
779 329648 : move16();
780 :
781 329648 : hExtOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
782 329648 : move16();
783 329648 : hExtOutMeta->directToTotalRatio[1][sf][band] = 0u;
784 329648 : move16();
785 329648 : hExtOutMeta->spreadCoherence[1][sf][band] = 0u;
786 329648 : move16();
787 :
788 329648 : hExtOutMeta->surroundCoherence[sf][band] = 0u;
789 329648 : move16();
790 329648 : hExtOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX;
791 329648 : move16();
792 : }
793 : }
794 : }
795 :
796 89040 : return;
797 : }
798 :
799 :
800 : /*-------------------------------------------------------------------------
801 : * index_theta_phi_16()
802 : *
803 : *
804 : *------------------------------------------------------------------------*/
805 :
806 : /*! r: output index for direction */
807 285945 : UWord16 index_theta_phi_16_fx(
808 : Word32 *p_theta, /* i/o: input elevation to be indexed Q22 */
809 : Word32 *p_phi, /* i/o: input azimuth to be indexed Q22 */
810 : const SPHERICAL_GRID_DATA *gridData /* i : generated grid data */
811 : )
812 : {
813 : Word32 abs_theta_fx;
814 : Word16 sign_th, id_phi, id_th;
815 : UWord16 idx_sph;
816 : UWord16 cum_n;
817 : Word32 theta_hat_fx, phi_hat_fx;
818 : Word32 theta_fx, phi_fx;
819 :
820 285945 : theta_fx = *p_theta; // Q22
821 285945 : move32();
822 285945 : phi_fx = *p_phi; // Q22
823 285945 : move32();
824 285945 : phi_hat_fx = 0;
825 285945 : move32();
826 285945 : theta_hat_fx = 0;
827 285945 : move32();
828 285945 : phi_fx = L_add( phi_fx, L_shl( 180, Q22 ) ); // Q22
829 :
830 285945 : IF( theta_fx < 0 )
831 : {
832 85360 : abs_theta_fx = L_negate( theta_fx ); // Q22
833 85360 : sign_th = -1;
834 85360 : move16();
835 : }
836 : ELSE
837 : {
838 200585 : abs_theta_fx = theta_fx; // Q22
839 200585 : move32();
840 200585 : sign_th = 1;
841 200585 : move16();
842 : }
843 :
844 285945 : id_th = quantize_theta_masa_fx( abs_theta_fx, gridData->no_theta, &theta_hat_fx );
845 285945 : IF( GT_16( gridData->no_theta, 1 ) )
846 : {
847 285945 : IF( GT_16( gridData->no_phi[id_th], 1 ) )
848 : {
849 285727 : id_phi = quantize_phi_masa_fx( phi_fx, (Word16) EQ_16( s_and( id_th, 1 ), 1 ), &phi_hat_fx, gridData->no_phi[id_th] );
850 : }
851 : ELSE
852 : {
853 218 : id_phi = 0;
854 218 : move16();
855 218 : phi_hat_fx = L_shl( 180, Q22 ); // Q22
856 : }
857 : }
858 : ELSE
859 : {
860 0 : id_phi = quantize_phi_masa_fx( phi_fx, (Word16) EQ_16( s_and( id_th, 1 ), 1 ), &phi_hat_fx, gridData->no_phi[id_th] );
861 : }
862 :
863 285945 : *p_theta = theta_hat_fx;
864 285945 : move32();
865 285945 : if ( EQ_16( sign_th, -1 ) )
866 : {
867 85360 : *p_theta = L_negate( theta_hat_fx ); // Q22
868 85360 : move32();
869 : }
870 285945 : *p_phi = L_sub( phi_hat_fx, L_shl( 180, Q22 ) ); // Q22
871 285945 : move32();
872 :
873 : /* Starting from Equator, alternating positive and negative */
874 285945 : IF( id_th == 0 )
875 : {
876 126962 : idx_sph = id_phi;
877 126962 : move16();
878 : }
879 : ELSE
880 : {
881 158983 : IF( EQ_16( id_th, sub( gridData->no_theta, 1 ) ) )
882 : {
883 218 : idx_sph = 65534; // Q0
884 218 : move16();
885 218 : if ( sign_th < 0 )
886 : {
887 184 : idx_sph = 65535; // Q0
888 184 : move16();
889 : }
890 : }
891 : ELSE
892 : {
893 158765 : cum_n = cum_n_for_id_th[id_th]; // Q0
894 158765 : move16();
895 :
896 158765 : cum_n = (UWord16) L_add( cum_n, gridData->no_phi[0] ); // Q0
897 :
898 158765 : IF( sign_th > 0 )
899 : {
900 74343 : cum_n = (UWord16) L_sub( cum_n, shl( gridData->no_phi[id_th], 1 ) ); // Q0
901 : }
902 : ELSE
903 : {
904 84422 : cum_n = (UWord16) L_sub( cum_n, gridData->no_phi[id_th] ); // Q0
905 : }
906 158765 : idx_sph = (UWord16) L_add( cum_n, id_phi ); // Q0
907 : }
908 : }
909 :
910 285945 : return idx_sph; // Q0
911 : }
912 :
913 :
914 : /*-------------------------------------------------------------------------
915 : * quantize_theta_masa()
916 : *
917 : *
918 : *------------------------------------------------------------------------*/
919 :
920 : /*! r: output index */
921 285945 : static Word16 quantize_theta_masa_fx(
922 : const Word32 x_fx, /* i : theta value to be quantized Q22*/
923 : const Word16 no_cb, /* i : number of codewords */
924 : Word32 *xhat_fx /* o : quantized value Q22*/
925 : )
926 : {
927 : Word16 imin;
928 : Word32 diff1_fx, diff2_fx;
929 :
930 285945 : imin = extract_l( L_shr( L_add( Mpy_32_32( x_fx, MASA_INV_ANGLE_AT_EQUATOR_DEG_Q30 ), ONE_IN_Q20 ), 21 ) ); // 22 + 30 - 31 = 21 -> Q21 - 21 = Q0
931 :
932 285945 : IF( GE_16( imin, sub( no_cb, 1 ) ) )
933 : {
934 223 : imin = sub( no_cb, 1 );
935 223 : diff1_fx = L_sub( x_fx, L_shl( 90, Q22 ) ); // Q22
936 223 : diff2_fx = L_sub( x_fx, Mpy_32_16_1( MASA_ANGLE_AT_EQUATOR_DEG_Q31, shl( sub( imin, 1 ), 6 ) ) ); // q31 + q0+6 - 15 = q22
937 223 : IF( GT_32( L_abs( diff1_fx ), L_abs( diff2_fx ) ) )
938 : {
939 5 : imin = sub( imin, 1 );
940 5 : *xhat_fx = Mpy_32_16_1( MASA_ANGLE_AT_EQUATOR_DEG_Q31, shl( imin, 6 ) ); // 31 + 6 - 15 = Q22
941 5 : move32();
942 : }
943 : ELSE
944 : {
945 218 : *xhat_fx = L_shl( 90, Q22 ); // Q22
946 218 : move32();
947 : }
948 : }
949 : ELSE
950 : {
951 285722 : *xhat_fx = Mpy_32_16_1( MASA_ANGLE_AT_EQUATOR_DEG_Q31, shl( imin, 6 ) ); // 31 + 6 - 15 = Q22
952 285722 : move32();
953 : }
954 :
955 285945 : return imin;
956 : }
957 :
958 :
959 : /*-------------------------------------------------------------------------
960 : * quantize_phi_masa()
961 : *
962 : *
963 : *------------------------------------------------------------------------*/
964 :
965 : /*! r: index azimuth */
966 285727 : static Word16 quantize_phi_masa_fx(
967 : const Word32 phi_fx, /* i : azimuth value Q22 */
968 : const Word16 flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */
969 : Word32 *phi_hat_fx, /* o : quantized azimuth Q22 */
970 : const Word16 n /* i : azimuth codebook size */
971 : )
972 : {
973 : Word16 id_phi;
974 :
975 : Word32 dd_fx;
976 : Word32 delta_phi_fx;
977 : Word32 tmp32;
978 : Word16 tmp_e, delta_phi_e;
979 :
980 285727 : delta_phi_fx = BASOP_Util_Divide3232_Scale_newton( 360, n, &delta_phi_e );
981 285727 : delta_phi_fx = L_shr( delta_phi_fx, sub( sub( 31, delta_phi_e ), 22 ) ); // Q22
982 :
983 285727 : IF( EQ_16( n, 1 ) )
984 : {
985 0 : *phi_hat_fx = 0;
986 0 : move32();
987 :
988 0 : return 0;
989 : }
990 :
991 285727 : IF( EQ_16( flag_delta, 1 ) )
992 : {
993 101291 : dd_fx = L_shr( delta_phi_fx, 1 ); // Q22
994 : }
995 : ELSE
996 : {
997 184436 : dd_fx = 0;
998 184436 : move32();
999 : }
1000 :
1001 285727 : tmp32 = L_add( L_sub( phi_fx, dd_fx ), L_shr( delta_phi_fx, 1 ) );
1002 285727 : tmp32 = BASOP_Util_Divide3232_Scale_newton( tmp32, delta_phi_fx, &tmp_e );
1003 285727 : id_phi = extract_l( L_shr( tmp32, sub( 31, tmp_e ) ) ); // Q0
1004 :
1005 285727 : if ( EQ_16( id_phi, n ) )
1006 : {
1007 22 : id_phi = 0;
1008 22 : move16();
1009 : }
1010 :
1011 285727 : if ( EQ_16( id_phi, -1 ) )
1012 : {
1013 0 : id_phi = sub( n, 1 );
1014 : }
1015 :
1016 285727 : delta_phi_fx = BASOP_Util_Divide3232_Scale_newton( L_mult0( 360, id_phi ), n, &delta_phi_e );
1017 285727 : delta_phi_fx = L_shr( delta_phi_fx, sub( sub( 31, delta_phi_e ), 22 ) ); // Q22
1018 :
1019 285727 : *phi_hat_fx = L_add( delta_phi_fx, dd_fx ); // Q22
1020 285727 : move32();
1021 :
1022 285727 : return id_phi; // Q0
1023 : }
1024 :
1025 :
1026 : /*-------------------------------------------------------------------------
1027 : * deindex_sph_idx()
1028 : *
1029 : * deindex the MASA metadata from the input metadata file
1030 : *------------------------------------------------------------------------*/
1031 :
1032 5932416 : void deindex_sph_idx_fx(
1033 : const UWord16 sphIndex, /* i : Spherical index */
1034 : const SPHERICAL_GRID_DATA *gridData, /* i : Prepared spherical grid */
1035 : Word32 *theta_fx, /* o : Elevation Q22*/
1036 : Word32 *phi_fx /* o : Azimuth Q22 */
1037 : )
1038 : {
1039 : Word32 ba_crt_fx, del_crt_fx, div_crt_fx, a4_crt_fx;
1040 : Word32 estim_fx;
1041 : Word32 base_low, base_up;
1042 : Word16 n_crt;
1043 : Word16 id_th;
1044 : Word16 sign_theta;
1045 : Word16 id_phi;
1046 5932416 : Word16 no_th = gridData->no_theta;
1047 5932416 : const Word16 *n = gridData->no_phi;
1048 : const Word32 ba_fx[3] = { 1793476992, 1044259584, 1030463872 }; /* Q23 */
1049 : const Word32 del_fx[3] = { 819022016, 1332105216, 1458249984 }; /* Q10 */
1050 : const Word32 div_fx[3] = { -510376000, -216763104, -197676320 }; /* Q31 */
1051 : const Word32 a4_fx[3] = { -564741248, -1329702144, -1458092544 }; /* Q26 */
1052 5932416 : const UWord16 limit_index1 = 64964, limit_index2 = 47870;
1053 : Word32 tmp32;
1054 : Word16 tmp16, tmp_e;
1055 5932416 : move16();
1056 5932416 : move16();
1057 5932416 : move16();
1058 5932416 : move32();
1059 5932416 : move32();
1060 5932416 : move32();
1061 5932416 : move32();
1062 5932416 : move32();
1063 5932416 : move32();
1064 5932416 : move32();
1065 5932416 : move32();
1066 5932416 : move32();
1067 5932416 : move32();
1068 5932416 : move32();
1069 5932416 : move32();
1070 :
1071 5932416 : IF( GE_32( sphIndex, limit_index1 ) )
1072 : {
1073 15726 : ba_crt_fx = ba_fx[2];
1074 15726 : move32();
1075 15726 : div_crt_fx = div_fx[2];
1076 15726 : move32();
1077 15726 : a4_crt_fx = a4_fx[2];
1078 15726 : move32();
1079 15726 : del_crt_fx = del_fx[2];
1080 15726 : move32();
1081 : }
1082 5916690 : ELSE IF( GE_32( sphIndex, limit_index2 ) )
1083 : {
1084 545381 : ba_crt_fx = ba_fx[1];
1085 545381 : move32();
1086 545381 : div_crt_fx = div_fx[1];
1087 545381 : move32();
1088 545381 : a4_crt_fx = a4_fx[1];
1089 545381 : move32();
1090 545381 : del_crt_fx = del_fx[1];
1091 545381 : move32();
1092 : }
1093 : ELSE
1094 : {
1095 5371309 : ba_crt_fx = ba_fx[0];
1096 5371309 : move32();
1097 5371309 : div_crt_fx = div_fx[0];
1098 5371309 : move32();
1099 5371309 : a4_crt_fx = a4_fx[0];
1100 5371309 : move32();
1101 5371309 : del_crt_fx = del_fx[0];
1102 5371309 : move32();
1103 : }
1104 5932416 : tmp32 = Mpy_32_32( a4_crt_fx, L_shl_sat( sphIndex, Q15 ) ); /* Q10 */
1105 5932416 : tmp32 = L_add( del_crt_fx, tmp32 ); /* Q10 */
1106 5932416 : tmp16 = Q31 - Q10;
1107 5932416 : move16();
1108 5932416 : tmp32 = Sqrt32( tmp32, &tmp16 ); // Q31-tmp16
1109 5932416 : tmp32 = Mpy_32_32( div_crt_fx, tmp32 ); // Q31-tmp16
1110 5932416 : tmp32 = L_shr( tmp32, sub( Q8, tmp16 ) ); /* Q23 */
1111 5932416 : estim_fx = L_add( ba_crt_fx, tmp32 ); /* Q23 */
1112 :
1113 5932416 : if ( GT_32( estim_fx, MASA_NO_CIRCLES_Q23 ) )
1114 : {
1115 640 : estim_fx = MASA_NO_CIRCLES_Q23; // Q23
1116 640 : move32();
1117 : }
1118 :
1119 5932416 : assert( estim_fx > 0 );
1120 5932416 : id_th = sub( extract_l( L_shr_r( estim_fx, Q23 ) ), 1 ); /* Q0 */
1121 5932416 : if ( id_th < 0 )
1122 : {
1123 0 : id_th = 0;
1124 0 : move16();
1125 : }
1126 :
1127 5932416 : IF( id_th == 0 )
1128 : {
1129 69244 : base_low = 0;
1130 69244 : move32();
1131 69244 : base_up = n[0];
1132 69244 : move32();
1133 : }
1134 : ELSE
1135 : {
1136 5863172 : base_low = n[0];
1137 5863172 : move32();
1138 5863172 : IF( GE_16( id_th, 2 ) )
1139 : {
1140 5574546 : IF( EQ_16( id_th, 2 ) )
1141 : {
1142 293749 : base_low = L_add( base_low, L_shl( estim_ceil[id_th], 1 ) ); /* Q0 */
1143 : }
1144 : ELSE
1145 : {
1146 5280797 : base_low = L_add( base_low, L_shl( estim_round[id_th], 1 ) ); /* Q0 */
1147 : }
1148 : }
1149 5863172 : base_up = L_add( base_low, L_shl( n[id_th], 1 ) );
1150 : }
1151 :
1152 5932416 : sign_theta = 1;
1153 5932416 : move16();
1154 :
1155 5932416 : n_crt = n[id_th];
1156 5932416 : move16();
1157 5932416 : IF( LT_32( sphIndex, base_low ) )
1158 : {
1159 299227 : id_th = sub( id_th, 1 );
1160 299227 : n_crt = n[id_th];
1161 299227 : move16();
1162 299227 : IF( id_th == 0 )
1163 : {
1164 74926 : base_low = 0;
1165 74926 : move32();
1166 74926 : base_up = n_crt;
1167 74926 : move32();
1168 : }
1169 : ELSE
1170 : {
1171 224301 : base_up = base_low;
1172 224301 : move32();
1173 224301 : base_low = L_sub( base_low, shl( n[id_th], 1 ) );
1174 : }
1175 299227 : assert( sphIndex >= base_low );
1176 : }
1177 5633189 : ELSE IF( GE_32( sphIndex, base_up ) )
1178 : {
1179 188638 : id_th = add( id_th, 1 );
1180 188638 : n_crt = n[id_th];
1181 188638 : move16();
1182 188638 : base_low = base_up;
1183 188638 : move32();
1184 188638 : base_up = L_add( base_up, shl( n_crt, 1 ) );
1185 188638 : assert( sphIndex < base_up );
1186 : }
1187 :
1188 5932416 : id_phi = extract_l( L_sub( sphIndex, base_low ) );
1189 5932416 : IF( GE_32( L_sub( sphIndex, base_low ), n_crt ) )
1190 : {
1191 3578401 : id_phi = sub( id_phi, n_crt );
1192 3578401 : sign_theta = -1;
1193 3578401 : move16();
1194 : }
1195 :
1196 5932416 : IF( id_th == 0 )
1197 : {
1198 144170 : *theta_fx = 0;
1199 144170 : move32();
1200 144170 : tmp32 = imult3216( sphIndex, 360 );
1201 144170 : tmp16 = BASOP_Util_Divide3232_Scale( tmp32, n_crt, &tmp_e );
1202 144170 : tmp32 = L_shl( tmp16, add( Q7, tmp_e ) ); /* Q22 */
1203 144170 : *phi_fx = L_sub( tmp32, 180 << Q22 ); /* Q22 */
1204 144170 : move32();
1205 : }
1206 : ELSE
1207 : {
1208 5788246 : IF( EQ_16( id_th, sub( no_th, 1 ) ) )
1209 : {
1210 273 : id_phi = 0;
1211 273 : move16();
1212 273 : *phi_fx = -754974720; /* -180 in Q22 */
1213 273 : move32();
1214 273 : *theta_fx = L_shl( L_mult0( 90, sign_theta ), Q22 ); /* Q22 */
1215 273 : move32();
1216 : }
1217 : ELSE
1218 : {
1219 5787973 : *theta_fx = Mpy_32_32( L_shl( id_th, Q22 ), MASA_ANGLE_AT_EQUATOR_DEG_Q31 ); /* Q22 */
1220 5787973 : move32();
1221 5787973 : if ( EQ_16( sign_theta, -1 ) )
1222 : {
1223 3578217 : *theta_fx = L_negate( *theta_fx ); /* Q22 */
1224 3578217 : move32();
1225 : }
1226 5787973 : IF( id_th % 2 == 0 )
1227 : {
1228 2826907 : tmp32 = L_mult0( id_phi, 360 );
1229 2826907 : tmp16 = BASOP_Util_Divide3232_Scale( tmp32, n_crt, &tmp_e );
1230 2826907 : tmp32 = L_shl( tmp16, add( Q7, tmp_e ) ); /* Q22 */
1231 2826907 : *phi_fx = L_sub( tmp32, 180 << Q22 ); /* Q22 */
1232 2826907 : move32();
1233 : }
1234 : ELSE
1235 : {
1236 2961066 : tmp32 = L_add( L_mult0( id_phi, 360 ), 180 );
1237 2961066 : tmp16 = BASOP_Util_Divide3232_Scale( tmp32, n_crt, &tmp_e );
1238 2961066 : tmp32 = L_shl( tmp16, add( Q7, tmp_e ) ); /* Q22 */
1239 2961066 : *phi_fx = L_sub( tmp32, 180 << Q22 ); /* Q22 */
1240 2961066 : move32();
1241 : }
1242 : }
1243 : }
1244 5932416 : return;
1245 : }
1246 : /*---------------------------------------------------------------
1247 : * valid_ratio_index()
1248 : *
1249 : * Checking validity of the index of an ISM ratio index vector,
1250 : * within the indexing function.
1251 : *---------------------------------------------------------------*/
1252 :
1253 : /*! r: valid or not 1/0 */
1254 1833696 : Word16 valid_ratio_index_fx(
1255 : Word16 index, /* i : index to be checked */
1256 : const Word16 K, /* i : L1 norm to check against */
1257 : const Word16 len /* i : vector length */
1258 : )
1259 : {
1260 : Word16 out;
1261 : Word16 i, sum, elem;
1262 : Word16 base[4];
1263 :
1264 1833696 : sum = 0;
1265 1833696 : move16();
1266 1833696 : set16_fx( base, 1, len );
1267 :
1268 5467216 : FOR( i = 1; i < len; i++ )
1269 : {
1270 3633520 : base[i] = i_mult( base[i - 1], 10 );
1271 3633520 : move16();
1272 : }
1273 1833696 : sum = 0;
1274 1833696 : move16();
1275 7300912 : FOR( i = len - 1; i >= 0; i-- )
1276 : {
1277 5467216 : IF( index == 0 )
1278 : {
1279 229017 : elem = 0;
1280 229017 : move16();
1281 : }
1282 : ELSE
1283 : {
1284 5238199 : elem = idiv1616( index, base[i] );
1285 : }
1286 5467216 : sum = add( sum, elem );
1287 5467216 : index = sub( index, i_mult( elem, base[i] ) );
1288 : }
1289 1833696 : IF( LE_16( sum, K ) )
1290 : {
1291 502747 : out = 1;
1292 502747 : move16();
1293 : }
1294 : ELSE
1295 : {
1296 1330949 : out = 0;
1297 1330949 : move16();
1298 : }
1299 :
1300 1833696 : return out;
1301 : }
1302 :
1303 :
1304 : /*---------------------------------------------------------------
1305 : * reconstruct_ism_ratios()
1306 : *
1307 : * Obtains ISM ratio values from the quantized indexes
1308 : *---------------------------------------------------------------*/
1309 :
1310 60559 : void reconstruct_ism_ratios_fx(
1311 : Word16 *ratio_ism_idx, /* i : index vector Q0 */
1312 : const Word16 nchan_ism, /* i : number of components/objects Q0 */
1313 : const Word32 step, /* i : quantization step Q31 */
1314 : Word32 *q_energy_ratio_ism /* o : reconstructed ISM values Q30 */
1315 : )
1316 : {
1317 : Word16 i;
1318 : Word32 sum;
1319 :
1320 60559 : sum = 0;
1321 60559 : move32();
1322 :
1323 213350 : FOR( i = 0; i < nchan_ism - 1; i++ )
1324 : {
1325 152791 : q_energy_ratio_ism[i] = W_extract_l( W_shr( W_mult_32_16( step, ratio_ism_idx[i] ), 2 ) ); // q0 + q31 + 1 - 2 = q30;
1326 152791 : move32();
1327 :
1328 152791 : sum = L_add( sum, q_energy_ratio_ism[i] ); // Q30
1329 : }
1330 :
1331 60559 : q_energy_ratio_ism[nchan_ism - 1] = L_sub( ONE_IN_Q30, sum );
1332 60559 : move32();
1333 :
1334 60559 : if ( q_energy_ratio_ism[nchan_ism - 1] < 0 )
1335 : {
1336 0 : q_energy_ratio_ism[nchan_ism - 1] = 0;
1337 0 : move32();
1338 : }
1339 :
1340 60559 : return;
1341 : }
1342 :
1343 :
1344 : /*---------------------------------------------------------------
1345 : * ivas_omasa_modify_masa_energy_ratios()
1346 : *
1347 : * Updates energy ratios by taking into account the MASA content contribution
1348 : * to the total audio scene
1349 : *---------------------------------------------------------------*/
1350 :
1351 3696 : void ivas_omasa_modify_masa_energy_ratios_fx(
1352 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
1353 : Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_MAXIMUM_CODING_SUBBANDS] /* Q30 */ )
1354 : {
1355 : Word16 i, m, d, b;
1356 :
1357 18480 : FOR( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ )
1358 : {
1359 14784 : IF( EQ_16( hQMetaData->q_direction[0].cfg.nblocks, 1 ) )
1360 : {
1361 4740 : i = 0;
1362 4740 : move16();
1363 : }
1364 : ELSE
1365 : {
1366 10044 : i = m;
1367 10044 : move16();
1368 : }
1369 :
1370 108616 : FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ )
1371 : {
1372 208544 : FOR( d = 0; d < hQMetaData->no_directions; d++ )
1373 : {
1374 114712 : hQMetaData->q_direction[d].band_data[b].energy_ratio_fx[m] = L_shl(
1375 114712 : Mpy_32_32( hQMetaData->q_direction[d].band_data[b].energy_ratio_fx[m],
1376 114712 : masa_to_total_energy_ratio_fx[i][b] ),
1377 : 1 ); // Q30 + Q30 - 31 = Q29 + 1 = Q30
1378 114712 : move32();
1379 : }
1380 : }
1381 : }
1382 :
1383 3696 : return;
1384 : }
1385 :
1386 :
1387 : /*---------------------------------------------------------------
1388 : * distribute_evenly_ism()
1389 : *
1390 : * Obtain ISM ratio indexes for even content distribution bbetween objects
1391 : *---------------------------------------------------------------*/
1392 :
1393 7192 : void distribute_evenly_ism_fx(
1394 : Word16 *idx, /* o : index values Q0 */
1395 : const Word16 K, /* i : sum of indexes Q0*/
1396 : const Word16 nchan_ism /* i : number of objects Q0 */
1397 : )
1398 : {
1399 : Word16 i;
1400 : Word16 sum;
1401 :
1402 7192 : sum = 0;
1403 7192 : move16();
1404 31486 : FOR( i = 0; i < nchan_ism; i++ )
1405 : {
1406 24294 : IF( K == 0 )
1407 : {
1408 0 : idx[i] = 0;
1409 0 : move16();
1410 : }
1411 : ELSE
1412 : {
1413 24294 : idx[i] = idiv1616( K, nchan_ism ); // Q0
1414 24294 : move16();
1415 : }
1416 24294 : sum = add( sum, idx[i] );
1417 : }
1418 :
1419 7192 : assert( LE_16( sum, K ) );
1420 :
1421 7192 : i = 0;
1422 7192 : move16();
1423 21468 : WHILE( LT_16( sum, K ) )
1424 : {
1425 14276 : if ( EQ_16( i, nchan_ism ) )
1426 : {
1427 0 : i = 0;
1428 0 : move16();
1429 : }
1430 14276 : idx[i] = add( idx[i], 1 );
1431 14276 : move16();
1432 14276 : sum = add( sum, 1 );
1433 14276 : i = add( i, 1 );
1434 : }
1435 :
1436 7192 : return;
1437 : }
1438 :
1439 :
1440 : /*---------------------------------------------------------------
1441 : * calculate_cpe_brate_MASA_ISM()
1442 : *
1443 : * Calculates bitrate for MASA_ISM mode that is not used for separated objects,
1444 : * * but for the CPE part (metadata included)
1445 : *---------------------------------------------------------------*/
1446 :
1447 : /*! r: CPE bitrate value */
1448 18111 : Word32 calculate_cpe_brate_MASA_ISM_fx(
1449 : const ISM_MODE ism_mode, /* i : ism mode */
1450 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
1451 : const Word16 nchan_ism /* i : number of objects */
1452 : )
1453 : {
1454 : Word32 cpe_brate;
1455 : Word16 k, sce_id;
1456 :
1457 18111 : k = 0;
1458 18111 : move16();
1459 :
1460 201275 : WHILE( LT_16( k, SIZE_IVAS_BRATE_TBL ) && NE_32( ivas_total_brate, ivas_brate_tbl[k] ) )
1461 : {
1462 183164 : test();
1463 183164 : k = add( k, 1 );
1464 : }
1465 :
1466 18111 : test();
1467 18111 : IF( EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
1468 : {
1469 4691 : cpe_brate = L_sub( ivas_total_brate, sep_object_brate[k - 2][0] ); /* take data from the first column */
1470 : }
1471 13420 : ELSE IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) )
1472 : {
1473 12975 : cpe_brate = ivas_total_brate;
1474 12975 : move32();
1475 :
1476 48081 : FOR( sce_id = 0; sce_id < nchan_ism; sce_id++ )
1477 : {
1478 35106 : cpe_brate = L_sub( cpe_brate, sep_object_brate[k - 2][nchan_ism - 1] );
1479 : }
1480 : }
1481 : ELSE
1482 : {
1483 445 : cpe_brate = ivas_total_brate;
1484 445 : move32();
1485 : }
1486 :
1487 18111 : return cpe_brate;
1488 : }
|