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