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.h"
38 : #include "ivas_cnst.h"
39 : #include "ivas_prot.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_stat_dec.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include "wmc_auto.h"
46 :
47 : /*---------------------------------------------------------------
48 : * Local constants
49 : *---------------------------------------------------------------*/
50 :
51 : #define MASA_EXTRA_BAND_META_BITS 40
52 :
53 : #define MASA_SMALL_INC_META_BITS 10
54 :
55 :
56 : /*---------------------------------------------------------------
57 : * Local prototypes
58 : *---------------------------------------------------------------*/
59 :
60 : static int16_t quantize_theta_masa( float x, const int16_t no_cb, float *xhat );
61 :
62 : static int16_t quantize_phi_masa( float phi, const int16_t flag_delta, float *phi_hat, const int16_t n );
63 :
64 :
65 : /*---------------------------------------------------------------
66 : * ivas_masa_setup()
67 : *
68 : * Set-up MASA coding elements and bitrates
69 : *---------------------------------------------------------------*/
70 :
71 199096 : void ivas_masa_set_elements(
72 : const int32_t ivas_total_brate, /* i : IVAS total bitrate */
73 : const int16_t mc_mode, /* i : MC format mode */
74 : const int16_t nchan_transport, /* i : number of MASA input/transport channels */
75 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
76 : int16_t *element_mode, /* o : element mode */
77 : int16_t *nSCE, /* o : number of SCEs */
78 : int16_t *nCPE, /* o : number of CPEs */
79 : const int16_t ivas_format, /* i : IVAS format */
80 : const ISM_MODE ism_mode, /* i : ISM mode */
81 : const int32_t ism_total_brate /* i : initial ISM total bitrate */
82 : )
83 : {
84 199096 : if ( nchan_transport == 2 )
85 : {
86 110351 : if ( ivas_total_brate >= MCMASA_SEPARATE_BRATE && mc_mode == MC_MODE_MCMASA )
87 : {
88 1976 : *nCPE = 1;
89 1976 : *nSCE = 1;
90 :
91 1976 : *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*/
92 : }
93 108375 : else if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE )
94 : {
95 31542 : *nCPE = 1;
96 :
97 31542 : if ( *element_mode == -1 )
98 : {
99 20832 : *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */
100 : }
101 31542 : if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO )
102 : {
103 21022 : *element_mode = IVAS_CPE_MDCT;
104 21022 : if ( ( ism_mode == ISM_MASA_MODE_DISC || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) && ( ivas_total_brate - ism_total_brate < MIN_BRATE_MDCT_STEREO ) )
105 : {
106 2421 : *element_mode = IVAS_CPE_DFT;
107 : }
108 : }
109 : }
110 : else
111 : {
112 76833 : *nCPE = 1;
113 76833 : *nSCE = 0;
114 :
115 76833 : if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO )
116 : {
117 35596 : *element_mode = IVAS_CPE_MDCT;
118 : }
119 : }
120 110351 : hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC );
121 110351 : if ( ivas_format == MASA_ISM_FORMAT && ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_DISC ) )
122 : {
123 31542 : hQMetaData->bits_frame_nominal -= (int16_t) ( ism_total_brate / FRAMES_PER_SEC );
124 : }
125 : }
126 88745 : else if ( nchan_transport == 1 )
127 : {
128 88745 : *nCPE = 0;
129 88745 : *nSCE = 1;
130 :
131 88745 : if ( ivas_total_brate == IVAS_13k2 )
132 : {
133 15601 : hQMetaData->bits_frame_nominal = ACELP_9k60 / FRAMES_PER_SEC;
134 : }
135 73144 : else if ( ivas_total_brate <= IVAS_16k4 )
136 : {
137 5261 : hQMetaData->bits_frame_nominal = ACELP_13k20 / FRAMES_PER_SEC;
138 : }
139 67883 : else if ( ivas_total_brate <= IVAS_24k4 )
140 : {
141 29275 : hQMetaData->bits_frame_nominal = ACELP_16k40 / FRAMES_PER_SEC;
142 : }
143 38608 : else if ( ivas_total_brate <= IVAS_32k )
144 : {
145 11539 : hQMetaData->bits_frame_nominal = ACELP_24k40 / FRAMES_PER_SEC;
146 : }
147 : else
148 : {
149 27069 : hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC );
150 : }
151 88745 : *element_mode = IVAS_SCE;
152 : }
153 : else
154 : {
155 0 : assert( !"MASA number of transport channels must be 1, or 2" );
156 : }
157 :
158 199096 : return;
159 : }
160 :
161 :
162 : /*---------------------------------------------------------------
163 : * generate_gridEq()
164 : *
165 : * generate Spherical grid
166 : *---------------------------------------------------------------*/
167 :
168 782 : void generate_gridEq(
169 : SPHERICAL_GRID_DATA *data /* o : data structure for grid */
170 : )
171 : {
172 : int32_t cum_n, cum_n_prev;
173 : float theta;
174 : int16_t i;
175 : int16_t *n;
176 :
177 782 : n = data->no_phi;
178 782 : n[0] = MASA_NO_POINTS_EQUATOR;
179 :
180 782 : cum_n_prev = 0;
181 :
182 94622 : for ( i = 1; i < MASA_NO_CIRCLES; i++ )
183 : {
184 93840 : theta = MASA_ANGLE_AT_EQUATOR * (float) ( i + 0.5f );
185 93840 : if ( i == 1 )
186 : {
187 782 : cum_n = 2 * (int32_t) ceilf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
188 : }
189 : else
190 : {
191 93058 : cum_n = 2 * (int32_t) roundf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
192 : }
193 93840 : n[i] = (int16_t) ( ( cum_n - cum_n_prev ) >> 1 );
194 93840 : cum_n_prev = cum_n;
195 : }
196 782 : n[i] = 1;
197 782 : data->no_theta = i + 1;
198 :
199 782 : return;
200 : }
201 :
202 :
203 : /*---------------------------------------------------------------
204 : * ivas_masa_set_coding_config()
205 : *
206 : * Sets MASA codec parameters based on bitrate, number of directions,
207 : * and other metadata properties.
208 : *---------------------------------------------------------------*/
209 :
210 187391 : void ivas_masa_set_coding_config(
211 : MASA_CODEC_CONFIG *config, /* i/o: MASA coding config structure */
212 : int16_t *band_mapping, /* o : Band mapping used */
213 : const int32_t ivas_total_brate, /* i : IVAS total bitrate */
214 : const int16_t nchan_transport, /* i : number of transport channels (mono/stereo) */
215 : const uint8_t isMcMasa /* i : toggle for selecting mcMASA specific config */
216 : )
217 : {
218 : int16_t i;
219 : uint8_t nbands;
220 : uint8_t nTwoDirBands;
221 : const int16_t *masa_bits_table;
222 :
223 : /* When coming into this function, these values should be already set:
224 : * joinedSubframes;
225 : * useCoherence;
226 : * numberOfDirections;
227 : */
228 :
229 : /* Setup coding parameters based on the bitrate, transport channel count, subframe metadata information,
230 : * and number of directions in metadata. */
231 187391 : nbands = 0;
232 187391 : nTwoDirBands = 0;
233 187391 : i = 0;
234 :
235 : /* First select correct bit budget table */
236 187391 : masa_bits_table = masa_bits;
237 187391 : if ( isMcMasa )
238 : {
239 35040 : masa_bits_table = mcmasa_bits;
240 : }
241 152351 : else if ( ivas_total_brate < IVAS_48k && nchan_transport == 2 )
242 : {
243 45785 : masa_bits_table = masa_bits_LR_stereo;
244 : }
245 :
246 1174865 : while ( nbands == 0 && i < IVAS_NUM_ACTIVE_BRATES )
247 : {
248 987474 : if ( ivas_total_brate <= ivas_brate_tbl[i + SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES] )
249 : {
250 : int16_t idx_bands;
251 187391 : if ( ivas_total_brate < IVAS_48k && nchan_transport == 2 && i > 3 )
252 : {
253 : /* because it uses the bitallocation for the lower bit rates from 'masa_bits_LR_stereo' and it has 4 elements */
254 1498 : i = 3;
255 : }
256 187391 : idx_bands = i;
257 :
258 187391 : if ( config->numberOfDirections > 1 )
259 : {
260 27192 : nTwoDirBands = config->joinedSubframes ? masa_twodir_bands_joined[i] : masa_twodir_bands[i];
261 :
262 27192 : if ( ( ivas_total_brate > IVAS_96k && !config->joinedSubframes ) || ( ivas_total_brate > IVAS_80k && config->joinedSubframes ) )
263 : {
264 15471 : idx_bands--;
265 : }
266 : }
267 :
268 187391 : if ( config->joinedSubframes )
269 : {
270 21840 : nbands = masa_joined_nbands[idx_bands];
271 : }
272 : else
273 : {
274 165551 : nbands = masa_nbands[idx_bands];
275 : }
276 :
277 187391 : config->max_metadata_bits = masa_bits_table[i];
278 :
279 187391 : if ( ivas_total_brate == IVAS_64k && config->numberOfDirections > 1 )
280 : {
281 : /* At 64k, we increase metadata bit budget when there is two directions present. */
282 2182 : config->max_metadata_bits += MASA_EXTRA_BAND_META_BITS;
283 : }
284 :
285 187391 : if ( ( ( ivas_total_brate == IVAS_32k && nchan_transport == 2 ) || ivas_total_brate == IVAS_48k ) && config->joinedSubframes )
286 : {
287 : /* At 32k and 48k, we increase metadata bit budget when joinedSubframes. */
288 4459 : config->max_metadata_bits += ( MASA_SMALL_INC_META_BITS );
289 : }
290 : }
291 987474 : i++;
292 : }
293 187391 : config->numCodingBands = nbands;
294 187391 : config->numTwoDirBands = nTwoDirBands;
295 :
296 : #ifdef DEBUGGING
297 : assert( nbands > 0 );
298 : #endif
299 187391 : if ( config->joinedSubframes == TRUE )
300 : {
301 21840 : config->mergeRatiosOverSubframes = FALSE;
302 : }
303 : else
304 : {
305 165551 : config->mergeRatiosOverSubframes = TRUE;
306 : }
307 :
308 : /* Setup frequency band mapping based on the number of used coding bands */
309 187391 : switch ( config->numCodingBands )
310 : {
311 142665 : case 5:
312 142665 : mvs2s( MASA_band_mapping_24_to_5, band_mapping, 5 + 1 );
313 142665 : break;
314 13637 : case 8:
315 13637 : mvs2s( MASA_band_mapping_24_to_8, band_mapping, 8 + 1 );
316 13637 : break;
317 7948 : case 12:
318 7948 : mvs2s( MASA_band_mapping_24_to_12, band_mapping, 12 + 1 );
319 7948 : break;
320 8717 : case 18:
321 8717 : mvs2s( MASA_band_mapping_24_to_18, band_mapping, 18 + 1 );
322 8717 : break;
323 14424 : case MASA_FREQUENCY_BANDS:
324 : /* With input count of bands, no mapping is needed but for unified processing later, we store normal mapping */
325 375024 : for ( i = 0; i < MASA_FREQUENCY_BANDS + 1; i++ )
326 : {
327 360600 : band_mapping[i] = i;
328 : }
329 14424 : break;
330 0 : default:
331 0 : assert( 0 && "Error: The number of MASA coding bands is not supported" );
332 : }
333 :
334 187391 : config->useCoherence = TRUE;
335 187391 : if ( ( !isMcMasa && ivas_total_brate < IVAS_48k ) || ( isMcMasa && ivas_total_brate < IVAS_16k4 ) )
336 : {
337 77384 : config->useCoherence = FALSE;
338 : }
339 :
340 187391 : return;
341 : }
342 :
343 :
344 : /*---------------------------------------------------------------
345 : * masa_sample_rate_band_correction()
346 : *
347 : *
348 : *---------------------------------------------------------------*/
349 :
350 187391 : void masa_sample_rate_band_correction(
351 : MASA_CODEC_CONFIG *config, /* i/o: MASA codec config */
352 : int16_t *band_mapping, /* i/o: Band mapping used and modified */
353 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */
354 : const uint8_t maxBand, /* i : max band */
355 : uint8_t is_encoder, /* i : signals if called at encoder */
356 : MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */
357 : )
358 : {
359 : uint8_t band, sf;
360 : int16_t highBand;
361 : uint8_t numBands48k;
362 :
363 187391 : numBands48k = config->numCodingBands;
364 :
365 1412516 : for ( band = 1; band < config->numCodingBands + 1; band++ )
366 : {
367 1412516 : highBand = band_mapping[band];
368 :
369 1412516 : if ( highBand >= maxBand )
370 : {
371 187391 : config->numCodingBands = band;
372 187391 : hQMetaData->numCodingBands = band;
373 :
374 187391 : if ( is_encoder )
375 : {
376 2276 : if ( hQMetaData->q_direction->cfg.nbands > band )
377 : {
378 300 : hQMetaData->q_direction->cfg.nbands = band;
379 : }
380 2276 : if ( hQMetaData->no_directions == 2 && hQMetaData->q_direction[1].cfg.nbands > band )
381 : {
382 300 : hQMetaData->q_direction[1].cfg.nbands = band;
383 : }
384 : }
385 :
386 187391 : band_mapping[band] = maxBand;
387 :
388 187391 : break;
389 : }
390 : }
391 :
392 : /* Set rest of the bands to zero in qmetadata. */
393 195754 : for ( ; band < numBands48k; band++ )
394 : {
395 41815 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
396 : {
397 33452 : hQMetaData->q_direction[0].band_data[band].azimuth[sf] = 0.0f;
398 33452 : hQMetaData->q_direction[0].band_data[band].elevation[sf] = 0.0f;
399 33452 : hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = 0.0f;
400 :
401 33452 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL )
402 : {
403 33452 : hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u;
404 : }
405 :
406 33452 : if ( hQMetaData->no_directions == 2 )
407 : {
408 4512 : hQMetaData->q_direction[1].band_data[band].azimuth[sf] = 0.0f;
409 4512 : hQMetaData->q_direction[1].band_data[band].elevation[sf] = 0.0f;
410 4512 : hQMetaData->q_direction[1].band_data[band].energy_ratio[sf] = 0.0f;
411 :
412 4512 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL )
413 : {
414 4512 : hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = 0u;
415 : }
416 : }
417 :
418 33452 : if ( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL )
419 : {
420 33452 : hQMetaData->surcoh_band_data[band].surround_coherence[sf] = 0u;
421 : }
422 : }
423 :
424 8363 : if ( hQMetaData->no_directions == 2 )
425 : {
426 1128 : hQMetaData->twoDirBands[band] = 0;
427 : }
428 : }
429 :
430 187391 : if ( hExtOutMeta != NULL )
431 : {
432 : /* in decoder, zero the EXT out MASA meta buffer */
433 79305 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
434 : {
435 1048284 : for ( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ )
436 : {
437 984840 : hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT;
438 984840 : hExtOutMeta->directToTotalRatio[0][sf][band] = 0u;
439 984840 : hExtOutMeta->spreadCoherence[0][sf][band] = 0u;
440 :
441 984840 : hExtOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
442 984840 : hExtOutMeta->directToTotalRatio[1][sf][band] = 0u;
443 984840 : hExtOutMeta->spreadCoherence[1][sf][band] = 0u;
444 :
445 984840 : hExtOutMeta->surroundCoherence[sf][band] = 0u;
446 984840 : hExtOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX;
447 : }
448 : }
449 : }
450 :
451 187391 : return;
452 : }
453 :
454 :
455 : /*-------------------------------------------------------------------------
456 : * index_theta_phi_16()
457 : *
458 : *
459 : *------------------------------------------------------------------------*/
460 :
461 : /*! r: output index for direction */
462 785568 : uint16_t index_theta_phi_16(
463 : float *p_theta, /* i/o: input elevation to be indexed */
464 : float *p_phi, /* i/o: input azimuth to be indexed */
465 : const SPHERICAL_GRID_DATA *gridData /* i : generated grid data */
466 : )
467 : {
468 : float abs_theta;
469 : int16_t sign_th, id_phi, id_th;
470 : uint16_t idx_sph;
471 : uint16_t cum_n;
472 : float theta_hat, phi_hat;
473 : float theta, phi;
474 :
475 785568 : theta = *p_theta;
476 785568 : phi = *p_phi;
477 785568 : phi_hat = 0;
478 785568 : theta_hat = 0;
479 785568 : phi = phi + 180;
480 :
481 785568 : if ( theta < 0 )
482 : {
483 224838 : abs_theta = -theta;
484 224838 : sign_th = -1;
485 : }
486 : else
487 : {
488 560730 : abs_theta = theta;
489 560730 : sign_th = 1;
490 : }
491 :
492 785568 : id_th = quantize_theta_masa( abs_theta, gridData->no_theta, &theta_hat );
493 785568 : if ( gridData->no_theta > 1 )
494 : {
495 785568 : if ( gridData->no_phi[id_th] > 1 )
496 : {
497 784979 : id_phi = quantize_phi_masa( phi, ( id_th % 2 == 1 ), &phi_hat, gridData->no_phi[id_th] );
498 : }
499 : else
500 : {
501 589 : id_phi = 0;
502 589 : phi_hat = 180;
503 : }
504 : }
505 : else
506 : {
507 0 : id_phi = quantize_phi_masa( phi, ( id_th % 2 == 1 ), &phi_hat, gridData->no_phi[id_th] );
508 : }
509 785568 : *p_theta = sign_th * theta_hat;
510 785568 : *p_phi = phi_hat - 180;
511 :
512 : /* Starting from Equator, alternating positive and negative */
513 785568 : if ( id_th == 0 )
514 : {
515 378051 : idx_sph = id_phi;
516 : }
517 : else
518 : {
519 407517 : if ( id_th == gridData->no_theta - 1 )
520 : {
521 589 : idx_sph = 65534 + ( sign_th < 0 );
522 : }
523 : else
524 : {
525 406928 : theta = MASA_ANGLE_AT_EQUATOR * (float) ( id_th + 0.5f );
526 406928 : if ( id_th == 1 )
527 : {
528 15141 : cum_n = 2 * (uint16_t) ceilf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
529 : }
530 : else
531 : {
532 391787 : cum_n = 2 * (uint16_t) roundf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
533 : }
534 :
535 406928 : cum_n += gridData->no_phi[0];
536 :
537 406928 : if ( sign_th > 0 )
538 : {
539 184159 : cum_n -= 2 * gridData->no_phi[id_th];
540 : }
541 : else
542 : {
543 222769 : cum_n -= gridData->no_phi[id_th];
544 : }
545 406928 : idx_sph = cum_n + id_phi;
546 : }
547 : }
548 :
549 785568 : return idx_sph;
550 : }
551 :
552 :
553 : /*-------------------------------------------------------------------------
554 : * quantize_phi_masa()
555 : *
556 : *
557 : *------------------------------------------------------------------------*/
558 :
559 : /*! r: output index */
560 785568 : static int16_t quantize_theta_masa(
561 : float x, /* i : theta value to be quantized */
562 : const int16_t no_cb, /* i : number of codewords */
563 : float *xhat /* o : quantized value */
564 : )
565 : {
566 : int16_t imin;
567 : float diff1, diff2;
568 :
569 785568 : imin = (int16_t) ( x * MASA_INV_ANGLE_AT_EQUATOR_DEG + 0.5f );
570 :
571 785568 : if ( imin >= no_cb - 1 )
572 : {
573 591 : imin = no_cb - 1;
574 591 : diff1 = x - 90;
575 591 : diff2 = x - MASA_ANGLE_AT_EQUATOR_DEG * ( imin - 1 );
576 591 : if ( fabsf( diff1 ) > fabsf( diff2 ) )
577 : {
578 2 : imin--;
579 2 : *xhat = imin * MASA_ANGLE_AT_EQUATOR_DEG;
580 : }
581 : else
582 : {
583 589 : *xhat = 90;
584 : }
585 : }
586 : else
587 : {
588 784977 : *xhat = imin * MASA_ANGLE_AT_EQUATOR_DEG;
589 : }
590 :
591 785568 : return imin;
592 : }
593 :
594 :
595 : /*-------------------------------------------------------------------------
596 : * quantize_phi_masa()
597 : *
598 : *
599 : *------------------------------------------------------------------------*/
600 :
601 : /*! r: index azimuth */
602 784979 : static int16_t quantize_phi_masa(
603 : float phi, /* i : azimuth value */
604 : const int16_t flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */
605 : float *phi_hat, /* o : quantized azimuth */
606 : const int16_t n /* i : azimuth codebook size */
607 : )
608 : {
609 : int16_t id_phi;
610 : float dd;
611 : float delta_phi;
612 :
613 784979 : delta_phi = 360.0f / (float) n;
614 :
615 784979 : if ( n == 1 )
616 : {
617 0 : *phi_hat = 0;
618 :
619 0 : return 0;
620 : }
621 :
622 784979 : if ( flag_delta == 1 )
623 : {
624 267553 : dd = delta_phi / 2.0f;
625 : }
626 : else
627 : {
628 517426 : dd = 0;
629 : }
630 :
631 784979 : id_phi = (int16_t) ( ( phi - dd + delta_phi / 2.0f ) / (float) delta_phi );
632 :
633 784979 : if ( id_phi == n )
634 : {
635 46 : id_phi = 0;
636 : }
637 :
638 784979 : if ( id_phi == -1 )
639 : {
640 0 : id_phi = n - 1;
641 : }
642 :
643 784979 : *phi_hat = id_phi * delta_phi + dd;
644 :
645 784979 : return id_phi;
646 : }
647 :
648 :
649 : /*-------------------------------------------------------------------------
650 : * deindex_sph_idx()
651 : *
652 : * deindex the MASA metadata from the input metadata file
653 : *------------------------------------------------------------------------*/
654 :
655 7222656 : void deindex_sph_idx(
656 : const uint16_t sphIndex, /* i : Spherical index */
657 : const SPHERICAL_GRID_DATA *gridData, /* i : Prepared spherical grid */
658 : float *theta, /* o : Elevation */
659 : float *phi /* o : Azimuth */
660 : )
661 : {
662 : float ba_crt, del_crt, div_crt, a4_crt;
663 : float estim;
664 : int32_t base_low, base_up;
665 : int16_t n_crt;
666 : int16_t id_th;
667 : int16_t sign_theta;
668 : int16_t id_phi;
669 7222656 : int16_t no_th = gridData->no_theta;
670 7222656 : const int16_t *n = gridData->no_phi;
671 : const float ba[3] = { 2.137991118026424e+02f, 1.244854404591542e+02f, 1.228408647140870e+02f };
672 : const float del[3] = { 7.998262115303199e+05f, 1.300883976959332e+06f, 1.424072242426373e+06f };
673 : const float div[3] = { -0.237662341081474f, -0.100938185496887f, -0.092050209205032f };
674 : const float a4[3] = { -8.415300425381099f, -19.814106922515204f, -21.727272727270197f };
675 7222656 : const uint16_t limit_index1 = 64964, limit_index2 = 47870;
676 :
677 7222656 : if ( sphIndex >= limit_index1 )
678 : {
679 17167 : ba_crt = ba[2];
680 17167 : div_crt = div[2];
681 17167 : a4_crt = a4[2];
682 17167 : del_crt = del[2];
683 : }
684 7205489 : else if ( sphIndex >= limit_index2 )
685 : {
686 603999 : ba_crt = ba[1];
687 603999 : div_crt = div[1];
688 603999 : a4_crt = a4[1];
689 603999 : del_crt = del[1];
690 : }
691 : else
692 : {
693 6601490 : ba_crt = ba[0];
694 6601490 : div_crt = div[0];
695 6601490 : a4_crt = a4[0];
696 6601490 : del_crt = del[0];
697 : }
698 7222656 : estim = ba_crt + div_crt * sqrtf( del_crt + a4_crt * sphIndex );
699 :
700 7222656 : if ( estim > MASA_NO_CIRCLES )
701 : {
702 700 : estim = MASA_NO_CIRCLES;
703 : }
704 :
705 7222656 : assert( estim > 0 );
706 7222656 : id_th = (int16_t) roundf( estim ) - 1;
707 7222656 : if ( id_th < 0 )
708 : {
709 0 : id_th = 0;
710 : }
711 :
712 7222656 : if ( id_th == 0 )
713 : {
714 87462 : base_low = 0;
715 87462 : base_up = n[0];
716 : }
717 : else
718 : {
719 7135194 : estim = MASA_ANGLE_AT_EQUATOR * (float) ( id_th - 0.5f );
720 7135194 : base_low = n[0];
721 7135194 : if ( id_th >= 2 )
722 : {
723 6766219 : if ( id_th == 2 )
724 : {
725 374498 : base_low += 2 * (int16_t) ceilf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) );
726 : }
727 : else
728 : {
729 6391721 : base_low += 2 * (int16_t) roundf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) );
730 : }
731 : }
732 7135194 : base_up = base_low + 2 * n[id_th];
733 : }
734 :
735 7222656 : sign_theta = 1;
736 :
737 7222656 : n_crt = n[id_th];
738 7222656 : if ( sphIndex < base_low )
739 : {
740 355036 : id_th--;
741 355036 : n_crt = n[id_th];
742 355036 : if ( id_th == 0 )
743 : {
744 96215 : base_low = 0;
745 96215 : base_up = n_crt;
746 : }
747 : else
748 : {
749 258821 : base_up = base_low;
750 258821 : base_low -= 2 * n[id_th];
751 : }
752 355036 : assert( sphIndex >= base_low );
753 : }
754 6867620 : else if ( sphIndex >= base_up )
755 : {
756 226601 : id_th++;
757 226601 : n_crt = n[id_th];
758 226601 : base_low = base_up;
759 226601 : base_up += 2 * n_crt;
760 226601 : assert( sphIndex < base_up );
761 : }
762 :
763 7222656 : id_phi = (int16_t) ( sphIndex - base_low );
764 7222656 : if ( sphIndex - base_low >= n_crt )
765 : {
766 4276282 : id_phi -= n_crt;
767 4276282 : sign_theta = -1;
768 : }
769 :
770 7222656 : if ( id_th == 0 )
771 : {
772 183677 : *theta = 0.f;
773 183677 : *phi = (float) sphIndex * 360 / (float) n_crt - 180;
774 : }
775 : else
776 : {
777 7038979 : if ( id_th == no_th - 1 )
778 : {
779 321 : id_phi = 0;
780 321 : *phi = -180;
781 321 : *theta = 90 * (float) sign_theta;
782 : }
783 : else
784 : {
785 7038658 : *theta = id_th * MASA_ANGLE_AT_EQUATOR_DEG * (float) sign_theta;
786 7038658 : if ( id_th % 2 == 0 )
787 : {
788 3432836 : *phi = (float) id_phi * 360 / (float) n_crt - 180;
789 : }
790 : else
791 : {
792 3605822 : *phi = ( (float) id_phi + 0.5f ) * 360 / (float) n_crt - 180;
793 : }
794 : }
795 : }
796 :
797 7222656 : return;
798 : }
799 :
800 :
801 : /*---------------------------------------------------------------
802 : * valid_ratio_index()
803 : *
804 : * Checking validity of the index of an ISM ratio index vector,
805 : * within the indexing function.
806 : *---------------------------------------------------------------*/
807 :
808 : /*! r: valid or not 1/0 */
809 3658094 : int16_t valid_ratio_index(
810 : int16_t index, /* i : index to be checked */
811 : const int16_t K, /* i : L1 norm to check against */
812 : const int16_t len /* i : vector length */
813 : )
814 : {
815 : int16_t out;
816 : int16_t i, sum, elem;
817 : int16_t base[4];
818 :
819 3658094 : sum = 0;
820 3658094 : set_s( base, 1, len );
821 :
822 :
823 10906718 : for ( i = 1; i < len; i++ )
824 : {
825 7248624 : base[i] = base[i - 1] * 10;
826 : }
827 3658094 : sum = 0;
828 14564812 : for ( i = len - 1; i >= 0; i-- )
829 : {
830 10906718 : elem = index / base[i];
831 10906718 : sum += elem;
832 10906718 : index -= elem * base[i];
833 : }
834 3658094 : if ( sum <= K )
835 : {
836 1003953 : out = 1;
837 : }
838 : else
839 : {
840 2654141 : out = 0;
841 : }
842 :
843 3658094 : return out;
844 : }
845 :
846 :
847 : /*---------------------------------------------------------------
848 : * reconstruct_ism_ratios()
849 : *
850 : * Obtains ISM ratio values from the quantized indexes
851 : *---------------------------------------------------------------*/
852 :
853 120793 : void reconstruct_ism_ratios(
854 : int16_t *ratio_ism_idx, /* i : index vector */
855 : const int16_t nchan_ism, /* i : number of components/objects */
856 : const float step, /* i : quantization step */
857 : float *q_energy_ratio_ism /* o : reconstructed ISM values */
858 : )
859 : {
860 : int16_t i;
861 : float sum;
862 :
863 120793 : sum = 0;
864 425706 : for ( i = 0; i < nchan_ism - 1; i++ )
865 : {
866 304913 : q_energy_ratio_ism[i] = ratio_ism_idx[i] * step;
867 304913 : sum += q_energy_ratio_ism[i];
868 : }
869 :
870 120793 : q_energy_ratio_ism[nchan_ism - 1] = 1.0f - sum;
871 :
872 120793 : if ( q_energy_ratio_ism[nchan_ism - 1] < 0 )
873 : {
874 10762 : q_energy_ratio_ism[nchan_ism - 1] = 0.0f;
875 : }
876 :
877 120793 : return;
878 : }
879 :
880 :
881 : /*---------------------------------------------------------------
882 : * ivas_omasa_modify_masa_energy_ratios()
883 : *
884 : * Updates energy ratios by taking into account the MASA content contribution
885 : * to the total audio scene
886 : *---------------------------------------------------------------*/
887 :
888 7364 : void ivas_omasa_modify_masa_energy_ratios(
889 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
890 : float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_MAXIMUM_CODING_SUBBANDS] )
891 : {
892 : int16_t i, m, d, b;
893 :
894 36820 : for ( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ )
895 : {
896 29456 : if ( hQMetaData->q_direction[0].cfg.nblocks == 1 )
897 : {
898 9388 : i = 0;
899 : }
900 : else
901 : {
902 20068 : i = m;
903 : }
904 :
905 216072 : for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ )
906 : {
907 414656 : for ( d = 0; d < hQMetaData->no_directions; d++ )
908 : {
909 228040 : hQMetaData->q_direction[d].band_data[b].energy_ratio[m] = hQMetaData->q_direction[d].band_data[b].energy_ratio[m] * masa_to_total_energy_ratio[i][b];
910 : }
911 : }
912 : }
913 :
914 7364 : return;
915 : }
916 :
917 :
918 : /*---------------------------------------------------------------
919 : * distribute_evenly_ism()
920 : *
921 : * Obtain ISM ratio indexes for even content distribution bbetween objects
922 : *---------------------------------------------------------------*/
923 :
924 14414 : void distribute_evenly_ism(
925 : int16_t *idx, /* o : index values */
926 : const int16_t K, /* i : sum of indexes */
927 : const int16_t nchan_ism /* i : number of objects */
928 : )
929 : {
930 : int16_t i;
931 : int16_t sum;
932 :
933 14414 : sum = 0;
934 63138 : for ( i = 0; i < nchan_ism; i++ )
935 : {
936 48724 : idx[i] = (int16_t) ( K / nchan_ism );
937 48724 : sum += idx[i];
938 : }
939 :
940 14414 : assert( sum <= K );
941 :
942 14414 : i = 0;
943 43060 : while ( sum < K )
944 : {
945 28646 : if ( i == nchan_ism )
946 : {
947 0 : i = 0;
948 : }
949 28646 : idx[i]++;
950 28646 : sum++;
951 28646 : i++;
952 : }
953 :
954 14414 : return;
955 : }
956 :
957 :
958 : /*---------------------------------------------------------------
959 : * calculate_cpe_brate_MASA_ISM()
960 : *
961 : * Calculates bitrate for MASA_ISM mode that is not used for separated objects,
962 : * * but for the CPE part (metadata included)
963 : *---------------------------------------------------------------*/
964 :
965 : /*! r: CPE bitrate value */
966 41677 : int32_t calculate_cpe_brate_MASA_ISM(
967 : const ISM_MODE ism_mode, /* i : ism mode */
968 : const int32_t ivas_total_brate, /* i : IVAS total bitrate */
969 : const int16_t nchan_ism /* i : number of objects */
970 : )
971 : {
972 : int32_t cpe_brate;
973 : int16_t k, sce_id;
974 :
975 41677 : k = 0;
976 443139 : while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] )
977 : {
978 401462 : k++;
979 : }
980 :
981 41677 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ )
982 : {
983 14033 : cpe_brate = ivas_total_brate - sep_object_brate[k - 2][0]; /* take data from the first column */
984 : }
985 27644 : else if ( ism_mode == ISM_MASA_MODE_DISC )
986 : {
987 26323 : cpe_brate = ivas_total_brate;
988 :
989 97707 : for ( sce_id = 0; sce_id < nchan_ism; sce_id++ )
990 : {
991 71384 : cpe_brate -= sep_object_brate[k - 2][nchan_ism - 1];
992 : }
993 : }
994 : else
995 : {
996 1321 : cpe_brate = ivas_total_brate;
997 : }
998 :
999 41677 : return cpe_brate;
1000 : }
|