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 2900731 : 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 2900731 : if ( nchan_transport == 2 )
85 : {
86 2117035 : if ( ivas_total_brate >= MCMASA_SEPARATE_BRATE && mc_mode == MC_MODE_MCMASA )
87 : {
88 61600 : *nCPE = 1;
89 61600 : *nSCE = 1;
90 :
91 61600 : *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 2055435 : else if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE )
94 : {
95 858743 : *nCPE = 1;
96 :
97 858743 : if ( *element_mode == -1 )
98 : {
99 583842 : *element_mode = IVAS_CPE_DFT; /* To have it initialized in case it was not already. */
100 : }
101 858743 : if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO )
102 : {
103 612884 : *element_mode = IVAS_CPE_MDCT;
104 612884 : 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 54064 : *element_mode = IVAS_CPE_DFT;
107 : }
108 : }
109 : }
110 : else
111 : {
112 1196692 : *nCPE = 1;
113 1196692 : *nSCE = 0;
114 :
115 1196692 : if ( ivas_total_brate > MIN_BRATE_MDCT_STEREO )
116 : {
117 552297 : *element_mode = IVAS_CPE_MDCT;
118 : }
119 : }
120 2117035 : hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC );
121 2117035 : 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 858743 : hQMetaData->bits_frame_nominal -= (int16_t) ( ism_total_brate / FRAMES_PER_SEC );
124 : }
125 : }
126 783696 : else if ( nchan_transport == 1 )
127 : {
128 783696 : *nCPE = 0;
129 783696 : *nSCE = 1;
130 :
131 783696 : if ( ivas_total_brate == IVAS_13k2 )
132 : {
133 112814 : hQMetaData->bits_frame_nominal = ACELP_9k60 / FRAMES_PER_SEC;
134 : }
135 670882 : else if ( ivas_total_brate <= IVAS_16k4 )
136 : {
137 64670 : hQMetaData->bits_frame_nominal = ACELP_13k20 / FRAMES_PER_SEC;
138 : }
139 606212 : else if ( ivas_total_brate <= IVAS_24k4 )
140 : {
141 181043 : hQMetaData->bits_frame_nominal = ACELP_16k40 / FRAMES_PER_SEC;
142 : }
143 425169 : else if ( ivas_total_brate <= IVAS_32k )
144 : {
145 100129 : hQMetaData->bits_frame_nominal = ACELP_24k40 / FRAMES_PER_SEC;
146 : }
147 : else
148 : {
149 325040 : hQMetaData->bits_frame_nominal = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC );
150 : }
151 783696 : *element_mode = IVAS_SCE;
152 : }
153 : else
154 : {
155 0 : assert( !"MASA number of transport channels must be 1, or 2" );
156 : }
157 :
158 2900731 : return;
159 : }
160 :
161 :
162 : /*---------------------------------------------------------------
163 : * generate_gridEq()
164 : *
165 : * generate Spherical grid
166 : *---------------------------------------------------------------*/
167 :
168 11506 : 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 11506 : n = data->no_phi;
178 11506 : n[0] = MASA_NO_POINTS_EQUATOR;
179 :
180 11506 : cum_n_prev = 0;
181 :
182 1392226 : for ( i = 1; i < MASA_NO_CIRCLES; i++ )
183 : {
184 1380720 : theta = MASA_ANGLE_AT_EQUATOR * (float) ( i + 0.5f );
185 1380720 : if ( i == 1 )
186 : {
187 11506 : cum_n = 2 * (int32_t) ceilf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
188 : }
189 : else
190 : {
191 1369214 : cum_n = 2 * (int32_t) roundf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
192 : }
193 1380720 : n[i] = (int16_t) ( ( cum_n - cum_n_prev ) >> 1 );
194 1380720 : cum_n_prev = cum_n;
195 : }
196 11506 : n[i] = 1;
197 11506 : data->no_theta = i + 1;
198 :
199 11506 : 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 2785000 : 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 2785000 : nbands = 0;
232 2785000 : nTwoDirBands = 0;
233 2785000 : i = 0;
234 :
235 : /* First select correct bit budget table */
236 2785000 : masa_bits_table = masa_bits;
237 2785000 : if ( isMcMasa )
238 : {
239 308463 : masa_bits_table = mcmasa_bits;
240 : }
241 2476537 : else if ( ivas_total_brate < IVAS_48k && nchan_transport == 2 )
242 : {
243 806606 : masa_bits_table = masa_bits_LR_stereo;
244 : }
245 :
246 19693105 : while ( nbands == 0 && i < IVAS_NUM_ACTIVE_BRATES )
247 : {
248 16908105 : if ( ivas_total_brate <= ivas_brate_tbl[i + SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES] )
249 : {
250 : int16_t idx_bands;
251 2785000 : 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 33969 : i = 3;
255 : }
256 2785000 : idx_bands = i;
257 :
258 2785000 : if ( config->numberOfDirections > 1 )
259 : {
260 510092 : nTwoDirBands = config->joinedSubframes ? masa_twodir_bands_joined[i] : masa_twodir_bands[i];
261 :
262 510092 : if ( ( ivas_total_brate > IVAS_96k && !config->joinedSubframes ) || ( ivas_total_brate > IVAS_80k && config->joinedSubframes ) )
263 : {
264 212257 : idx_bands--;
265 : }
266 : }
267 :
268 2785000 : if ( config->joinedSubframes )
269 : {
270 613478 : nbands = masa_joined_nbands[idx_bands];
271 : }
272 : else
273 : {
274 2171522 : nbands = masa_nbands[idx_bands];
275 : }
276 :
277 2785000 : config->max_metadata_bits = masa_bits_table[i];
278 :
279 2785000 : 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 39154 : config->max_metadata_bits += MASA_EXTRA_BAND_META_BITS;
283 : }
284 :
285 2785000 : 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 116063 : config->max_metadata_bits += ( MASA_SMALL_INC_META_BITS );
289 : }
290 : }
291 16908105 : i++;
292 : }
293 2785000 : config->numCodingBands = nbands;
294 2785000 : config->numTwoDirBands = nTwoDirBands;
295 :
296 : #ifdef DEBUGGING
297 : assert( nbands > 0 );
298 : #endif
299 2785000 : if ( config->joinedSubframes == TRUE )
300 : {
301 613478 : config->mergeRatiosOverSubframes = FALSE;
302 : }
303 : else
304 : {
305 2171522 : config->mergeRatiosOverSubframes = TRUE;
306 : }
307 :
308 : /* Setup frequency band mapping based on the number of used coding bands */
309 2785000 : switch ( config->numCodingBands )
310 : {
311 1817579 : case 5:
312 1817579 : mvs2s( MASA_band_mapping_24_to_5, band_mapping, 5 + 1 );
313 1817579 : break;
314 208973 : case 8:
315 208973 : mvs2s( MASA_band_mapping_24_to_8, band_mapping, 8 + 1 );
316 208973 : break;
317 194468 : case 12:
318 194468 : mvs2s( MASA_band_mapping_24_to_12, band_mapping, 12 + 1 );
319 194468 : break;
320 236751 : case 18:
321 236751 : mvs2s( MASA_band_mapping_24_to_18, band_mapping, 18 + 1 );
322 236751 : break;
323 327229 : case MASA_FREQUENCY_BANDS:
324 : /* With input count of bands, no mapping is needed but for unified processing later, we store normal mapping */
325 8507954 : for ( i = 0; i < MASA_FREQUENCY_BANDS + 1; i++ )
326 : {
327 8180725 : band_mapping[i] = i;
328 : }
329 327229 : break;
330 0 : default:
331 0 : assert( 0 && "Error: The number of MASA coding bands is not supported" );
332 : }
333 :
334 2785000 : config->useCoherence = TRUE;
335 2785000 : if ( ( !isMcMasa && ivas_total_brate < IVAS_48k ) || ( isMcMasa && ivas_total_brate < IVAS_16k4 ) )
336 : {
337 1067472 : config->useCoherence = FALSE;
338 : }
339 :
340 2785000 : return;
341 : }
342 :
343 :
344 : /*---------------------------------------------------------------
345 : * masa_sample_rate_band_correction()
346 : *
347 : *
348 : *---------------------------------------------------------------*/
349 :
350 2785000 : 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 2785000 : numBands48k = config->numCodingBands;
364 :
365 24742721 : for ( band = 1; band < config->numCodingBands + 1; band++ )
366 : {
367 24742721 : highBand = band_mapping[band];
368 :
369 24742721 : if ( highBand >= maxBand )
370 : {
371 2785000 : config->numCodingBands = band;
372 2785000 : hQMetaData->numCodingBands = band;
373 :
374 2785000 : if ( is_encoder )
375 : {
376 66396 : if ( hQMetaData->q_direction->cfg.nbands > band )
377 : {
378 14670 : hQMetaData->q_direction->cfg.nbands = band;
379 : }
380 66396 : if ( hQMetaData->no_directions == 2 && hQMetaData->q_direction[1].cfg.nbands > band )
381 : {
382 4846 : hQMetaData->q_direction[1].cfg.nbands = band;
383 : }
384 : }
385 :
386 2785000 : band_mapping[band] = maxBand;
387 :
388 2785000 : break;
389 : }
390 : }
391 :
392 : /* Set rest of the bands to zero in qmetadata. */
393 3250588 : for ( ; band < numBands48k; band++ )
394 : {
395 2327940 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
396 : {
397 1862352 : hQMetaData->q_direction[0].band_data[band].azimuth[sf] = 0.0f;
398 1862352 : hQMetaData->q_direction[0].band_data[band].elevation[sf] = 0.0f;
399 1862352 : hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = 0.0f;
400 :
401 1862352 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL )
402 : {
403 1859860 : hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u;
404 : }
405 :
406 1862352 : if ( hQMetaData->no_directions == 2 )
407 : {
408 235284 : hQMetaData->q_direction[1].band_data[band].azimuth[sf] = 0.0f;
409 235284 : hQMetaData->q_direction[1].band_data[band].elevation[sf] = 0.0f;
410 235284 : hQMetaData->q_direction[1].band_data[band].energy_ratio[sf] = 0.0f;
411 :
412 235284 : if ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL )
413 : {
414 235284 : hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = 0u;
415 : }
416 : }
417 :
418 1862352 : if ( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL )
419 : {
420 1859860 : hQMetaData->surcoh_band_data[band].surround_coherence[sf] = 0u;
421 : }
422 : }
423 :
424 465588 : if ( hQMetaData->no_directions == 2 )
425 : {
426 58821 : hQMetaData->twoDirBands[band] = 0;
427 : }
428 : }
429 :
430 2785000 : if ( hExtOutMeta != NULL )
431 : {
432 : /* in decoder, zero the EXT out MASA meta buffer */
433 1071545 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
434 : {
435 12197888 : for ( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ )
436 : {
437 11340652 : hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT;
438 11340652 : hExtOutMeta->directToTotalRatio[0][sf][band] = 0u;
439 11340652 : hExtOutMeta->spreadCoherence[0][sf][band] = 0u;
440 :
441 11340652 : hExtOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
442 11340652 : hExtOutMeta->directToTotalRatio[1][sf][band] = 0u;
443 11340652 : hExtOutMeta->spreadCoherence[1][sf][band] = 0u;
444 :
445 11340652 : hExtOutMeta->surroundCoherence[sf][band] = 0u;
446 11340652 : hExtOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX;
447 : }
448 : }
449 : }
450 :
451 2785000 : return;
452 : }
453 :
454 :
455 : /*-------------------------------------------------------------------------
456 : * index_theta_phi_16()
457 : *
458 : *
459 : *------------------------------------------------------------------------*/
460 :
461 : /*! r: output index for direction */
462 7987286 : 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 7987286 : theta = *p_theta;
476 7987286 : phi = *p_phi;
477 7987286 : phi_hat = 0;
478 7987286 : theta_hat = 0;
479 7987286 : phi = phi + 180;
480 :
481 7987286 : if ( theta < 0 )
482 : {
483 1956283 : abs_theta = -theta;
484 1956283 : sign_th = -1;
485 : }
486 : else
487 : {
488 6031003 : abs_theta = theta;
489 6031003 : sign_th = 1;
490 : }
491 :
492 7987286 : id_th = quantize_theta_masa( abs_theta, gridData->no_theta, &theta_hat );
493 7987286 : if ( gridData->no_theta > 1 )
494 : {
495 7987286 : if ( gridData->no_phi[id_th] > 1 )
496 : {
497 7983448 : id_phi = quantize_phi_masa( phi, ( id_th % 2 == 1 ), &phi_hat, gridData->no_phi[id_th] );
498 : }
499 : else
500 : {
501 3838 : id_phi = 0;
502 3838 : 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 7987286 : *p_theta = sign_th * theta_hat;
510 7987286 : *p_phi = phi_hat - 180;
511 :
512 : /* Starting from Equator, alternating positive and negative */
513 7987286 : if ( id_th == 0 )
514 : {
515 4839514 : idx_sph = id_phi;
516 : }
517 : else
518 : {
519 3147772 : if ( id_th == gridData->no_theta - 1 )
520 : {
521 3838 : idx_sph = 65534 + ( sign_th < 0 );
522 : }
523 : else
524 : {
525 3143934 : theta = MASA_ANGLE_AT_EQUATOR * (float) ( id_th + 0.5f );
526 3143934 : if ( id_th == 1 )
527 : {
528 53471 : cum_n = 2 * (uint16_t) ceilf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
529 : }
530 : else
531 : {
532 3090463 : cum_n = 2 * (uint16_t) roundf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) );
533 : }
534 :
535 3143934 : cum_n += gridData->no_phi[0];
536 :
537 3143934 : if ( sign_th > 0 )
538 : {
539 1192851 : cum_n -= 2 * gridData->no_phi[id_th];
540 : }
541 : else
542 : {
543 1951083 : cum_n -= gridData->no_phi[id_th];
544 : }
545 3143934 : idx_sph = cum_n + id_phi;
546 : }
547 : }
548 :
549 7987286 : return idx_sph;
550 : }
551 :
552 :
553 : /*-------------------------------------------------------------------------
554 : * quantize_phi_masa()
555 : *
556 : *
557 : *------------------------------------------------------------------------*/
558 :
559 : /*! r: output index */
560 7987286 : 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 7987286 : imin = (int16_t) ( x * MASA_INV_ANGLE_AT_EQUATOR_DEG + 0.5f );
570 :
571 7987286 : if ( imin >= no_cb - 1 )
572 : {
573 3840 : imin = no_cb - 1;
574 3840 : diff1 = x - 90;
575 3840 : diff2 = x - MASA_ANGLE_AT_EQUATOR_DEG * ( imin - 1 );
576 3840 : if ( fabsf( diff1 ) > fabsf( diff2 ) )
577 : {
578 2 : imin--;
579 2 : *xhat = imin * MASA_ANGLE_AT_EQUATOR_DEG;
580 : }
581 : else
582 : {
583 3838 : *xhat = 90;
584 : }
585 : }
586 : else
587 : {
588 7983446 : *xhat = imin * MASA_ANGLE_AT_EQUATOR_DEG;
589 : }
590 :
591 7987286 : return imin;
592 : }
593 :
594 :
595 : /*-------------------------------------------------------------------------
596 : * quantize_phi_masa()
597 : *
598 : *
599 : *------------------------------------------------------------------------*/
600 :
601 : /*! r: index azimuth */
602 7983448 : 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 7983448 : delta_phi = 360.0f / (float) n;
614 :
615 7983448 : if ( n == 1 )
616 : {
617 0 : *phi_hat = 0;
618 :
619 0 : return 0;
620 : }
621 :
622 7983448 : if ( flag_delta == 1 )
623 : {
624 2295780 : dd = delta_phi / 2.0f;
625 : }
626 : else
627 : {
628 5687668 : dd = 0;
629 : }
630 :
631 7983448 : id_phi = (int16_t) ( ( phi - dd + delta_phi / 2.0f ) / (float) delta_phi );
632 :
633 7983448 : if ( id_phi == n )
634 : {
635 130 : id_phi = 0;
636 : }
637 :
638 7983448 : if ( id_phi == -1 )
639 : {
640 0 : id_phi = n - 1;
641 : }
642 :
643 7983448 : *phi_hat = id_phi * delta_phi + dd;
644 :
645 7983448 : 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 124420854 : 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 124420854 : int16_t no_th = gridData->no_theta;
670 124420854 : 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 124420854 : const uint16_t limit_index1 = 64964, limit_index2 = 47870;
676 :
677 124420854 : if ( sphIndex >= limit_index1 )
678 : {
679 134743 : ba_crt = ba[2];
680 134743 : div_crt = div[2];
681 134743 : a4_crt = a4[2];
682 134743 : del_crt = del[2];
683 : }
684 124286111 : else if ( sphIndex >= limit_index2 )
685 : {
686 6843815 : ba_crt = ba[1];
687 6843815 : div_crt = div[1];
688 6843815 : a4_crt = a4[1];
689 6843815 : del_crt = del[1];
690 : }
691 : else
692 : {
693 117442296 : ba_crt = ba[0];
694 117442296 : div_crt = div[0];
695 117442296 : a4_crt = a4[0];
696 117442296 : del_crt = del[0];
697 : }
698 124420854 : estim = ba_crt + div_crt * sqrtf( del_crt + a4_crt * sphIndex );
699 :
700 124420854 : if ( estim > MASA_NO_CIRCLES )
701 : {
702 4298 : estim = MASA_NO_CIRCLES;
703 : }
704 :
705 124420854 : assert( estim > 0 );
706 124420854 : id_th = (int16_t) roundf( estim ) - 1;
707 124420854 : if ( id_th < 0 )
708 : {
709 0 : id_th = 0;
710 : }
711 :
712 124420854 : if ( id_th == 0 )
713 : {
714 16623368 : base_low = 0;
715 16623368 : base_up = n[0];
716 : }
717 : else
718 : {
719 107797486 : estim = MASA_ANGLE_AT_EQUATOR * (float) ( id_th - 0.5f );
720 107797486 : base_low = n[0];
721 107797486 : if ( id_th >= 2 )
722 : {
723 95421077 : if ( id_th == 2 )
724 : {
725 5118321 : base_low += 2 * (int16_t) ceilf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) );
726 : }
727 : else
728 : {
729 90302756 : base_low += 2 * (int16_t) roundf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) );
730 : }
731 : }
732 107797486 : base_up = base_low + 2 * n[id_th];
733 : }
734 :
735 124420854 : sign_theta = 1;
736 :
737 124420854 : n_crt = n[id_th];
738 124420854 : if ( sphIndex < base_low )
739 : {
740 11391690 : id_th--;
741 11391690 : n_crt = n[id_th];
742 11391690 : if ( id_th == 0 )
743 : {
744 8236004 : base_low = 0;
745 8236004 : base_up = n_crt;
746 : }
747 : else
748 : {
749 3155686 : base_up = base_low;
750 3155686 : base_low -= 2 * n[id_th];
751 : }
752 11391690 : assert( sphIndex >= base_low );
753 : }
754 113029164 : else if ( sphIndex >= base_up )
755 : {
756 4605785 : id_th++;
757 4605785 : n_crt = n[id_th];
758 4605785 : base_low = base_up;
759 4605785 : base_up += 2 * n_crt;
760 4605785 : assert( sphIndex < base_up );
761 : }
762 :
763 124420854 : id_phi = (int16_t) ( sphIndex - base_low );
764 124420854 : if ( sphIndex - base_low >= n_crt )
765 : {
766 51801683 : id_phi -= n_crt;
767 51801683 : sign_theta = -1;
768 : }
769 :
770 124420854 : if ( id_th == 0 )
771 : {
772 24859372 : *theta = 0.f;
773 24859372 : *phi = (float) sphIndex * 360 / (float) n_crt - 180;
774 : }
775 : else
776 : {
777 99561482 : if ( id_th == no_th - 1 )
778 : {
779 1856 : id_phi = 0;
780 1856 : *phi = -180;
781 1856 : *theta = 90 * (float) sign_theta;
782 : }
783 : else
784 : {
785 99559626 : *theta = id_th * MASA_ANGLE_AT_EQUATOR_DEG * (float) sign_theta;
786 99559626 : if ( id_th % 2 == 0 )
787 : {
788 47411780 : *phi = (float) id_phi * 360 / (float) n_crt - 180;
789 : }
790 : else
791 : {
792 52147846 : *phi = ( (float) id_phi + 0.5f ) * 360 / (float) n_crt - 180;
793 : }
794 : }
795 : }
796 :
797 124420854 : 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 18236649 : 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 18236649 : sum = 0;
820 18236649 : set_s( base, 1, len );
821 :
822 :
823 53728386 : for ( i = 1; i < len; i++ )
824 : {
825 35491737 : base[i] = base[i - 1] * 10;
826 : }
827 18236649 : sum = 0;
828 71965035 : for ( i = len - 1; i >= 0; i-- )
829 : {
830 53728386 : elem = index / base[i];
831 53728386 : sum += elem;
832 53728386 : index -= elem * base[i];
833 : }
834 18236649 : if ( sum <= K )
835 : {
836 7041768 : out = 1;
837 : }
838 : else
839 : {
840 11194881 : out = 0;
841 : }
842 :
843 18236649 : return out;
844 : }
845 :
846 :
847 : /*---------------------------------------------------------------
848 : * reconstruct_ism_ratios()
849 : *
850 : * Obtains ISM ratio values from the quantized indexes
851 : *---------------------------------------------------------------*/
852 :
853 2764220 : 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 2764220 : sum = 0;
864 9678208 : for ( i = 0; i < nchan_ism - 1; i++ )
865 : {
866 6913988 : q_energy_ratio_ism[i] = ratio_ism_idx[i] * step;
867 6913988 : sum += q_energy_ratio_ism[i];
868 : }
869 :
870 2764220 : q_energy_ratio_ism[nchan_ism - 1] = 1.0f - sum;
871 :
872 2764220 : if ( q_energy_ratio_ism[nchan_ism - 1] < 0 )
873 : {
874 130002 : q_energy_ratio_ism[nchan_ism - 1] = 0.0f;
875 : }
876 :
877 2764220 : 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 178094 : 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 890470 : for ( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ )
895 : {
896 712376 : if ( hQMetaData->q_direction[0].cfg.nblocks == 1 )
897 : {
898 288192 : i = 0;
899 : }
900 : else
901 : {
902 424184 : i = m;
903 : }
904 :
905 5481904 : for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ )
906 : {
907 10460100 : for ( d = 0; d < hQMetaData->no_directions; d++ )
908 : {
909 5690572 : 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 178094 : return;
915 : }
916 :
917 :
918 : /*---------------------------------------------------------------
919 : * distribute_evenly_ism()
920 : *
921 : * Obtain ISM ratio indexes for even content distribution bbetween objects
922 : *---------------------------------------------------------------*/
923 :
924 862755 : 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 862755 : sum = 0;
934 3795474 : for ( i = 0; i < nchan_ism; i++ )
935 : {
936 2932719 : idx[i] = (int16_t) ( K / nchan_ism );
937 2932719 : sum += idx[i];
938 : }
939 :
940 862755 : assert( sum <= K );
941 :
942 862755 : i = 0;
943 2556894 : while ( sum < K )
944 : {
945 1694139 : if ( i == nchan_ism )
946 : {
947 0 : i = 0;
948 : }
949 1694139 : idx[i]++;
950 1694139 : sum++;
951 1694139 : i++;
952 : }
953 :
954 862755 : 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 1253586 : 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 1253586 : k = 0;
976 14130085 : while ( k < SIZE_IVAS_BRATE_TBL && ivas_total_brate != ivas_brate_tbl[k] )
977 : {
978 12876499 : k++;
979 : }
980 :
981 1253586 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ )
982 : {
983 249067 : cpe_brate = ivas_total_brate - sep_object_brate[k - 2][0]; /* take data from the first column */
984 : }
985 1004519 : else if ( ism_mode == ISM_MASA_MODE_DISC )
986 : {
987 989673 : cpe_brate = ivas_total_brate;
988 :
989 3410876 : for ( sce_id = 0; sce_id < nchan_ism; sce_id++ )
990 : {
991 2421203 : cpe_brate -= sep_object_brate[k - 2][nchan_ism - 1];
992 : }
993 : }
994 : else
995 : {
996 14846 : cpe_brate = ivas_total_brate;
997 : }
998 :
999 1253586 : return cpe_brate;
1000 : }
|