Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2026 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 <stdint.h>
34 : #include <math.h>
35 : #include "options.h"
36 : #include "ivas_cnst.h"
37 : #include "ivas_prot.h"
38 : #include "ivas_rom_com.h"
39 : #include "ivas_stat_enc.h"
40 : #include "wmc_auto.h"
41 : #include "prot.h"
42 :
43 :
44 : /*-----------------------------------------------------------------------*
45 : * Local function prototypes
46 : *-----------------------------------------------------------------------*/
47 :
48 : static void combine_freqbands_and_subframes( MASA_ENCODER_HANDLE hMasa );
49 :
50 : static void find_n_largest( const float *input, int16_t *largestIndices, const int16_t numElements, const int16_t numLargest );
51 :
52 : static void move_metadata_to_qmetadata( const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta );
53 :
54 : static void detect_metadata_composition( const MASA_ENCODER_HANDLE hMasa, uint8_t *joinedSubframes, uint8_t *coherencePresent, uint8_t *isTwoDir );
55 :
56 : static void compensate_energy_ratios( MASA_ENCODER_HANDLE hMasa );
57 :
58 : static int16_t encode_lfe_to_total_energy_ratio( MASA_ENCODER_HANDLE hMasa, BSTR_ENC_HANDLE hMetaData, const int32_t ivas_total_brate );
59 :
60 : static void ivas_encode_masaism_metadata( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMetaData, BSTR_ENC_HANDLE hMetaData, ISM_METADATA_HANDLE hIsmMeta[], const int16_t nchan_ism, const int16_t low_bitrate_mode, const int16_t omasa_nbands, const int16_t omasa_nblocks, const int16_t idx_separated_object, const int16_t ism_imp );
61 :
62 : static void reduce_metadata_further( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format );
63 :
64 : static void average_masa_metadata( MASA_METADATA_FRAME *masaMetadata, float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const SPHERICAL_GRID_DATA *sphGrid, const uint8_t useSphGrid );
65 :
66 : static void copy_masa_metadata_subframe( const MASA_METADATA_HANDLE hMetaFrom, const uint8_t sfFrom, MASA_METADATA_HANDLE hMetaTo, const uint8_t sfTo );
67 :
68 : static void copy_masa_metadata( const MASA_METADATA_HANDLE hMetaFrom, MASA_METADATA_HANDLE hMetaTo );
69 :
70 : static uint8_t are_masa_subframes_similar( const MASA_METADATA_HANDLE frame1, const uint8_t sf1_idx, const MASA_METADATA_HANDLE frame2, const uint8_t sf2_idx );
71 :
72 : static void detect_framing_async( MASA_ENCODER_HANDLE hMasa );
73 :
74 : static void masa_metadata_direction_alignment( MASA_ENCODER_HANDLE hMasa );
75 :
76 :
77 : /*-----------------------------------------------------------------------*
78 : * Local constants
79 : *-----------------------------------------------------------------------*/
80 :
81 : #define LOWBITRATE_ONSET_ALPHA 0.2f /* Onset values are for processing in frames */
82 : #define LOWBITRATE_ONSET_BETA 0.92f
83 : #define LOWBITRATE_ONSET_GAIN 1.4f
84 : #define LOWBITRATE_NUM_BANDS 5
85 :
86 :
87 : /*-----------------------------------------------------------------------*
88 : * ivas_masa_enc_open()
89 : *
90 : * open and initialize MASA encoder
91 : *-----------------------------------------------------------------------*/
92 :
93 8752 : ivas_error ivas_masa_enc_open(
94 : Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */
95 : )
96 : {
97 : int16_t i;
98 : MASA_ENCODER_HANDLE hMasa;
99 : ENCODER_CONFIG_HANDLE hEncoderConfig;
100 : ivas_error error;
101 : int32_t ism_total_brate;
102 :
103 8752 : error = IVAS_ERR_OK;
104 :
105 8752 : if ( ( hMasa = (MASA_ENCODER_HANDLE) malloc( sizeof( MASA_ENCODER ) ) ) == NULL )
106 : {
107 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
108 : }
109 :
110 8752 : hEncoderConfig = st_ivas->hEncoderConfig;
111 :
112 8752 : generate_gridEq( &( hMasa->data.Sph_Grid16 ) );
113 :
114 8752 : if ( hEncoderConfig->ivas_format == MASA_FORMAT || hEncoderConfig->ivas_format == MASA_ISM_FORMAT )
115 : {
116 1642 : hMasa->data.num_Cldfb_instances = st_ivas->nchan_transport;
117 : }
118 : else
119 : {
120 7110 : hMasa->data.num_Cldfb_instances = 0;
121 : }
122 :
123 11741 : for ( i = 0; i < hMasa->data.num_Cldfb_instances; i++ )
124 : {
125 2989 : if ( ( error = openCldfb( &( hMasa->data.cldfbAnaEnc[i] ), CLDFB_ANALYSIS, hEncoderConfig->input_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
126 : {
127 0 : return error;
128 : }
129 : }
130 :
131 8752 : ism_total_brate = 0;
132 8752 : if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) )
133 : {
134 2060 : for ( i = 0; i < st_ivas->nSCE; i++ )
135 : {
136 1291 : ism_total_brate += st_ivas->hSCE[i]->element_brate;
137 : }
138 : }
139 :
140 8752 : ivas_masa_set_elements( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate );
141 :
142 8752 : mvs2s( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
143 8752 : mvs2s( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 );
144 :
145 :
146 8752 : hMasa->data.onset_detector_1 = 0.0f;
147 8752 : hMasa->data.onset_detector_2 = 0.0f;
148 :
149 8752 : set_zero( hMasa->data.lfeToTotalEnergyRatio, MAX_PARAM_SPATIAL_SUBFRAMES );
150 8752 : hMasa->data.prevq_lfeToTotalEnergyRatio = 0.0f;
151 8752 : hMasa->data.prevq_lfeIndex = 0;
152 :
153 8752 : hMasa->data.sync_state.prev_sim_stop = 0;
154 8752 : hMasa->data.sync_state.prev_offset = 0;
155 8752 : hMasa->data.sync_state.frame_mode = MASA_FRAME_4SF;
156 :
157 8752 : set_zero( hMasa->data.dir_align_state.previous_azi_dir1, MASA_FREQUENCY_BANDS );
158 8752 : set_zero( hMasa->data.dir_align_state.previous_ele_dir1, MASA_FREQUENCY_BANDS );
159 8752 : set_zero( hMasa->data.dir_align_state.previous_azi_dir2, MASA_FREQUENCY_BANDS );
160 8752 : set_zero( hMasa->data.dir_align_state.previous_ele_dir2, MASA_FREQUENCY_BANDS );
161 :
162 8752 : if ( hEncoderConfig->ivas_format == MASA_ISM_FORMAT )
163 : {
164 : OMASA_ENCODER_DATA_HANDLE hOmasaData;
165 :
166 1016 : if ( ( hOmasaData = (OMASA_ENCODER_DATA_HANDLE) malloc( sizeof( OMASA_ENCODER_DATA_STATE ) ) ) == NULL )
167 : {
168 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data encoder\n" ) );
169 : }
170 5080 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
171 : {
172 4064 : set_f( hOmasaData->masa_to_total_energy_ratio[i], 0, MASA_FREQUENCY_BANDS );
173 : }
174 1016 : hOmasaData->lp_noise_CPE = -1;
175 1016 : hOmasaData->omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX;
176 :
177 1016 : if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC )
178 : {
179 501 : if ( ( hOmasaData->hOmasaEnergy = (OMASA_ENCODER_ENERGY_HANDLE) malloc( sizeof( OMASA_ENCODER_ENERGY_STATE ) ) ) == NULL )
180 : {
181 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA energy handle\n" ) );
182 : }
183 : }
184 : else
185 : {
186 515 : hOmasaData->hOmasaEnergy = NULL;
187 : }
188 :
189 1016 : hMasa->data.hOmasaData = hOmasaData;
190 : }
191 : else
192 : {
193 7736 : hMasa->data.hOmasaData = NULL;
194 : }
195 :
196 8752 : st_ivas->hMasa = hMasa;
197 :
198 8752 : return error;
199 : }
200 :
201 :
202 : /*-----------------------------------------------------------------------*
203 : * ivas_masa_enc_close()
204 : *
205 : * close MASA encoder
206 : *-----------------------------------------------------------------------*/
207 :
208 16681 : void ivas_masa_enc_close(
209 : MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */
210 : )
211 : {
212 : int16_t i;
213 :
214 16681 : if ( hMasa == NULL || *hMasa == NULL )
215 : {
216 7929 : return;
217 : }
218 :
219 11741 : for ( i = 0; i < ( *hMasa )->data.num_Cldfb_instances; i++ )
220 : {
221 2989 : deleteCldfb( &( ( *hMasa )->data.cldfbAnaEnc[i] ) );
222 : }
223 :
224 8752 : if ( ( *hMasa )->data.hOmasaData != NULL )
225 : {
226 1016 : if ( ( *hMasa )->data.hOmasaData->hOmasaEnergy != NULL )
227 : {
228 512 : free( ( *hMasa )->data.hOmasaData->hOmasaEnergy );
229 512 : ( *hMasa )->data.hOmasaData->hOmasaEnergy = NULL;
230 : }
231 :
232 1016 : free( ( *hMasa )->data.hOmasaData );
233 1016 : ( *hMasa )->data.hOmasaData = NULL;
234 : }
235 :
236 8752 : free( ( *hMasa ) );
237 8752 : ( *hMasa ) = NULL;
238 :
239 8752 : return;
240 : }
241 :
242 :
243 : /*-----------------------------------------------------------------------*
244 : * ivas_masa_encode()
245 : *
246 : * main MASA encoder function
247 : *-----------------------------------------------------------------------*/
248 :
249 1302497 : ivas_error ivas_masa_encode(
250 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
251 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
252 : BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */
253 : int16_t *nb_bits_metadata, /* o : number of metadata bits written */
254 : const int16_t nchan_transport, /* i : number of MASA input/transport channels */
255 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
256 : const int32_t ivas_total_brate, /* i : IVAS total bitrate */
257 : const int16_t Opt_DTX_ON, /* i : DTX on flag */
258 : const int16_t element_mode, /* i : element mode */
259 : const ISM_MODE ism_mode, /* i : ISM format mode */
260 : const int16_t nchan_ism, /* i : number of ISM channels */
261 : ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata handle */
262 : const int16_t idx_separated_object, /* i : index of the separated object */
263 : OMASA_ENC_HANDLE hOMasa, /* i : OMASA encoder handle */
264 : const int16_t ism_imp, /* i : importance of separated object */
265 : const int16_t flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */
266 : )
267 : {
268 : MASA_DIRECTIONAL_SPATIAL_META *h_orig_metadata;
269 : int16_t i, j;
270 : int16_t masa_sid_descriptor;
271 : int16_t low_bitrate_mode;
272 : int32_t masa_total_brate;
273 : ivas_error error;
274 :
275 1302497 : masa_sid_descriptor = -1;
276 1302497 : h_orig_metadata = NULL;
277 1302497 : low_bitrate_mode = 0;
278 :
279 1302497 : if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT )
280 : {
281 : /* Create the MASA SID descriptor for the metadata and CPE mode, in order to have the SID frame self-contained. */
282 1111657 : if ( Opt_DTX_ON && hQMetaData != NULL )
283 : {
284 70127 : if ( nchan_transport == 2 ) /* this is MASA format in CPE only */
285 : {
286 45112 : masa_sid_descriptor = 0; /* for IVAS_CPE_DFT */
287 45112 : if ( element_mode == IVAS_CPE_MDCT )
288 : {
289 19946 : masa_sid_descriptor = 1;
290 : }
291 : }
292 : }
293 :
294 : /* Validate and compensate ratios as necessary */
295 1111657 : compensate_energy_ratios( hMasa );
296 :
297 1111657 : if ( Opt_DTX_ON )
298 : {
299 70127 : if ( ( h_orig_metadata = (MASA_DIRECTIONAL_SPATIAL_META *) malloc( MASA_MAXIMUM_DIRECTIONS * sizeof( MASA_DIRECTIONAL_SPATIAL_META ) ) ) == NULL )
300 : {
301 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
302 : }
303 :
304 210381 : for ( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
305 : {
306 701270 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
307 : {
308 561016 : mvr2r( hMasa->masaMetadata.directional_meta[i].azimuth[j], h_orig_metadata[i].azimuth[j], MASA_FREQUENCY_BANDS );
309 561016 : mvr2r( hMasa->masaMetadata.directional_meta[i].elevation[j], h_orig_metadata[i].elevation[j], MASA_FREQUENCY_BANDS );
310 561016 : mvr2r( hMasa->masaMetadata.directional_meta[i].energy_ratio[j], h_orig_metadata[i].energy_ratio[j], MASA_FREQUENCY_BANDS );
311 561016 : mvs2s( (int16_t *) ( hMasa->masaMetadata.directional_meta[i].spherical_index[j] ), (int16_t *) ( h_orig_metadata[i].spherical_index[j] ), MASA_FREQUENCY_BANDS );
312 : }
313 : }
314 : }
315 :
316 1111657 : if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ivas_total_brate >= IVAS_384k )
317 : {
318 108834 : hMasa->config.mergeRatiosOverSubframes = 0;
319 : }
320 :
321 : /* Combine frequency bands and sub-frames */
322 1111657 : combine_freqbands_and_subframes( hMasa );
323 : }
324 :
325 1302497 : if ( hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands < hMasa->config.numCodingBands && ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) )
326 : {
327 422730 : if ( ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE && ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) || ( ivas_format != MASA_ISM_FORMAT ) )
328 : {
329 : /* Combine directions */
330 332942 : ivas_masa_combine_directions( hMasa );
331 : }
332 :
333 : /* If we joined all bands, then metadata is now one directional. */
334 422730 : if ( hMasa->config.numTwoDirBands == 0 )
335 : {
336 225318 : hMasa->config.numberOfDirections = 1;
337 225318 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
338 225318 : hQMetaData->no_directions = 1;
339 : }
340 : }
341 :
342 : /* Reset qmetadata bit budget */
343 1302497 : hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits;
344 1302497 : if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT )
345 : {
346 1111657 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode != ISM_MODE_NONE )
347 : {
348 : /* write the number of objects in ISM_MASA format*/
349 320920 : push_next_indice( hMetaData, nchan_ism - 1, NO_BITS_MASA_ISM_NO_OBJ );
350 320920 : hQMetaData->metadata_max_bits -= NO_BITS_MASA_ISM_NO_OBJ;
351 :
352 : /* write index of separated object if needed */
353 320920 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && nchan_ism > 1 )
354 : {
355 82794 : push_next_indice( hMetaData, idx_separated_object, NO_BITS_MASA_ISM_NO_OBJ );
356 82794 : hQMetaData->metadata_max_bits -= NO_BITS_MASA_ISM_NO_OBJ;
357 : }
358 :
359 : /* write ISM importance flag (one per object) */
360 320920 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ )
361 : {
362 82794 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
363 82794 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
364 : }
365 238126 : else if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ )
366 : {
367 87818 : if ( hIsmMetaData[0]->ism_md_null_flag )
368 : {
369 : /* signal NULL metadata frame */
370 0 : push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
371 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS;
372 :
373 : /* write the ISM class to ISM_NO_META and again the true ISM class */
374 0 : push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
375 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
376 0 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
377 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
378 : }
379 : else
380 : {
381 87818 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
382 87818 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
383 :
384 87818 : if ( hIsmMetaData[0]->ism_imp == ISM_NO_META )
385 : {
386 : /* signal low-rate ISM_NO_META frame */
387 2830 : push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
388 2830 : hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS;
389 :
390 : /* signal presence of MD in low-rate ISM_NO_META frame */
391 2830 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
392 2830 : hQMetaData->metadata_max_bits -= ISM_METADATA_INACTIVE_FLAG_BITS;
393 : }
394 : }
395 : }
396 150308 : else if ( ism_mode == ISM_MASA_MODE_DISC )
397 : {
398 544040 : for ( i = 0; i < nchan_ism; i++ )
399 : {
400 393732 : if ( hIsmMetaData[i]->ism_md_null_flag )
401 : {
402 : /* signal NULL metadata frame */
403 0 : push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
404 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS;
405 :
406 : /* write the ISM class to ISM_NO_META and again the true ISM class */
407 0 : push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
408 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
409 0 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
410 0 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
411 : }
412 : else
413 : {
414 393732 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
415 393732 : hQMetaData->metadata_max_bits -= ISM_METADATA_FLAG_BITS;
416 :
417 393732 : if ( hIsmMetaData[i]->ism_imp == ISM_NO_META )
418 : {
419 : /* signal low-rate ISM_NO_META frame */
420 11733 : push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
421 11733 : hQMetaData->metadata_max_bits -= ISM_METADATA_MD_FLAG_BITS;
422 :
423 : /* signal presence of MD in low-rate ISM_NO_META frame */
424 11733 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
425 11733 : hQMetaData->metadata_max_bits -= ISM_METADATA_INACTIVE_FLAG_BITS;
426 : }
427 : }
428 : }
429 :
430 150308 : if ( ivas_total_brate == IVAS_128k && nchan_ism >= 3 )
431 : {
432 4446 : push_next_indice( hMetaData, flag_omasa_ener_brate, 1 );
433 4446 : hQMetaData->metadata_max_bits -= 1;
434 : }
435 : }
436 : }
437 : else
438 : {
439 790737 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MODE_NONE )
440 : {
441 : /* use the MASA number of transport channels bit to signal if there are 1 or 2 objects */
442 90320 : if ( nchan_ism == 1 || nchan_ism == 2 )
443 : {
444 32666 : push_next_indice( hMetaData, nchan_ism - 1, MASA_TRANSP_BITS );
445 : }
446 : else
447 : {
448 : /* for 3 or 4 objects write already the number of MASA directions */
449 57654 : push_next_indice( hMetaData, hQMetaData->no_directions - 1, MASA_TRANSP_BITS );
450 : }
451 : }
452 : else
453 : {
454 : /* write the number of MASA transport channels */
455 700417 : push_next_indice( hMetaData, nchan_transport - 1, MASA_TRANSP_BITS );
456 : }
457 790737 : hQMetaData->metadata_max_bits -= MASA_TRANSP_BITS;
458 : }
459 :
460 1111657 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MODE_NONE )
461 : {
462 90320 : if ( nchan_ism >= 3 ) /* if 3 or 4 objects */
463 : {
464 57654 : push_next_indice( hMetaData, 5 - nchan_ism, MASA_HEADER_BITS );
465 : }
466 : else
467 : {
468 32666 : push_next_indice( hMetaData, 3, MASA_HEADER_BITS );
469 : }
470 90320 : hQMetaData->metadata_max_bits -= MASA_HEADER_BITS;
471 : }
472 : else
473 : {
474 : /* the MASA_ISM_FORMAT is not signalled here */
475 : /* write reserved bits */
476 1021337 : push_next_indice( hMetaData, 0, MASA_HEADER_BITS );
477 1021337 : hQMetaData->metadata_max_bits -= MASA_HEADER_BITS;
478 : }
479 1111657 : if ( !( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MODE_NONE && nchan_ism > 2 ) )
480 : {
481 : /* write number of directions */
482 1054003 : push_next_indice( hMetaData, hQMetaData->no_directions - 1, 1 );
483 1054003 : hQMetaData->metadata_max_bits -= 1;
484 : }
485 : /* write subframe mode */
486 1111657 : push_next_indice( hMetaData, hQMetaData->q_direction[0].cfg.nblocks == 1 ? 1 : 0, MASA_SUBFRAME_BITS );
487 1111657 : hQMetaData->metadata_max_bits -= MASA_SUBFRAME_BITS;
488 : }
489 :
490 1302497 : if ( ivas_format == MC_FORMAT )
491 : {
492 : int16_t lfeBitsWritten;
493 190840 : lfeBitsWritten = encode_lfe_to_total_energy_ratio( hMasa, hMetaData, ivas_total_brate );
494 190840 : hQMetaData->metadata_max_bits -= lfeBitsWritten;
495 : }
496 :
497 : /* Move data from encoder to qmetadata */
498 1302497 : if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT )
499 : {
500 1111657 : move_metadata_to_qmetadata( hMasa, hQMetaData );
501 : }
502 :
503 1302497 : if ( hMasa->config.max_metadata_bits < MINIMUM_BIT_BUDGET_NORMAL_META && !hMasa->config.joinedSubframes )
504 : {
505 409021 : reduce_metadata_further( hMasa, hQMetaData, ivas_format );
506 :
507 409021 : low_bitrate_mode = ( ivas_total_brate <= 32000 );
508 :
509 : /* Write low bitrate mode. 1 signals that we have merged through time, 0 signals merge through frequency. */
510 409021 : push_next_indice( hMetaData, hQMetaData->q_direction[0].cfg.nblocks == 1 ? 1 : 0, MASA_LOWBITRATE_MODE_BITS );
511 409021 : hQMetaData->metadata_max_bits -= MASA_LOWBITRATE_MODE_BITS;
512 : }
513 :
514 : /* Encode MASA+ISM metadata */
515 1302497 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ )
516 : {
517 : /* encode MASA/ISM energy ratios */
518 82794 : ivas_encode_masaism_metadata( hMasa, hQMetaData, hMetaData, hIsmMetaData, nchan_ism, low_bitrate_mode, hOMasa->nCodingBands, hOMasa->nSubframes, idx_separated_object, ism_imp );
519 : }
520 : else
521 : {
522 1219703 : if ( ivas_format == MASA_ISM_FORMAT )
523 : {
524 328446 : hMasa->data.hOmasaData->masa_to_total_energy_ratio[0][0] = -1; /* signals NOT to adjust the energy ratios */
525 : }
526 : }
527 :
528 : /* Encode metadata */
529 1302497 : masa_total_brate = ivas_total_brate;
530 1302497 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_DISC )
531 : {
532 150308 : masa_total_brate = calculate_cpe_brate_MASA_ISM( ism_mode, ivas_total_brate, nchan_ism );
533 : }
534 :
535 1302497 : if ( masa_total_brate >= IVAS_384k )
536 : {
537 74940 : if ( masa_total_brate >= IVAS_512k )
538 : {
539 28990 : if ( ( error = ivas_qmetadata_enc_encode_hr_384_512( hMetaData, hQMetaData, 16, 4 ) ) != IVAS_ERR_OK )
540 : {
541 0 : return error;
542 : }
543 : }
544 : else
545 : {
546 45950 : if ( ( error = ivas_qmetadata_enc_encode_hr_384_512( hMetaData, hQMetaData, 11, 3 ) ) != IVAS_ERR_OK )
547 : {
548 0 : return error;
549 : }
550 : }
551 : }
552 : else
553 : {
554 1227557 : if ( ( error = ivas_qmetadata_enc_encode( hMetaData, hQMetaData, 0 ) ) != IVAS_ERR_OK )
555 : {
556 0 : return error;
557 : }
558 : }
559 :
560 1302497 : if ( ivas_format == MASA_ISM_FORMAT && ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ )
561 : {
562 : /* Modify spatial metadata based on the MASA-to-total energy ratios */
563 82794 : ivas_omasa_modify_masa_energy_ratios( hQMetaData, hMasa->data.hOmasaData->masa_to_total_energy_ratio );
564 : }
565 :
566 1302497 : *nb_bits_metadata = hMetaData->nb_bits_tot;
567 :
568 1302497 : if ( ivas_format == MASA_FORMAT && Opt_DTX_ON )
569 : {
570 : /* save old values */
571 70127 : uint8_t numCodingBands = hMasa->config.numCodingBands;
572 70127 : uint8_t numTwoDirBands = hMasa->config.numTwoDirBands;
573 70127 : int16_t nbands = hQMetaData->q_direction[0].cfg.nbands;
574 70127 : uint8_t numberOfDirections = hMasa->config.numberOfDirections;
575 70127 : uint8_t numberOfDirectionsMeta = hMasa->masaMetadata.descriptive_meta.numberOfDirections;
576 70127 : uint16_t numberOfDirectionsQMetaData = hQMetaData->no_directions;
577 :
578 70127 : if ( !( hMasa->config.numberOfDirections == 1 && hQMetaData->q_direction->cfg.nbands == 5 ) )
579 : {
580 77655 : for ( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
581 : {
582 258850 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
583 : {
584 207080 : mvr2r( h_orig_metadata[i].azimuth[j], hMasa->masaMetadata.directional_meta[i].azimuth[j], MASA_FREQUENCY_BANDS );
585 207080 : mvr2r( h_orig_metadata[i].elevation[j], hMasa->masaMetadata.directional_meta[i].elevation[j], MASA_FREQUENCY_BANDS );
586 207080 : mvr2r( h_orig_metadata[i].energy_ratio[j], hMasa->masaMetadata.directional_meta[i].energy_ratio[j], MASA_FREQUENCY_BANDS );
587 : }
588 : }
589 :
590 : /* Force to have 5 bands and 1 direction */
591 25885 : hMasa->config.numCodingBands = 5;
592 25885 : hMasa->config.numTwoDirBands = 0;
593 25885 : combine_freqbands_and_subframes( hMasa );
594 25885 : hQMetaData->q_direction[0].cfg.nbands = 5;
595 :
596 25885 : if ( hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands < hMasa->config.numCodingBands )
597 : {
598 : /* Combine directions */
599 4669 : ivas_masa_combine_directions( hMasa );
600 :
601 : /* If we joined all bands, then metadata is now one directional. */
602 4669 : if ( hMasa->config.numTwoDirBands == 0 )
603 : {
604 4669 : hMasa->config.numberOfDirections = 1;
605 4669 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
606 4669 : hQMetaData->no_directions = 1;
607 : }
608 : }
609 :
610 25885 : move_metadata_to_qmetadata( hMasa, hQMetaData );
611 :
612 155310 : for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
613 : {
614 129425 : hQMetaData->q_direction[0].band_data[j].energy_ratio_index[0] = masa_sq( 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[0], diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS );
615 : }
616 : }
617 :
618 70127 : free( h_orig_metadata );
619 :
620 70127 : ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, masa_sid_descriptor, 0, ivas_format );
621 :
622 : /* restore old values */
623 70127 : hMasa->config.numCodingBands = numCodingBands;
624 70127 : hMasa->config.numTwoDirBands = numTwoDirBands;
625 70127 : hQMetaData->q_direction[0].cfg.nbands = nbands;
626 70127 : hMasa->config.numberOfDirections = numberOfDirections;
627 70127 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = numberOfDirectionsMeta;
628 70127 : hQMetaData->no_directions = numberOfDirectionsQMetaData;
629 : }
630 :
631 1302497 : return IVAS_ERR_OK;
632 : }
633 :
634 :
635 : /*-----------------------------------------------------------------------*
636 : * ivas_masa_estimate_energy()
637 : *
638 : *
639 : *-----------------------------------------------------------------------*/
640 :
641 1111657 : void ivas_masa_estimate_energy(
642 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
643 : float *data_f[], /* i : Input audio channels */
644 : const int16_t input_frame, /* i : frame length */
645 : const int16_t nchan_transport /* i : number of MASA input/transport channels */
646 : )
647 : {
648 : float Input_RealBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
649 : float Input_ImagBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
650 : int16_t block_m_idx, band_m_idx;
651 : int16_t mrange[2], brange[2];
652 : int16_t i, j, ts, l_ts, maxBin;
653 :
654 1111657 : maxBin = (int16_t) ( (float) CLDFB_NO_CHANNELS_MAX * (float) input_frame / L_FRAME48k + 0.5f );
655 :
656 1111657 : l_ts = input_frame / CLDFB_NO_COL_MAX;
657 :
658 5558285 : for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
659 : {
660 4446628 : mrange[0] = hMasa->config.block_grouping[block_m_idx];
661 4446628 : mrange[1] = hMasa->config.block_grouping[block_m_idx + 1];
662 :
663 4446628 : set_zero( hMasa->data.energy[block_m_idx], MASA_FREQUENCY_BANDS );
664 :
665 22233140 : for ( ts = mrange[0]; ts < mrange[1]; ts++ )
666 : {
667 49305216 : for ( i = 0; i < nchan_transport; i++ )
668 : {
669 31518704 : cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Input_RealBuffer[i], Input_ImagBuffer[i], l_ts, hMasa->data.cldfbAnaEnc[i] );
670 : }
671 :
672 444662800 : for ( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
673 : {
674 426876288 : brange[0] = hMasa->config.band_grouping[band_m_idx];
675 426876288 : brange[1] = hMasa->config.band_grouping[band_m_idx + 1];
676 :
677 1183325184 : for ( i = 0; i < nchan_transport; i++ )
678 : {
679 756448896 : if ( brange[0] > maxBin )
680 : {
681 2860320 : hMasa->data.energy[block_m_idx][band_m_idx] = 0;
682 2860320 : continue;
683 : }
684 753588576 : else if ( brange[1] >= maxBin )
685 : {
686 34137024 : brange[1] = maxBin;
687 : }
688 :
689 2573275616 : for ( j = brange[0]; j < brange[1]; j++ )
690 : {
691 1819687040 : hMasa->data.energy[block_m_idx][band_m_idx] += Input_RealBuffer[i][j] * Input_RealBuffer[i][j] + Input_ImagBuffer[i][j] * Input_ImagBuffer[i][j];
692 : }
693 : }
694 : }
695 : }
696 : }
697 :
698 1111657 : return;
699 : }
700 :
701 :
702 : /*-----------------------------------------------------------------------*
703 : * ivas_masa_enc_config()
704 : *
705 : * Frame-by-frame configuration of MASA encoder
706 : *-----------------------------------------------------------------------*/
707 :
708 1118767 : ivas_error ivas_masa_enc_config(
709 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
710 : )
711 : {
712 : int16_t i;
713 : MASA_ENCODER_HANDLE hMasa;
714 : IVAS_QMETADATA_HANDLE hQMetaData;
715 : IVAS_FORMAT ivas_format;
716 : uint8_t joinedSubframes;
717 : uint8_t coherencePresent;
718 : uint8_t isActualTwoDir; /* Flag to tell that when there are two directions present in metadata, they both contain meaningful information. */
719 : int32_t ivas_total_brate;
720 : uint8_t maxBand;
721 : int16_t maxBin, sf;
722 : ivas_error error;
723 : int32_t ism_total_brate;
724 : int32_t masa_total_brate;
725 :
726 1118767 : error = IVAS_ERR_OK;
727 :
728 1118767 : hMasa = st_ivas->hMasa;
729 1118767 : hQMetaData = st_ivas->hQMetaData;
730 1118767 : ivas_format = st_ivas->hEncoderConfig->ivas_format;
731 1118767 : ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
732 :
733 1118767 : ism_total_brate = 0;
734 1118767 : if ( ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) )
735 : {
736 885264 : for ( i = 0; i < st_ivas->nSCE; i++ )
737 : {
738 564344 : ism_total_brate += st_ivas->hSCE[i]->element_brate;
739 : }
740 : }
741 :
742 1118767 : ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE, ivas_format, st_ivas->ism_mode, ism_total_brate );
743 :
744 1118767 : hQMetaData->is_masa_ivas_format = 1;
745 :
746 1118767 : if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT )
747 : {
748 1111657 : masa_metadata_direction_alignment( hMasa );
749 :
750 1111657 : detect_framing_async( hMasa ); /* detect the offset, set 1sf/4sf mode based on this. potentially also shift the metadata using a history buffer */
751 :
752 1111657 : if ( hMasa->data.sync_state.frame_mode == MASA_FRAME_1SF && hMasa->data.sync_state.prev_offset != 0 )
753 : {
754 : /* average over sub-frames */
755 142467 : average_masa_metadata( &( hMasa->masaMetadata ), hMasa->data.energy, &( hMasa->data.Sph_Grid16 ), ivas_total_brate == IVAS_512k ? TRUE : FALSE );
756 : }
757 :
758 : /* Inspect metadata for parameter changes that affect coding. */
759 1111657 : detect_metadata_composition( hMasa, &joinedSubframes, &coherencePresent, &isActualTwoDir );
760 1111657 : hMasa->config.joinedSubframes = joinedSubframes;
761 1111657 : hMasa->config.coherencePresent = coherencePresent;
762 1111657 : hMasa->config.numberOfDirections = ( hMasa->masaMetadata.descriptive_meta.numberOfDirections + 1 ) == 2 && isActualTwoDir ? 2 : 1;
763 : }
764 7110 : else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA )
765 : {
766 : /* For McMASA, these are set only once as this function is called only once. */
767 7110 : hMasa->config.joinedSubframes = 0;
768 7110 : hMasa->config.numberOfDirections = 1;
769 : }
770 :
771 1118767 : if ( ivas_format == MASA_ISM_FORMAT )
772 : {
773 411240 : ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE );
774 : }
775 : else
776 : {
777 707527 : ivas_masa_set_coding_config( &( hMasa->config ), hMasa->data.band_mapping, ivas_total_brate, st_ivas->nchan_transport, ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) );
778 : }
779 :
780 : /* Setup importance weights for two-direction band selection. */
781 1118767 : if ( hMasa->config.numberOfDirections == 2 )
782 : {
783 432192 : set_f( hMasa->data.importanceWeight, 1.0f, hMasa->config.numCodingBands );
784 :
785 432192 : if ( hMasa->config.numCodingBands == 5 )
786 : {
787 280403 : hMasa->data.importanceWeight[4] = 0.7f;
788 : }
789 151789 : else if ( hMasa->config.numCodingBands == 8 )
790 : {
791 25850 : hMasa->data.importanceWeight[7] = 0.7f;
792 : }
793 125939 : else if ( hMasa->config.numCodingBands == 10 )
794 : {
795 0 : hMasa->data.importanceWeight[8] = 0.7f;
796 0 : hMasa->data.importanceWeight[9] = 0.1f;
797 : }
798 125939 : else if ( hMasa->config.numCodingBands == 12 )
799 : {
800 55807 : hMasa->data.importanceWeight[10] = 0.7f;
801 55807 : hMasa->data.importanceWeight[11] = 0.1f;
802 : }
803 70132 : else if ( hMasa->config.numCodingBands == 18 )
804 : {
805 47282 : hMasa->data.importanceWeight[14] = 0.8f;
806 47282 : hMasa->data.importanceWeight[15] = 0.5f;
807 47282 : hMasa->data.importanceWeight[16] = 0.2f;
808 47282 : hMasa->data.importanceWeight[17] = 0.0f;
809 : }
810 22850 : else if ( hMasa->config.numCodingBands == 24 )
811 : {
812 22850 : hMasa->data.importanceWeight[20] = 0.8f;
813 22850 : hMasa->data.importanceWeight[21] = 0.5f;
814 22850 : hMasa->data.importanceWeight[22] = 0.2f;
815 22850 : hMasa->data.importanceWeight[23] = 0.0f;
816 : }
817 :
818 432192 : if ( hMasa->config.numTwoDirBands == hMasa->config.numCodingBands )
819 : {
820 7944 : set_c( (int8_t *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
821 : }
822 : }
823 : else
824 : {
825 686575 : set_c( (int8_t *) hMasa->data.twoDirBands, 0, hMasa->config.numCodingBands );
826 : }
827 :
828 : /* Set qmeta to correct values */
829 1118767 : if ( ( error = ivas_qmetadata_allocate_memory( hQMetaData, hMasa->config.numCodingBands, hMasa->config.numberOfDirections == 2 && hMasa->config.numTwoDirBands != 0 ? 2 : 1, hMasa->config.useCoherence ) ) != IVAS_ERR_OK )
830 : {
831 0 : return error;
832 : }
833 :
834 2444408 : for ( i = 0; i < hQMetaData->no_directions; i++ )
835 : {
836 1325641 : hQMetaData->q_direction[i].cfg.nbands = hMasa->config.numCodingBands;
837 1325641 : hQMetaData->q_direction[i].cfg.nblocks = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES;
838 :
839 1325641 : if ( ivas_format == MC_FORMAT )
840 : {
841 7110 : hQMetaData->q_direction[i].cfg.mc_ls_setup = st_ivas->hEncoderConfig->mc_input_setup;
842 : }
843 : else
844 : {
845 : /* Just to be sure that this default value is maintained */
846 1318531 : hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
847 : }
848 : }
849 :
850 1118767 : hQMetaData->all_coherence_zero = !hMasa->config.coherencePresent;
851 :
852 1118767 : ivas_set_qmetadata_maxbit_req( hQMetaData, ivas_format );
853 :
854 : /* Find maximum band usable */
855 1118767 : maxBin = (int16_t) ( st_ivas->hEncoderConfig->input_Fs * INV_CLDFB_BANDWIDTH );
856 1118767 : maxBand = 0;
857 28909736 : while ( maxBand <= MASA_FREQUENCY_BANDS && MASA_band_grouping_24[maxBand] <= maxBin )
858 : {
859 27790969 : maxBand++;
860 : }
861 1118767 : maxBand--;
862 :
863 1118767 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
864 1118767 : masa_total_brate = ivas_total_brate;
865 1118767 : if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC )
866 : {
867 150308 : masa_total_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->hEncoderConfig->nchan_ism );
868 : }
869 1118767 : if ( masa_total_brate >= IVAS_384k && ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) )
870 : {
871 : int16_t continueLoop;
872 74940 : continueLoop = 1;
873 251696 : while ( maxBand > 5 && continueLoop )
874 : {
875 606656 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
876 : {
877 500606 : if ( hMasa->data.energy[sf][maxBand - 1] > 100000 )
878 : {
879 70706 : continueLoop = 0;
880 70706 : break;
881 : }
882 : }
883 176756 : if ( continueLoop )
884 : {
885 106050 : maxBand--;
886 : }
887 : }
888 :
889 74940 : if ( maxBand < MASA_MAXIMUM_CODING_SUBBANDS )
890 : {
891 15616 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = MASA_MAXIMUM_CODING_SUBBANDS - maxBand;
892 : }
893 : else
894 : {
895 59324 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
896 : }
897 : }
898 :
899 1118767 : masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, maxBand, masa_total_brate >= IVAS_384k, NULL );
900 :
901 1118767 : if ( hMasa->config.numTwoDirBands >= hMasa->config.numCodingBands )
902 : {
903 9462 : hMasa->config.numTwoDirBands = hMasa->config.numCodingBands;
904 9462 : set_c( (int8_t *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
905 : }
906 :
907 : /* Transmit stereo signals using a mono downmix at lowest bitrates */
908 1118767 : if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL )
909 : {
910 352536 : st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ( ivas_total_brate - ism_total_brate < MASA_STEREO_MIN_BITRATE ) ? 1 : 0;
911 : }
912 :
913 1118767 : if ( ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_DISC ) )
914 : {
915 320920 : if ( st_ivas->hCPE[0]->element_mode == IVAS_CPE_DFT || st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt < OMASA_STEREO_SW_CNT_MAX )
916 : {
917 133660 : st_ivas->hMasa->data.hOmasaData->lp_noise_CPE = st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise;
918 : }
919 : else
920 : {
921 187260 : st_ivas->hMasa->data.hOmasaData->lp_noise_CPE = ( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise + st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise ) / CPE_CHANNELS;
922 : }
923 : }
924 :
925 1118767 : return error;
926 : }
927 :
928 :
929 : /*-----------------------------------------------------------------------*
930 : * ivas_masa_surrcoh_signicant()
931 : *
932 : * Determine if surrounding coherence is significant in this frame and should be encoded
933 : *-----------------------------------------------------------------------*/
934 :
935 158916 : uint8_t ivas_masa_surrcoh_signicant(
936 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */
937 : float diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio */
938 : const int16_t nSubFrames, /* i : Number of sub frames */
939 : const int16_t nBands /* i : Number of frequency bands */
940 : )
941 : {
942 : float significanceMeasure1, significanceMeasure2, significanceMeasure;
943 : float surrCohToTotal, surrCohToTotalSum, surrCohToTotalTimesDiffSum, diffSum;
944 : int16_t sf, band;
945 158916 : float surrCohSignificanceCoef = 0.4f;
946 158916 : float threshold = 0.1f;
947 :
948 391157 : for ( sf = 0; sf < nSubFrames; sf++ )
949 : {
950 273396 : surrCohToTotalSum = 0.0f;
951 273396 : surrCohToTotalTimesDiffSum = 0.0f;
952 273396 : diffSum = 0.0f;
953 6418230 : for ( band = 0; band < nBands; band++ )
954 : {
955 6144834 : surrCohToTotal = diffuse_to_total_ratio[sf][band] * surroundingCoherence[sf][band];
956 6144834 : surrCohToTotalSum += surrCohToTotal;
957 6144834 : surrCohToTotalTimesDiffSum += diffuse_to_total_ratio[sf][band] * surrCohToTotal;
958 6144834 : diffSum += diffuse_to_total_ratio[sf][band];
959 : }
960 273396 : significanceMeasure1 = surrCohToTotalSum / (float) nBands;
961 273396 : significanceMeasure2 = surrCohSignificanceCoef * surrCohToTotalTimesDiffSum / ( diffSum + EPSILON );
962 273396 : significanceMeasure = max( significanceMeasure1, significanceMeasure2 );
963 :
964 273396 : if ( significanceMeasure > threshold )
965 : {
966 41155 : return 1; /* Surrounding coherence was significant in at least one subframe */
967 : }
968 : }
969 :
970 117761 : return 0; /* Surrounding coherence was not significant in any subframe */
971 : }
972 :
973 :
974 : /*-----------------------------------------------------------------------*
975 : * Local functions
976 : *-----------------------------------------------------------------------*/
977 :
978 1137542 : static void combine_freqbands_and_subframes(
979 : MASA_ENCODER_HANDLE hMasa )
980 : {
981 : int16_t i, j, k, m;
982 : float aziRad, eleRad;
983 : float x[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
984 : float y[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
985 : float z[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
986 : float vecLen;
987 : float xSum, ySum, zSum;
988 : float energySum;
989 : float spreadCohSum;
990 : float surrCohSum;
991 : float energyRatioSum;
992 : float surrCohTemp;
993 : float energyRatioTemp;
994 : float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
995 : int16_t brange[2];
996 : uint8_t numCodingBands;
997 : uint8_t numSf;
998 : uint8_t numDirections;
999 : MASA_METADATA_HANDLE hMeta;
1000 : uint8_t mergeRatiosOverSubframes;
1001 : uint8_t computeCoherence;
1002 :
1003 1137542 : numCodingBands = hMasa->config.numCodingBands;
1004 1137542 : numDirections = hMasa->config.numberOfDirections;
1005 1137542 : numSf = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES;
1006 1137542 : hMeta = &( hMasa->masaMetadata );
1007 :
1008 1137542 : mergeRatiosOverSubframes = hMasa->config.mergeRatiosOverSubframes;
1009 1137542 : computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
1010 :
1011 : /* If metadata subframes are joined then we need all energy to be in the first subframe for combining.
1012 : * This optimizes following computations a bit.
1013 : * Note: If energy is used elsewhere, then this can cause problems and local energy should be used. */
1014 1137542 : if ( numSf == 1 )
1015 : {
1016 1542288 : for ( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
1017 : {
1018 28917900 : for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
1019 : {
1020 27761184 : hMasa->data.energy[0][k] += hMasa->data.energy[j][k];
1021 : }
1022 : }
1023 : }
1024 :
1025 1137542 : if ( numCodingBands <= MAX_REDUCED_NBANDS )
1026 : {
1027 : /* reduce metadata *frequency* resolution. time resolution is not touched */
1028 2450255 : for ( i = 0; i < numDirections; i++ )
1029 : {
1030 5696451 : for ( j = 0; j < numSf; j++ ) /* NB: for numSf==1, operates only on first sub-frame */
1031 : {
1032 106583550 : for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
1033 : {
1034 102320208 : aziRad = hMeta->directional_meta[i].azimuth[j][k] / 180.0f * EVS_PI;
1035 102320208 : eleRad = hMeta->directional_meta[i].elevation[j][k] / 180.0f * EVS_PI;
1036 102320208 : vecLen = hMeta->directional_meta[i].energy_ratio[j][k] * hMasa->data.energy[j][k];
1037 :
1038 102320208 : x[i][j][k] = cosf( aziRad ) * cosf( eleRad ) * vecLen;
1039 102320208 : y[i][j][k] = sinf( aziRad ) * cosf( eleRad ) * vecLen;
1040 102320208 : z[i][j][k] = sinf( eleRad ) * vecLen;
1041 : }
1042 : }
1043 : }
1044 :
1045 2450255 : for ( i = 0; i < numDirections; i++ )
1046 : {
1047 5696451 : for ( j = 0; j < numSf; j++ )
1048 : {
1049 32695617 : for ( k = 0; k < numCodingBands; k++ )
1050 : {
1051 28432275 : brange[0] = hMasa->data.band_mapping[k];
1052 28432275 : brange[1] = hMasa->data.band_mapping[k + 1];
1053 :
1054 28432275 : xSum = 0.0f;
1055 28432275 : ySum = 0.0f;
1056 28432275 : zSum = 0.0f;
1057 28432275 : energySum = 0.0f;
1058 28432275 : spreadCohSum = 0.0f;
1059 :
1060 128648548 : for ( m = brange[0]; m < brange[1]; m++ )
1061 : {
1062 100216273 : xSum += x[i][j][m];
1063 100216273 : ySum += y[i][j][m];
1064 100216273 : zSum += z[i][j][m];
1065 100216273 : energySum += hMasa->data.energy[j][m];
1066 : }
1067 :
1068 28432275 : aziRad = atan2f( ySum, xSum );
1069 28432275 : eleRad = atan2f( zSum, sqrtf( xSum * xSum + ySum * ySum ) );
1070 :
1071 28432275 : hMeta->directional_meta[i].azimuth[j][k] = aziRad / EVS_PI * 180.0f;
1072 28432275 : hMeta->directional_meta[i].elevation[j][k] = eleRad / EVS_PI * 180.0f;
1073 :
1074 28432275 : vecLen = sqrtf( xSum * xSum + ySum * ySum + zSum * zSum );
1075 28432275 : hMeta->directional_meta[i].energy_ratio[j][k] = vecLen / ( energySum + EPSILON );
1076 :
1077 28432275 : if ( computeCoherence )
1078 : {
1079 65693318 : for ( m = brange[0]; m < brange[1]; m++ )
1080 : {
1081 48873580 : spreadCohSum += hMeta->directional_meta[i].spread_coherence[j][m] * hMasa->data.energy[j][m];
1082 : }
1083 16819738 : hMeta->directional_meta[i].spread_coherence[j][k] = spreadCohSum / ( energySum + EPSILON );
1084 :
1085 16819738 : if ( i == 0 )
1086 : {
1087 11653209 : surrCohSum = 0.0f;
1088 45371013 : for ( m = brange[0]; m < brange[1]; m++ )
1089 : {
1090 33717804 : surrCohSum += hMeta->common_meta.surround_coherence[j][m] * hMasa->data.energy[j][m];
1091 : }
1092 11653209 : hMeta->common_meta.surround_coherence[j][k] = surrCohSum / ( energySum + EPSILON );
1093 : }
1094 : }
1095 :
1096 28432275 : if ( i == 0 )
1097 : {
1098 20156817 : energy[j][k] = energySum;
1099 : }
1100 : }
1101 : }
1102 : }
1103 : }
1104 120396 : else if ( mergeRatiosOverSubframes ) /* keep frequency resolution */
1105 : {
1106 123390 : for ( j = 0; j < numSf; j++ )
1107 : {
1108 2463800 : for ( k = 0; k < numCodingBands; k++ )
1109 : {
1110 2365088 : energy[j][k] = hMasa->data.energy[j][k];
1111 : }
1112 : }
1113 : }
1114 :
1115 1137542 : if ( mergeRatiosOverSubframes )
1116 : {
1117 5155228 : for ( k = 0; k < numCodingBands; k++ )
1118 : {
1119 4482321 : energySum = 0.0f;
1120 22411605 : for ( j = 0; j < numSf; j++ )
1121 : {
1122 17929284 : energySum += energy[j][k];
1123 : }
1124 :
1125 4482321 : if ( computeCoherence )
1126 : {
1127 2696265 : surrCohSum = 0.0f;
1128 13481325 : for ( j = 0; j < numSf; j++ )
1129 : {
1130 10785060 : surrCohSum += energy[j][k] * hMeta->common_meta.surround_coherence[j][k];
1131 : }
1132 2696265 : surrCohTemp = surrCohSum / ( energySum + EPSILON );
1133 :
1134 13481325 : for ( j = 0; j < numSf; j++ )
1135 : {
1136 10785060 : hMeta->common_meta.surround_coherence[j][k] = surrCohTemp;
1137 : }
1138 : }
1139 :
1140 10515352 : for ( i = 0; i < numDirections; i++ )
1141 : {
1142 6033031 : energyRatioSum = 0.0f;
1143 30165155 : for ( j = 0; j < numSf; j++ )
1144 : {
1145 24132124 : energyRatioSum += energy[j][k] * hMeta->directional_meta[i].energy_ratio[j][k];
1146 : }
1147 6033031 : energyRatioTemp = energyRatioSum / ( energySum + EPSILON );
1148 :
1149 30165155 : for ( j = 0; j < numSf; j++ )
1150 : {
1151 24132124 : hMeta->directional_meta[i].energy_ratio[j][k] = energyRatioTemp;
1152 : }
1153 : }
1154 : }
1155 : }
1156 :
1157 1137542 : return;
1158 : }
1159 :
1160 :
1161 : /*-------------------------------------------------------------------*
1162 : * ivas_masa_combine_directions()
1163 : *
1164 : *
1165 : *-------------------------------------------------------------------*/
1166 :
1167 427399 : void ivas_masa_combine_directions(
1168 : MASA_ENCODER_HANDLE hMasa )
1169 : {
1170 : int16_t i, j, k;
1171 : uint8_t numCodingBands;
1172 : uint8_t numSf;
1173 : uint8_t numDirections;
1174 : uint8_t computeCoherence;
1175 : MASA_METADATA_HANDLE hMeta;
1176 :
1177 : float aziRad;
1178 : float eleRad;
1179 : float x[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1180 : float y[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1181 : float z[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1182 : float vecLen;
1183 : float xSum[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1184 : float ySum[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1185 : float zSum[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1186 : float sumVecLen[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1187 : float tempImportance;
1188 : float importance[MASA_FREQUENCY_BANDS];
1189 : int16_t indicesOfLargest[MASA_FREQUENCY_BANDS];
1190 :
1191 : float ambience1dir;
1192 : float ambience2dir;
1193 : float ambienceIncrease;
1194 : float ratioSum;
1195 : float origSurrCohEne;
1196 : float newSurrCohEne;
1197 :
1198 427399 : numCodingBands = hMasa->config.numCodingBands;
1199 427399 : numDirections = hMasa->config.numberOfDirections;
1200 427399 : numSf = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES;
1201 :
1202 427399 : hMeta = &( hMasa->masaMetadata );
1203 :
1204 427399 : computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
1205 :
1206 1282197 : for ( i = 0; i < numDirections; i++ )
1207 : {
1208 3393184 : for ( j = 0; j < numSf; j++ )
1209 : {
1210 30863046 : for ( k = 0; k < numCodingBands; k++ )
1211 : {
1212 28324660 : aziRad = hMeta->directional_meta[i].azimuth[j][k] / 180.0f * EVS_PI;
1213 28324660 : eleRad = hMeta->directional_meta[i].elevation[j][k] / 180.0f * EVS_PI;
1214 28324660 : vecLen = hMeta->directional_meta[i].energy_ratio[j][k];
1215 :
1216 28324660 : x[i][j][k] = cosf( aziRad ) * cosf( eleRad ) * vecLen;
1217 28324660 : y[i][j][k] = sinf( aziRad ) * cosf( eleRad ) * vecLen;
1218 28324660 : z[i][j][k] = sinf( eleRad ) * vecLen;
1219 : }
1220 : }
1221 : }
1222 :
1223 : /* Compute sum vector */
1224 1696592 : for ( j = 0; j < numSf; j++ )
1225 : {
1226 15431523 : for ( k = 0; k < numCodingBands; k++ )
1227 : {
1228 14162330 : xSum[j][k] = x[0][j][k] + x[1][j][k];
1229 14162330 : ySum[j][k] = y[0][j][k] + y[1][j][k];
1230 14162330 : zSum[j][k] = z[0][j][k] + z[1][j][k];
1231 14162330 : sumVecLen[j][k] = sqrtf( xSum[j][k] * xSum[j][k] + ySum[j][k] * ySum[j][k] + zSum[j][k] * zSum[j][k] );
1232 : }
1233 : }
1234 :
1235 427399 : if ( hMasa->config.numTwoDirBands > 0 )
1236 : {
1237 : /* Estimate the importance of having two directions instead of one */
1238 2378017 : for ( i = 0; i < numCodingBands; i++ )
1239 : {
1240 2180605 : importance[i] = 0.0f;
1241 7824329 : for ( j = 0; j < numSf; j++ )
1242 : {
1243 5643724 : tempImportance = hMeta->directional_meta[0].energy_ratio[j][i] + hMeta->directional_meta[1].energy_ratio[j][i] - sumVecLen[j][i];
1244 5643724 : importance[i] += tempImportance;
1245 : }
1246 2180605 : importance[i] /= (float) numSf;
1247 2180605 : importance[i] *= hMasa->data.importanceWeight[i];
1248 : }
1249 :
1250 : /* Determine bands where to use two directions */
1251 197412 : find_n_largest( importance, indicesOfLargest, numCodingBands, hMasa->config.numTwoDirBands );
1252 : }
1253 :
1254 5574486 : for ( i = 0; i < numCodingBands; i++ )
1255 : {
1256 5147087 : hMasa->data.twoDirBands[i] = 0;
1257 : }
1258 :
1259 1184096 : for ( i = 0; i < hMasa->config.numTwoDirBands; i++ )
1260 : {
1261 756697 : hMasa->data.twoDirBands[indicesOfLargest[i]] = 1;
1262 : }
1263 :
1264 : /* Combine directions on the remaining bands */
1265 5574486 : for ( i = 0; i < numCodingBands; i++ )
1266 : {
1267 5147087 : if ( hMasa->data.twoDirBands[i] == 0 )
1268 : {
1269 16487507 : for ( j = 0; j < numSf; j++ )
1270 : {
1271 12097117 : aziRad = atan2f( ySum[j][i], xSum[j][i] );
1272 12097117 : eleRad = atan2f( zSum[j][i], sqrtf( xSum[j][i] * xSum[j][i] + ySum[j][i] * ySum[j][i] ) );
1273 :
1274 12097117 : hMeta->directional_meta[0].azimuth[j][i] = aziRad / EVS_PI * 180.0f;
1275 12097117 : hMeta->directional_meta[0].elevation[j][i] = eleRad / EVS_PI * 180.0f;
1276 :
1277 12097117 : ratioSum = hMeta->directional_meta[0].energy_ratio[j][i] + hMeta->directional_meta[1].energy_ratio[j][i];
1278 12097117 : if ( computeCoherence )
1279 : {
1280 4002758 : hMeta->directional_meta[0].spread_coherence[j][i] =
1281 4002758 : ( hMeta->directional_meta[0].spread_coherence[j][i] * hMeta->directional_meta[0].energy_ratio[j][i] + hMeta->directional_meta[1].spread_coherence[j][i] * hMeta->directional_meta[1].energy_ratio[j][i] ) / ( ratioSum + EPSILON );
1282 : }
1283 :
1284 12097117 : ambience2dir = 1.0f - ratioSum;
1285 12097117 : hMeta->directional_meta[0].energy_ratio[j][i] = sumVecLen[j][i] / ( hMeta->directional_meta[0].energy_ratio[j][i] + hMeta->directional_meta[1].energy_ratio[j][i] + ambience2dir / 2.0f );
1286 12097117 : hMeta->directional_meta[1].energy_ratio[j][i] = 0.0f;
1287 12097117 : hMeta->common_meta.diffuse_to_total_ratio[j][i] = 1.0f - hMeta->directional_meta[0].energy_ratio[j][i];
1288 12097117 : if ( computeCoherence )
1289 : {
1290 4002758 : ambience1dir = 1.0f - hMeta->directional_meta[0].energy_ratio[j][i];
1291 4002758 : ambienceIncrease = max( ambience1dir - ambience2dir, 0.0f );
1292 :
1293 4002758 : origSurrCohEne = ambience2dir * hMeta->common_meta.surround_coherence[j][i];
1294 4002758 : newSurrCohEne = ambienceIncrease * hMeta->directional_meta[0].spread_coherence[j][i];
1295 4002758 : hMeta->common_meta.surround_coherence[j][i] = min( 1.0f, ( origSurrCohEne + newSurrCohEne ) / ( ambience1dir + EPSILON ) );
1296 : }
1297 : }
1298 : }
1299 : }
1300 :
1301 427399 : return;
1302 : }
1303 :
1304 :
1305 197412 : static void find_n_largest(
1306 : const float *input,
1307 : int16_t *largestIndices,
1308 : const int16_t numElements,
1309 : const int16_t numLargest )
1310 : {
1311 : int16_t i, j;
1312 : float largestValue;
1313 : int16_t largestIndex;
1314 : float values[MASA_FREQUENCY_BANDS];
1315 :
1316 2378017 : for ( j = 0; j < numElements; j++ )
1317 : {
1318 2180605 : values[j] = input[j];
1319 : }
1320 :
1321 954109 : for ( i = 0; i < numLargest; i++ )
1322 : {
1323 756697 : largestValue = values[0];
1324 756697 : largestIndex = 0;
1325 11277099 : for ( j = 1; j < numElements; j++ )
1326 : {
1327 10520402 : if ( values[j] > largestValue )
1328 : {
1329 1545972 : largestValue = values[j];
1330 1545972 : largestIndex = j;
1331 : }
1332 : }
1333 756697 : largestIndices[i] = largestIndex;
1334 756697 : values[largestIndex] = -1.0f;
1335 : }
1336 :
1337 197412 : return;
1338 : }
1339 :
1340 :
1341 1137542 : static void move_metadata_to_qmetadata(
1342 : const MASA_ENCODER_HANDLE hMasa,
1343 : IVAS_QMETADATA_HANDLE hQMeta )
1344 : {
1345 : int16_t dir, sf, band;
1346 : uint8_t numCodingBands;
1347 : uint8_t numDirections;
1348 : uint8_t numSf;
1349 : MASA_METADATA_HANDLE hMeta;
1350 :
1351 1137542 : numCodingBands = hMasa->config.numCodingBands;
1352 1137542 : numDirections = hMasa->config.numberOfDirections;
1353 1137542 : numSf = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES;
1354 1137542 : hMeta = &( hMasa->masaMetadata );
1355 :
1356 2481958 : for ( dir = 0; dir < numDirections; dir++ )
1357 : {
1358 5359243 : for ( sf = 0; sf < numSf; sf++ )
1359 : {
1360 39124985 : for ( band = 0; band < numCodingBands; band++ )
1361 : {
1362 35110158 : hQMeta->q_direction[dir].band_data[band].azimuth[sf] = hMeta->directional_meta[dir].azimuth[sf][band];
1363 35110158 : hQMeta->q_direction[dir].band_data[band].elevation[sf] = hMeta->directional_meta[dir].elevation[sf][band];
1364 35110158 : hQMeta->q_direction[dir].band_data[band].energy_ratio[sf] = hMeta->directional_meta[dir].energy_ratio[sf][band];
1365 35110158 : hQMeta->q_direction[dir].band_data[band].spherical_index[sf] = hMeta->directional_meta[dir].spherical_index[sf][band];
1366 35110158 : if ( hQMeta->q_direction[dir].coherence_band_data != NULL )
1367 : {
1368 27650494 : hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = (uint8_t) roundf( hMeta->directional_meta[dir].spread_coherence[sf][band] * UINT8_MAX );
1369 : }
1370 : }
1371 : }
1372 : }
1373 :
1374 4530994 : for ( sf = 0; sf < numSf; sf++ )
1375 : {
1376 32308987 : for ( band = 0; band < numCodingBands; band++ )
1377 : {
1378 28915535 : if ( hQMeta->surcoh_band_data != NULL )
1379 : {
1380 21455871 : hQMeta->surcoh_band_data[band].surround_coherence[sf] = (uint8_t) roundf( hMeta->common_meta.surround_coherence[sf][band] * UINT8_MAX );
1381 : }
1382 : }
1383 : }
1384 :
1385 1137542 : if ( numDirections > 1 )
1386 : {
1387 2578237 : for ( band = 0; band < numCodingBands; band++ )
1388 : {
1389 2371363 : hQMeta->twoDirBands[band] = hMasa->data.twoDirBands[band];
1390 : }
1391 206874 : hQMeta->numTwoDirBands = hMasa->config.numTwoDirBands;
1392 : }
1393 :
1394 : /* Copy spread coherence for DCT-based coding */
1395 1137542 : if ( numSf == 1 && hMasa->config.useCoherence )
1396 : {
1397 498477 : for ( dir = 0; dir < numDirections; dir++ )
1398 : {
1399 1134368 : for ( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1400 : {
1401 14557314 : for ( band = 0; band < numCodingBands; band++ )
1402 : {
1403 13706538 : hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[0];
1404 : }
1405 : }
1406 : }
1407 : }
1408 :
1409 1137542 : return;
1410 : }
1411 :
1412 :
1413 : /* This function studies parametric MASA metadata to provide information for codec configuration */
1414 1111657 : static void detect_metadata_composition(
1415 : const MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder data */
1416 : uint8_t *joinedSubframes, /* o : Result of subframe composition */
1417 : uint8_t *coherencePresent, /* o : Result of coherence presence */
1418 : uint8_t *isTwoDir /* o : Result of two direction check */
1419 : )
1420 : {
1421 : MASA_METADATA_FRAME *hMeta;
1422 : int8_t sf, band, dir, numDir;
1423 : int16_t nSubFrames;
1424 1111657 : uint8_t dirValid[2] = { FALSE, FALSE };
1425 1111657 : uint8_t cohPresent = FALSE;
1426 1111657 : uint8_t sfDiffer = FALSE;
1427 : uint8_t sfSimilar;
1428 :
1429 1111657 : hMeta = &( hMasa->masaMetadata );
1430 1111657 : numDir = hMeta->descriptive_meta.numberOfDirections + 1;
1431 :
1432 1111657 : *isTwoDir = FALSE;
1433 :
1434 : /* First check for valid two directions */
1435 1111657 : if ( numDir == 1 )
1436 : {
1437 665685 : dirValid[0] = TRUE;
1438 : }
1439 : else
1440 : {
1441 : /* Default assumption */
1442 445972 : *isTwoDir = TRUE;
1443 :
1444 : /* Check for direct-to-total ratio values */
1445 1337916 : for ( dir = 0; dir < numDir; dir++ )
1446 : {
1447 891944 : sf = 0;
1448 1832218 : while ( !dirValid[dir] && sf < MAX_PARAM_SPATIAL_SUBFRAMES )
1449 : {
1450 940274 : band = 0;
1451 3503842 : while ( !dirValid[dir] && band < MASA_FREQUENCY_BANDS )
1452 : {
1453 2563568 : if ( hMeta->directional_meta[dir].energy_ratio[sf][band] >= MASA_RATIO_THRESHOLD )
1454 : {
1455 876240 : dirValid[dir] = TRUE;
1456 : }
1457 2563568 : band++;
1458 : }
1459 940274 : sf++;
1460 : }
1461 : }
1462 :
1463 445972 : if ( dirValid[1] == FALSE )
1464 : {
1465 : /* This handles also case where both are false. Then we just use first dir metadata. */
1466 5664 : *isTwoDir = FALSE;
1467 : }
1468 440308 : else if ( dirValid[0] == FALSE && dirValid[1] == TRUE )
1469 : {
1470 8116 : *isTwoDir = FALSE;
1471 : /* Copy data to first direction */
1472 40580 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1473 : {
1474 811600 : for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
1475 : {
1476 779136 : hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band];
1477 779136 : hMeta->directional_meta[0].azimuth[sf][band] = hMeta->directional_meta[1].azimuth[sf][band];
1478 779136 : hMeta->directional_meta[0].elevation[sf][band] = hMeta->directional_meta[1].elevation[sf][band];
1479 779136 : hMeta->directional_meta[0].energy_ratio[sf][band] = hMeta->directional_meta[1].energy_ratio[sf][band];
1480 779136 : hMeta->directional_meta[0].spread_coherence[sf][band] = hMeta->directional_meta[1].spread_coherence[sf][band];
1481 : }
1482 : }
1483 : }
1484 :
1485 445972 : if ( *isTwoDir == FALSE )
1486 : {
1487 : /* Further checks will be done with just one direction */
1488 13780 : numDir = 1;
1489 : }
1490 : }
1491 :
1492 : /* Check if data over subframes is identical. Check is done by comparing to first subframe. */
1493 1111657 : sfSimilar = TRUE;
1494 1111657 : sf = 1;
1495 3185967 : while ( ( sfSimilar == TRUE ) && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) )
1496 : {
1497 2074310 : sfSimilar = are_masa_subframes_similar( hMeta, 0, hMeta, sf );
1498 2074310 : sf++;
1499 : }
1500 1111657 : sfDiffer = sfSimilar == TRUE ? FALSE : TRUE;
1501 :
1502 : /* Further checks can be done with just one subframe if they are identical */
1503 1111657 : nSubFrames = sfDiffer == TRUE ? MAX_PARAM_SPATIAL_SUBFRAMES : 1;
1504 :
1505 : /* Check spread coherence */
1506 1111657 : dir = 0;
1507 2239809 : while ( cohPresent == FALSE && dir < numDir )
1508 : {
1509 1128152 : sf = 0;
1510 2430679 : while ( cohPresent == FALSE && sf < nSubFrames )
1511 : {
1512 1302527 : band = 0;
1513 13135144 : while ( cohPresent == FALSE && band < MASA_FREQUENCY_BANDS )
1514 : {
1515 : /* Check coherences for presence of coherence */
1516 11832617 : if ( hMeta->directional_meta[dir].spread_coherence[sf][band] >= MASA_COHERENCE_THRESHOLD )
1517 : {
1518 974671 : cohPresent = TRUE;
1519 : }
1520 11832617 : band++;
1521 : }
1522 1302527 : sf++;
1523 : }
1524 1128152 : dir++;
1525 : }
1526 :
1527 : /* Check surround coherence separately if we do not have already knowledge of coherence */
1528 1111657 : if ( cohPresent == FALSE )
1529 : {
1530 136986 : cohPresent = ivas_masa_surrcoh_signicant( hMeta->common_meta.surround_coherence, hMeta->common_meta.diffuse_to_total_ratio, nSubFrames, MASA_FREQUENCY_BANDS );
1531 : }
1532 :
1533 : /* Set output flags */
1534 1111657 : *joinedSubframes = sfDiffer == TRUE ? FALSE : TRUE;
1535 1111657 : *coherencePresent = cohPresent;
1536 :
1537 1111657 : return;
1538 : }
1539 :
1540 :
1541 : /* Check and compensate energy ratios. This function verifies that energy ratios follow the principle of summing to one.
1542 : * In addition, it implements simple remainder-to-total handling where remainder energy is proportionally added to other
1543 : * ratios. */
1544 1111657 : static void compensate_energy_ratios(
1545 : MASA_ENCODER_HANDLE hMasa )
1546 : {
1547 : int16_t sf, band, dir;
1548 : float ratioSum;
1549 : MASA_METADATA_HANDLE hMeta;
1550 : uint8_t numDirs;
1551 :
1552 1111657 : hMeta = &( hMasa->masaMetadata );
1553 1111657 : numDirs = hMasa->config.numberOfDirections;
1554 :
1555 5558285 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1556 : {
1557 111165700 : for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
1558 : {
1559 : /* Remainder is always set to zero and energy removal is compensated in following steps
1560 : * to other ratios. */
1561 106719072 : hMeta->common_meta.remainder_to_total_ratio[sf][band] = 0.0f;
1562 :
1563 106719072 : ratioSum = 0;
1564 254928576 : for ( dir = 0; dir < numDirs; dir++ )
1565 : {
1566 148209504 : ratioSum += hMeta->directional_meta[dir].energy_ratio[sf][band];
1567 : }
1568 106719072 : ratioSum += hMeta->common_meta.diffuse_to_total_ratio[sf][band];
1569 :
1570 106719072 : if ( ratioSum == 0.0f )
1571 : {
1572 0 : for ( dir = 0; dir < numDirs; dir++ )
1573 : {
1574 0 : hMeta->directional_meta[dir].energy_ratio[sf][band] = 0.0f;
1575 : }
1576 0 : hMeta->common_meta.diffuse_to_total_ratio[sf][band] = 1.0f;
1577 : }
1578 106719072 : else if ( ratioSum != 1.0f )
1579 : {
1580 7971054 : for ( dir = 0; dir < numDirs; dir++ )
1581 : {
1582 4784964 : hMeta->directional_meta[dir].energy_ratio[sf][band] /= ratioSum;
1583 : }
1584 3186090 : hMeta->common_meta.diffuse_to_total_ratio[sf][band] /= ratioSum;
1585 : }
1586 : }
1587 : }
1588 :
1589 1111657 : return;
1590 : }
1591 :
1592 :
1593 : /* If the bit budget is very low, reduce metadata further to either 1 subframe and 5 bands, or 1 band and 4 subframes, based on which works better */
1594 409021 : static void reduce_metadata_further(
1595 : MASA_ENCODER_HANDLE hMasa,
1596 : IVAS_QMETADATA_HANDLE hqmetadata,
1597 : const IVAS_FORMAT ivas_format )
1598 : {
1599 : int16_t sf;
1600 : int16_t band;
1601 : int16_t selectedBand;
1602 : float energy[MAX_PARAM_SPATIAL_SUBFRAMES][LOWBITRATE_NUM_BANDS];
1603 : float totalEnergySum;
1604 : uint8_t numCodingBands;
1605 : uint8_t computeCoherence;
1606 : float onset_filter;
1607 : float bandEnergy;
1608 : uint8_t mergeOverFreqBands;
1609 : float meanRatio;
1610 :
1611 409021 : numCodingBands = hMasa->config.numCodingBands;
1612 409021 : computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
1613 :
1614 : /* Set default values */
1615 409021 : selectedBand = 0;
1616 409021 : mergeOverFreqBands = 0;
1617 :
1618 : /* Get energy for the input data in 4-subframe, 5-band format */
1619 409021 : totalEnergySum = 0.0f;
1620 409021 : if ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) /* Energy data is in 4-subframe, 24-band format */
1621 : {
1622 1588540 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1623 : {
1624 : int16_t brange[2];
1625 : float eneSum;
1626 : int16_t m;
1627 :
1628 7624992 : for ( band = 0; band < numCodingBands; band++ )
1629 : {
1630 6354160 : brange[0] = hMasa->data.band_mapping[band];
1631 6354160 : brange[1] = hMasa->data.band_mapping[band + 1];
1632 :
1633 6354160 : eneSum = 0.0f;
1634 36608592 : for ( m = brange[0]; m < brange[1]; m++ )
1635 : {
1636 30254432 : eneSum += hMasa->data.energy[sf][m];
1637 : }
1638 6354160 : energy[sf][band] = eneSum;
1639 6354160 : totalEnergySum += eneSum;
1640 : }
1641 : }
1642 : }
1643 : else /* Energy data is already in 4-subframe, 5-band format */
1644 : {
1645 456565 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1646 : {
1647 2191512 : for ( band = 0; band < numCodingBands; band++ )
1648 : {
1649 1826260 : energy[sf][band] = hMasa->data.energy[sf][band];
1650 1826260 : totalEnergySum += energy[sf][band];
1651 : }
1652 : }
1653 : }
1654 :
1655 : /* Determine onsets */
1656 409021 : hMasa->data.onset_detector_1 = hMasa->data.onset_detector_1 * LOWBITRATE_ONSET_ALPHA;
1657 409021 : hMasa->data.onset_detector_1 = max( hMasa->data.onset_detector_1, totalEnergySum );
1658 :
1659 409021 : hMasa->data.onset_detector_2 = LOWBITRATE_ONSET_BETA * hMasa->data.onset_detector_2 + ( 1.0f - LOWBITRATE_ONSET_BETA ) * hMasa->data.onset_detector_1;
1660 409021 : hMasa->data.onset_detector_2 = LOWBITRATE_ONSET_GAIN * min( hMasa->data.onset_detector_1, hMasa->data.onset_detector_2 );
1661 :
1662 409021 : onset_filter = min( max( hMasa->data.onset_detector_2 / ( hMasa->data.onset_detector_1 + EPSILON ), 0.0f ), 1.0f );
1663 :
1664 : /* If we have onset, continue checking if we should reduce in frequency instead of time. */
1665 409021 : if ( onset_filter < 0.99f )
1666 : {
1667 : /* Determine one frequency band to use to represent all frequency bands */
1668 375810 : for ( band = numCodingBands - 1; band >= 0; band-- )
1669 : {
1670 : float threshold;
1671 : float bandRatio;
1672 :
1673 369663 : threshold = totalEnergySum / ( MAX_PARAM_SPATIAL_SUBFRAMES * LOWBITRATE_NUM_BANDS ) * 0.5f; /* Average energy multiplied with energy ratio of 0.5f */
1674 369663 : bandRatio = hqmetadata->q_direction[0].band_data[band].energy_ratio[0];
1675 :
1676 369663 : bandEnergy = 0.0f;
1677 1848315 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1678 : {
1679 1478652 : bandEnergy += energy[sf][band];
1680 : }
1681 :
1682 369663 : if ( bandEnergy / MAX_PARAM_SPATIAL_SUBFRAMES * bandRatio > threshold )
1683 : {
1684 90901 : selectedBand = band;
1685 90901 : break;
1686 : }
1687 : }
1688 :
1689 : /* Determine if to merge over frequency instead of time */
1690 97048 : meanRatio = 0.0f;
1691 485240 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1692 : {
1693 2329152 : for ( band = 0; band < numCodingBands; band++ )
1694 : {
1695 1940960 : meanRatio += hqmetadata->q_direction[0].band_data[band].energy_ratio[sf] * energy[sf][band];
1696 : }
1697 : }
1698 97048 : meanRatio /= ( totalEnergySum + EPSILON );
1699 :
1700 : /* If the ratio of the selected band is larger than the average ratio of all bands and if there is an onset, merge over frequency bands.
1701 : * Otherwise, merge over subframes. */
1702 97048 : if ( hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio[0] > meanRatio )
1703 : {
1704 63720 : mergeOverFreqBands = 1;
1705 : }
1706 : else
1707 : {
1708 33328 : mergeOverFreqBands = 0;
1709 : }
1710 : }
1711 : else
1712 : {
1713 311973 : mergeOverFreqBands = 0;
1714 : }
1715 :
1716 : /* Merge values over subframes or frequency bands, depending on which one is less important */
1717 409021 : if ( !mergeOverFreqBands ) /* Merge values over subframes */
1718 : {
1719 : float xSum, ySum, zSum;
1720 : float bandSumEnergy;
1721 : float aziRad, eleRad;
1722 : float x, y, z;
1723 : float veclen;
1724 :
1725 2071806 : for ( band = 0; band < numCodingBands; band++ )
1726 : {
1727 1726505 : xSum = 0.0f;
1728 1726505 : ySum = 0.0f;
1729 1726505 : zSum = 0.0f;
1730 1726505 : bandSumEnergy = 0.0f;
1731 :
1732 8632525 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1733 : {
1734 6906020 : aziRad = hqmetadata->q_direction[0].band_data[band].azimuth[sf] / 180.0f * EVS_PI;
1735 6906020 : eleRad = hqmetadata->q_direction[0].band_data[band].elevation[sf] / 180.0f * EVS_PI;
1736 6906020 : veclen = hqmetadata->q_direction[0].band_data[band].energy_ratio[sf] * energy[sf][band];
1737 :
1738 6906020 : x = cosf( aziRad ) * cosf( eleRad ) * veclen;
1739 6906020 : y = sinf( aziRad ) * cosf( eleRad ) * veclen;
1740 6906020 : z = sinf( eleRad ) * veclen;
1741 :
1742 6906020 : xSum += x;
1743 6906020 : ySum += y;
1744 6906020 : zSum += z;
1745 :
1746 6906020 : bandSumEnergy += energy[sf][band];
1747 : }
1748 :
1749 1726505 : aziRad = atan2f( ySum, xSum );
1750 1726505 : eleRad = atan2f( zSum, sqrtf( xSum * xSum + ySum * ySum ) );
1751 :
1752 1726505 : hqmetadata->q_direction[0].band_data[band].azimuth[0] = aziRad / EVS_PI * 180.0f;
1753 1726505 : hqmetadata->q_direction[0].band_data[band].elevation[0] = eleRad / EVS_PI * 180.0f;
1754 :
1755 : /* Energy ratio is already merged through time */
1756 :
1757 1726505 : if ( computeCoherence && hqmetadata->q_direction[0].coherence_band_data != NULL )
1758 : {
1759 : float spreadCoh;
1760 288995 : float spreadCohSum = 0.0f;
1761 1444975 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1762 : {
1763 1155980 : spreadCoh = (float) hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] / 255.0f;
1764 1155980 : spreadCohSum += spreadCoh * energy[sf][band];
1765 : }
1766 288995 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (uint8_t) roundf( spreadCohSum / ( bandSumEnergy + EPSILON ) * 255.0f );
1767 :
1768 : /* Copy spread coherence to the rest of subframes for the coherence coding algorithm. */
1769 1155980 : for ( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1770 : {
1771 866985 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0];
1772 : }
1773 :
1774 : /* Surround coherence is already merged through time */
1775 : }
1776 : }
1777 :
1778 345301 : hqmetadata->q_direction->cfg.nblocks = 1;
1779 345301 : hMasa->config.joinedSubframes = 1;
1780 : }
1781 : else /* Merge values over frequency bands */
1782 : {
1783 : /* Use the selected frequency band to represent all data */
1784 318600 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1785 : {
1786 254880 : hqmetadata->q_direction[0].band_data[0].azimuth[sf] = hqmetadata->q_direction[0].band_data[selectedBand].azimuth[sf];
1787 254880 : hqmetadata->q_direction[0].band_data[0].elevation[sf] = hqmetadata->q_direction[0].band_data[selectedBand].elevation[sf];
1788 254880 : hqmetadata->q_direction[0].band_data[0].energy_ratio[sf] = hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio[sf];
1789 254880 : if ( hqmetadata->q_direction[0].coherence_band_data != NULL )
1790 : {
1791 66480 : hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[selectedBand].spread_coherence[sf];
1792 : }
1793 254880 : if ( hqmetadata->surcoh_band_data != NULL )
1794 : {
1795 66480 : hqmetadata->surcoh_band_data[0].surround_coherence[sf] = hqmetadata->surcoh_band_data[selectedBand].surround_coherence[sf];
1796 : }
1797 : }
1798 :
1799 : /* Copy coherence to rest of bands for the coherence coding algorithm. */
1800 318600 : for ( band = 1; band < numCodingBands; band++ )
1801 : {
1802 254880 : if ( hqmetadata->q_direction[0].coherence_band_data != NULL )
1803 : {
1804 332400 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1805 : {
1806 265920 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf];
1807 : }
1808 : }
1809 254880 : if ( hqmetadata->q_direction[0].coherence_band_data != NULL )
1810 : {
1811 332400 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1812 : {
1813 265920 : hqmetadata->surcoh_band_data[band].surround_coherence[sf] = hqmetadata->surcoh_band_data[0].surround_coherence[sf];
1814 : }
1815 : }
1816 : }
1817 :
1818 63720 : hqmetadata->q_direction[0].cfg.nbands = 1;
1819 : }
1820 :
1821 409021 : return;
1822 : }
1823 :
1824 :
1825 190840 : static int16_t encode_lfe_to_total_energy_ratio(
1826 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
1827 : BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */
1828 : const int32_t ivas_total_brate /* i : IVAS total bitrate */
1829 : )
1830 : {
1831 : int16_t i;
1832 : float xq;
1833 : int16_t VQLevels;
1834 : float maxLFESubFrameEner;
1835 : float log2LFEaverage;
1836 : float log2LFEratio[4];
1837 : float xqv[4];
1838 : float linearLFEaverage;
1839 : int16_t lfeToTotalEnergyRatioIndices[3];
1840 : int16_t lfeAdaptiveVQBits;
1841 : int16_t lfeBitsWritten;
1842 :
1843 190840 : VQLevels = 0;
1844 190840 : lfeAdaptiveVQBits = 0;
1845 :
1846 : /* Determine maximum amount of LFE energy in any subframe */
1847 190840 : maxLFESubFrameEner = 0.0f;
1848 954200 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
1849 : {
1850 763360 : if ( hMasa->data.lfeToTotalEnergyRatio[i] > maxLFESubFrameEner )
1851 : {
1852 402890 : maxLFESubFrameEner = hMasa->data.lfeToTotalEnergyRatio[i];
1853 : }
1854 : }
1855 :
1856 : /* Set default values for the indices */
1857 763360 : for ( i = 0; i < 3; i++ )
1858 : {
1859 572520 : lfeToTotalEnergyRatioIndices[i] = 0;
1860 : }
1861 :
1862 : /* Check if there is enough energy in any subframe. If not, send only 1 bit (0) and abort. */
1863 : /* If there is enough LFE energy at least in one subframe, quantize it. */
1864 190840 : if ( maxLFESubFrameEner > 0.005f )
1865 : {
1866 : /* Convert energy to log2 domain, and clamp it to reasonable values */
1867 164345 : log2LFEaverage = 0.0f;
1868 821725 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
1869 : {
1870 657380 : log2LFEratio[i] = log2f( max( 0.001f, hMasa->data.lfeToTotalEnergyRatio[i] ) );
1871 657380 : if ( log2LFEratio[i] > 1.0f ) /* Corresponds to linear value 2.0f */
1872 : {
1873 0 : log2LFEratio[i] = 1.0f;
1874 : }
1875 657380 : else if ( log2LFEratio[i] < -9.0f )
1876 : {
1877 25003 : log2LFEratio[i] = -9.0f;
1878 : }
1879 657380 : log2LFEaverage += 0.25f * log2LFEratio[i];
1880 : }
1881 :
1882 164345 : if ( ivas_total_brate == IVAS_13k2 )
1883 : {
1884 : /* Calculate adaptive 1-bit LFE quantizer index */
1885 13039 : linearLFEaverage = exp2f( log2LFEaverage ); /* Convert back to linear domain */
1886 13039 : if ( ( linearLFEaverage > MCMASA_LFE_1BIT_THRES ) && ( linearLFEaverage > ( 0.5f * ( MCMASA_LFE_BETA + hMasa->data.prevq_lfeToTotalEnergyRatio ) + 0.5f * ( MCMASA_LFE_ALPHA * hMasa->data.prevq_lfeToTotalEnergyRatio ) ) ) )
1887 : {
1888 5072 : lfeToTotalEnergyRatioIndices[0] = 1;
1889 5072 : if ( hMasa->data.prevq_lfeIndex == 1 )
1890 : {
1891 2197 : hMasa->data.prevq_lfeToTotalEnergyRatio = hMasa->data.prevq_lfeToTotalEnergyRatio + MCMASA_LFE_THETA * MCMASA_LFE_BETA; /* larger "bump-up" to LFE-to-total energy ratio */
1892 : }
1893 : else
1894 : {
1895 2875 : hMasa->data.prevq_lfeToTotalEnergyRatio = hMasa->data.prevq_lfeToTotalEnergyRatio + MCMASA_LFE_BETA; /* default "bump-up" to LFE-to-total energy ratio */
1896 : }
1897 : }
1898 : else
1899 : {
1900 7967 : hMasa->data.prevq_lfeToTotalEnergyRatio = MCMASA_LFE_ALPHA * hMasa->data.prevq_lfeToTotalEnergyRatio; /* exponential decay */
1901 : }
1902 :
1903 13039 : if ( hMasa->data.prevq_lfeToTotalEnergyRatio > 1.0f )
1904 : {
1905 4 : hMasa->data.prevq_lfeToTotalEnergyRatio = 1.0f;
1906 : }
1907 13039 : hMasa->data.prevq_lfeIndex = lfeToTotalEnergyRatioIndices[0]; /* Update to previous frame's index memories */
1908 : }
1909 : else /* Bitrate >= 16.4 kbps */
1910 : {
1911 : /* Do 1st stage scalar quantization */
1912 151306 : lfeToTotalEnergyRatioIndices[0] = 1;
1913 151306 : lfeToTotalEnergyRatioIndices[1] = usquant( log2LFEaverage, &xq, MCMASA_LFE_QLOW, MCMASA_LFE_DELTA, 8 );
1914 :
1915 151306 : if ( ivas_total_brate >= IVAS_24k4 ) /* Vector quantization is applied if bitrate >= 24.4 kbps */
1916 : {
1917 : /* Remove scalar value from the vector*/
1918 732645 : for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
1919 : {
1920 586116 : log2LFEratio[i] -= xq;
1921 : }
1922 :
1923 : /* Vector quantize residual with energy adaptive bit allocation */
1924 146529 : switch ( lfeToTotalEnergyRatioIndices[1] )
1925 : {
1926 30837 : case 0:
1927 : case 1:
1928 30837 : VQLevels = 0;
1929 30837 : lfeAdaptiveVQBits = 0;
1930 30837 : break;
1931 15327 : case 2:
1932 15327 : VQLevels = 2;
1933 15327 : lfeAdaptiveVQBits = 1;
1934 15327 : break;
1935 19092 : case 3:
1936 19092 : VQLevels = 4;
1937 19092 : lfeAdaptiveVQBits = 2;
1938 19092 : break;
1939 22580 : case 4:
1940 22580 : VQLevels = 8;
1941 22580 : lfeAdaptiveVQBits = 3;
1942 22580 : break;
1943 58693 : default:
1944 58693 : VQLevels = 16;
1945 58693 : lfeAdaptiveVQBits = 4;
1946 : }
1947 :
1948 146529 : if ( VQLevels > 0 )
1949 : {
1950 115692 : lfeToTotalEnergyRatioIndices[2] = vquant( log2LFEratio, 0, xqv, McMASA_LFEGain_vectors, 4, VQLevels );
1951 : }
1952 : }
1953 : }
1954 : }
1955 :
1956 : /* Write first LFE bit */
1957 190840 : lfeBitsWritten = 0;
1958 190840 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[0], 1 );
1959 190840 : lfeBitsWritten += 1;
1960 :
1961 190840 : if ( lfeToTotalEnergyRatioIndices[0] == 1 && ivas_total_brate >= IVAS_16k4 )
1962 : {
1963 : /* If bitrate >= 16.4kbit/s, send 1-bit on/off + 3-bit scalar */
1964 151306 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[1], 3 );
1965 151306 : lfeBitsWritten += 3;
1966 :
1967 : /* If bitrate >= 24.4kbit/s, use adaptive 1 + (3.. 7) bit quantizer */
1968 151306 : if ( ivas_total_brate >= IVAS_24k4 )
1969 : {
1970 : /* Vector quantize residual with energy adaptive bit allocation */
1971 146529 : if ( lfeAdaptiveVQBits > 0 )
1972 : {
1973 115692 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[2], lfeAdaptiveVQBits );
1974 115692 : lfeBitsWritten += lfeAdaptiveVQBits;
1975 : }
1976 : }
1977 : }
1978 :
1979 190840 : return lfeBitsWritten;
1980 : }
1981 :
1982 :
1983 : /*-------------------------------------------------------------------*
1984 : * ivas_masa_enc_reconfigure()
1985 : *
1986 : * Reconfigure IVAS MASA encoder
1987 : *-------------------------------------------------------------------*/
1988 :
1989 700417 : void ivas_masa_enc_reconfigure(
1990 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
1991 : )
1992 : {
1993 : int16_t n, tmp;
1994 : int16_t sce_id, cpe_id;
1995 : int32_t ivas_total_brate;
1996 : int32_t ism_total_brate;
1997 :
1998 700417 : ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
1999 :
2000 700417 : ism_total_brate = 0;
2001 700417 : if ( st_ivas->hEncoderConfig->ivas_format == MASA_ISM_FORMAT && st_ivas->nSCE > 0 && ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) )
2002 : {
2003 0 : for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
2004 : {
2005 0 : ism_total_brate += st_ivas->hSCE[sce_id]->element_brate;
2006 : }
2007 : }
2008 :
2009 700417 : if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate )
2010 : {
2011 18981 : for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
2012 : {
2013 5674 : copy_encoder_config( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 );
2014 5674 : st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport;
2015 5674 : st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
2016 : }
2017 :
2018 20940 : for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
2019 : {
2020 7633 : st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS;
2021 :
2022 : /* prepare bitstream buffers */
2023 22899 : for ( n = 0; n < CPE_CHANNELS; n++ )
2024 : {
2025 15266 : copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 );
2026 15266 : st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
2027 : }
2028 :
2029 7633 : if ( ivas_total_brate - ism_total_brate < MIN_BRATE_MDCT_STEREO )
2030 : {
2031 2305 : st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT;
2032 : }
2033 : else
2034 : {
2035 5328 : st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT;
2036 : }
2037 : }
2038 :
2039 13307 : ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->hEncoderConfig->ivas_format, st_ivas->ism_mode, ism_total_brate );
2040 : }
2041 :
2042 700417 : return;
2043 : }
2044 :
2045 :
2046 : /*-------------------------------------------------------------------*
2047 : * average_masa_metadata()
2048 : *
2049 : * Average MASA metadata frame subframe contents: applies aggregation over time
2050 : *-------------------------------------------------------------------*/
2051 :
2052 142467 : static void average_masa_metadata(
2053 : MASA_METADATA_FRAME *hMeta,
2054 : float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
2055 : const SPHERICAL_GRID_DATA *Sph_Grid16,
2056 : const uint8_t useSphGrid )
2057 : {
2058 : int16_t i, j, k;
2059 : float azi_rad, ele_rad;
2060 : uint8_t numDirections;
2061 :
2062 : /* use the nominal values without data-adaptivity */
2063 142467 : numDirections = hMeta->descriptive_meta.numberOfDirections + 1;
2064 :
2065 : /* azi/ele/nrg into vectors for each sub-frame and band */
2066 332194 : for ( i = 0; i < numDirections; i++ )
2067 : {
2068 4743175 : for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
2069 : {
2070 : float x_sum, y_sum, z_sum, energy_sum, vec_len, spread_coh_sum, surr_coh_sum;
2071 :
2072 4553448 : x_sum = 0.0f;
2073 4553448 : y_sum = 0.0f;
2074 4553448 : z_sum = 0.0f;
2075 4553448 : energy_sum = 0.0f;
2076 4553448 : spread_coh_sum = 0.0f;
2077 4553448 : surr_coh_sum = 0.0f;
2078 22767240 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
2079 : {
2080 18213792 : azi_rad = hMeta->directional_meta[i].azimuth[j][k] / 180.0f * EVS_PI;
2081 18213792 : ele_rad = hMeta->directional_meta[i].elevation[j][k] / 180.0f * EVS_PI;
2082 18213792 : vec_len = hMeta->directional_meta[i].energy_ratio[j][k] * energy[j][k];
2083 :
2084 : /* energy-weighted sum over subframes */
2085 18213792 : x_sum += cosf( azi_rad ) * cosf( ele_rad ) * vec_len;
2086 18213792 : y_sum += sinf( azi_rad ) * cosf( ele_rad ) * vec_len;
2087 18213792 : z_sum += sinf( ele_rad ) * vec_len;
2088 :
2089 18213792 : energy_sum += energy[j][k];
2090 :
2091 18213792 : spread_coh_sum += hMeta->directional_meta[i].spread_coherence[j][k] * energy[j][k];
2092 18213792 : if ( i == 0 )
2093 : {
2094 : /* this is in common metadata and not in each direction */
2095 13676832 : surr_coh_sum += hMeta->common_meta.surround_coherence[j][k] * energy[j][k];
2096 : }
2097 : }
2098 :
2099 : /* the data from the combined sub-frames is written into the first sub-frame band */
2100 4553448 : j = 0;
2101 4553448 : hMeta->directional_meta[i].azimuth[j][k] = atan2f( y_sum, x_sum ) / EVS_PI * 180.0f;
2102 4553448 : hMeta->directional_meta[i].elevation[j][k] = atan2f( z_sum, sqrtf( x_sum * x_sum + y_sum * y_sum ) ) / EVS_PI * 180.0f;
2103 4553448 : if ( useSphGrid == TRUE )
2104 : {
2105 166152 : hMeta->directional_meta[i].spherical_index[j][k] = index_theta_phi_16( &( hMeta->directional_meta[i].elevation[j][k] ),
2106 166152 : &( hMeta->directional_meta[i].azimuth[j][k] ), Sph_Grid16 );
2107 : }
2108 4553448 : vec_len = sqrtf( x_sum * x_sum + y_sum * y_sum + z_sum * z_sum );
2109 4553448 : hMeta->directional_meta[i].energy_ratio[j][k] = vec_len / ( energy_sum + EPSILON );
2110 :
2111 4553448 : hMeta->directional_meta[i].spread_coherence[j][k] = spread_coh_sum / ( energy_sum + EPSILON );
2112 4553448 : if ( i == 0 )
2113 : {
2114 3419208 : hMeta->common_meta.surround_coherence[j][k] = surr_coh_sum / ( energy_sum + EPSILON );
2115 : }
2116 :
2117 : /* copy the same value to all subframes */
2118 18213792 : for ( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
2119 : {
2120 13660344 : hMeta->directional_meta[i].azimuth[j][k] = hMeta->directional_meta[i].azimuth[0][k];
2121 13660344 : hMeta->directional_meta[i].elevation[j][k] = hMeta->directional_meta[i].elevation[0][k];
2122 13660344 : hMeta->directional_meta[i].energy_ratio[j][k] = hMeta->directional_meta[i].energy_ratio[0][k];
2123 13660344 : hMeta->directional_meta[i].spread_coherence[j][k] = hMeta->directional_meta[i].spread_coherence[0][k];
2124 13660344 : if ( i == 0 )
2125 : {
2126 10257624 : hMeta->common_meta.surround_coherence[j][k] = hMeta->common_meta.surround_coherence[0][k];
2127 : }
2128 : }
2129 : }
2130 : }
2131 :
2132 3561675 : for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
2133 : {
2134 17096040 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
2135 : {
2136 13676832 : if ( numDirections == 2 )
2137 : {
2138 4536960 : hMeta->common_meta.diffuse_to_total_ratio[j][k] = max( 0.0f, 1.0f - hMeta->directional_meta[1].energy_ratio[j][k] - hMeta->directional_meta[0].energy_ratio[j][k] );
2139 : }
2140 : else
2141 : {
2142 9139872 : hMeta->common_meta.diffuse_to_total_ratio[j][k] = max( 0.0f, 1.0f - hMeta->directional_meta[0].energy_ratio[j][k] );
2143 : }
2144 13676832 : hMeta->common_meta.remainder_to_total_ratio[j][k] = 0.0f;
2145 : }
2146 : }
2147 :
2148 142467 : return;
2149 : }
2150 :
2151 :
2152 : /*-------------------------------------------------------------------*
2153 : * copy_masa_metadata_subframe()
2154 : *
2155 : * Copy MASA metadata frame subframe contents
2156 : *-------------------------------------------------------------------*/
2157 :
2158 4446628 : static void copy_masa_metadata_subframe(
2159 : const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metdata to be copied */
2160 : const uint8_t sfFrom, /* i : subframe index of the copy source */
2161 : MASA_METADATA_HANDLE hMetaTo, /* o : MASA frame metadata copy destination */
2162 : const uint8_t sfTo /* i : subframe index of the copy target */
2163 : )
2164 : {
2165 : uint8_t dir;
2166 : uint8_t band;
2167 :
2168 : /* directional metadata */
2169 13339884 : for ( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ )
2170 : {
2171 222331400 : for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
2172 : {
2173 213438144 : hMetaTo->directional_meta[dir].spherical_index[sfTo][band] = hMetaFrom->directional_meta[dir].spherical_index[sfFrom][band];
2174 : }
2175 8893256 : mvr2r( hMetaFrom->directional_meta[dir].azimuth[sfFrom], hMetaTo->directional_meta[dir].azimuth[sfTo], MASA_FREQUENCY_BANDS );
2176 8893256 : mvr2r( hMetaFrom->directional_meta[dir].elevation[sfFrom], hMetaTo->directional_meta[dir].elevation[sfTo], MASA_FREQUENCY_BANDS );
2177 8893256 : mvr2r( hMetaFrom->directional_meta[dir].energy_ratio[sfFrom], hMetaTo->directional_meta[dir].energy_ratio[sfTo], MASA_FREQUENCY_BANDS );
2178 8893256 : mvr2r( hMetaFrom->directional_meta[dir].spread_coherence[sfFrom], hMetaTo->directional_meta[dir].spread_coherence[sfTo], MASA_FREQUENCY_BANDS );
2179 : }
2180 :
2181 : /* common metadata */
2182 4446628 : mvr2r( hMetaFrom->common_meta.diffuse_to_total_ratio[sfFrom], hMetaTo->common_meta.diffuse_to_total_ratio[sfTo], MASA_FREQUENCY_BANDS );
2183 4446628 : mvr2r( hMetaFrom->common_meta.surround_coherence[sfFrom], hMetaTo->common_meta.surround_coherence[sfTo], MASA_FREQUENCY_BANDS );
2184 4446628 : mvr2r( hMetaFrom->common_meta.remainder_to_total_ratio[sfFrom], hMetaTo->common_meta.remainder_to_total_ratio[sfTo], MASA_FREQUENCY_BANDS );
2185 :
2186 4446628 : return;
2187 : }
2188 :
2189 :
2190 : /*-------------------------------------------------------------------*
2191 : * copy_masa_metadata()
2192 : *
2193 : * Copy MASA metada frame contents
2194 : *-------------------------------------------------------------------*/
2195 :
2196 1111657 : static void copy_masa_metadata(
2197 : const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metadata to be copied */
2198 : MASA_METADATA_HANDLE hMetaTo /* o : MASA frame metadata copy destination */
2199 : )
2200 : {
2201 : uint8_t sf, byte_idx;
2202 :
2203 : /* descriptive metadata */
2204 10004913 : for ( byte_idx = 0; byte_idx < 8; byte_idx++ )
2205 : {
2206 8893256 : hMetaTo->descriptive_meta.formatDescriptor[byte_idx] = hMetaFrom->descriptive_meta.formatDescriptor[byte_idx];
2207 : }
2208 :
2209 1111657 : hMetaTo->descriptive_meta.numberOfDirections = hMetaFrom->descriptive_meta.numberOfDirections;
2210 1111657 : hMetaTo->descriptive_meta.numberOfChannels = hMetaFrom->descriptive_meta.numberOfChannels;
2211 1111657 : hMetaTo->descriptive_meta.sourceFormat = hMetaFrom->descriptive_meta.sourceFormat;
2212 1111657 : hMetaTo->descriptive_meta.transportDefinition = hMetaFrom->descriptive_meta.transportDefinition;
2213 1111657 : hMetaTo->descriptive_meta.channelAngle = hMetaFrom->descriptive_meta.channelAngle;
2214 1111657 : hMetaTo->descriptive_meta.channelDistance = hMetaFrom->descriptive_meta.channelDistance;
2215 1111657 : hMetaTo->descriptive_meta.channelLayout = hMetaFrom->descriptive_meta.channelLayout;
2216 :
2217 : /* directional and common metadata */
2218 5558285 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2219 : {
2220 4446628 : copy_masa_metadata_subframe( hMetaFrom, sf, hMetaTo, sf );
2221 : }
2222 :
2223 1111657 : return;
2224 : }
2225 :
2226 :
2227 : /*-------------------------------------------------------------------*
2228 : * are_masa_subframes_similar()
2229 : *
2230 : * Compare the similarity of MASA metadata in two sub-frames
2231 : *-------------------------------------------------------------------*/
2232 :
2233 : /* r: similarity decision */
2234 6260718 : static uint8_t are_masa_subframes_similar(
2235 : const MASA_METADATA_HANDLE frame1, /* i : MASA metadata frame 1 */
2236 : const uint8_t sf1_idx, /* i : index of the subframe of frame1 to inspect */
2237 : const MASA_METADATA_HANDLE frame2, /* i : MASA metadata frame 2 */
2238 : const uint8_t sf2_idx /* i : index of the subframe of frame2 to inspect */
2239 : )
2240 : {
2241 : uint8_t num_dir;
2242 : uint8_t dir;
2243 : uint8_t band_idx;
2244 : uint8_t sf_differ;
2245 :
2246 6260718 : num_dir = frame1->descriptive_meta.numberOfDirections;
2247 6260718 : dir = 0;
2248 6260718 : band_idx = 0;
2249 6260718 : sf_differ = FALSE;
2250 :
2251 6260718 : if ( num_dir != frame2->descriptive_meta.numberOfDirections )
2252 : {
2253 51054 : sf_differ = TRUE;
2254 : }
2255 : else
2256 : {
2257 : /* check per-direction metadata */
2258 6209664 : dir = 0;
2259 6209664 : band_idx = 0;
2260 :
2261 13725787 : while ( ( sf_differ == FALSE ) && ( dir <= num_dir ) )
2262 : {
2263 7516123 : band_idx = 0;
2264 112779235 : while ( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
2265 : {
2266 : float azi_dif;
2267 108463203 : azi_dif = fabsf( frame1->directional_meta[dir].azimuth[sf1_idx][band_idx] - frame2->directional_meta[dir].azimuth[sf2_idx][band_idx] );
2268 108463203 : azi_dif = azi_dif > 180.0f ? 360.0f - azi_dif : azi_dif;
2269 :
2270 108463203 : if ( azi_dif > MASA_ANGLE_TOLERANCE )
2271 : {
2272 3005232 : sf_differ = TRUE;
2273 3005232 : break;
2274 : }
2275 :
2276 105457971 : if ( fabsf( frame1->directional_meta[dir].elevation[sf1_idx][band_idx] - frame2->directional_meta[dir].elevation[sf2_idx][band_idx] ) > MASA_ANGLE_TOLERANCE )
2277 : {
2278 111494 : sf_differ = TRUE;
2279 111494 : break;
2280 : }
2281 :
2282 105346477 : if ( fabsf( frame1->directional_meta[dir].energy_ratio[sf1_idx][band_idx] - frame2->directional_meta[dir].energy_ratio[sf2_idx][band_idx] ) > MASA_RATIO_TOLERANCE )
2283 : {
2284 55575 : sf_differ = TRUE;
2285 55575 : break;
2286 : }
2287 :
2288 105290902 : if ( fabsf( frame1->directional_meta[dir].spread_coherence[sf1_idx][band_idx] - frame2->directional_meta[dir].spread_coherence[sf2_idx][band_idx] ) > MASA_COHERENCE_TOLERANCE )
2289 : {
2290 27790 : sf_differ = TRUE;
2291 27790 : break;
2292 : }
2293 :
2294 105263112 : band_idx++;
2295 : }
2296 7516123 : dir++;
2297 : }
2298 :
2299 : /* check the common metadata */
2300 6209664 : while ( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
2301 : {
2302 0 : if ( fabsf( frame1->common_meta.surround_coherence[sf1_idx][band_idx] - frame2->common_meta.surround_coherence[sf2_idx][band_idx] ) > MASA_COHERENCE_TOLERANCE )
2303 : {
2304 0 : sf_differ = TRUE;
2305 0 : break;
2306 : }
2307 :
2308 0 : band_idx++;
2309 : }
2310 : }
2311 :
2312 6260718 : if ( sf_differ )
2313 : {
2314 3251145 : return FALSE;
2315 : }
2316 : else
2317 : {
2318 3009573 : return TRUE;
2319 : }
2320 : }
2321 :
2322 :
2323 : /*-------------------------------------------------------------------*
2324 : * detect_framing_async()
2325 : *
2326 : * Compare the similarity of MASA metadata in two sub-frames
2327 : * Analysis result is stored in hMasa->data.sync_state, and
2328 : * potentially hMasa->masaMetadata is modified
2329 : *-------------------------------------------------------------------*/
2330 :
2331 1111657 : static void detect_framing_async(
2332 : MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
2333 : )
2334 : {
2335 : MASA_METADATA_HANDLE current_meta;
2336 : MASA_METADATA_HANDLE previous_meta;
2337 : MASA_SYNC_HANDLE sync_state;
2338 : MASA_FRAME_MODE frame_mode;
2339 : uint8_t n_sim_start, n_sim_stop, sf_idx;
2340 : uint8_t found_offset;
2341 :
2342 1111657 : current_meta = &( hMasa->masaMetadata ); /* metadata from current frame */
2343 1111657 : sync_state = &( hMasa->data.sync_state ); /* synchronization structure */
2344 1111657 : previous_meta = &( sync_state->previous_metadata );
2345 :
2346 : /* check current frame, how many are similar from the start and from the end */
2347 1111657 : n_sim_start = 1;
2348 2221924 : for ( sf_idx = n_sim_start; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
2349 : {
2350 1954457 : if ( are_masa_subframes_similar( current_meta, 0, current_meta, sf_idx ) == TRUE )
2351 : {
2352 1110267 : n_sim_start = sf_idx + 1;
2353 : }
2354 : else
2355 : {
2356 844190 : break;
2357 : }
2358 : }
2359 :
2360 : /* number of similar sub-frames starting from the end of the frame */
2361 1111657 : if ( n_sim_start == MAX_PARAM_SPATIAL_SUBFRAMES ) /* shortcut */
2362 : {
2363 267467 : n_sim_stop = n_sim_start;
2364 : }
2365 : else
2366 : {
2367 844190 : n_sim_stop = 1;
2368 1167858 : for ( sf_idx = 2; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
2369 : {
2370 : /* we need to check only the two middle sub-frames, as all being the same would have taken the shortcut above */
2371 1144897 : if ( are_masa_subframes_similar( current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1, current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - sf_idx ) == TRUE )
2372 : {
2373 323668 : n_sim_stop = sf_idx;
2374 : }
2375 : else
2376 : {
2377 821229 : break;
2378 : }
2379 : }
2380 : }
2381 :
2382 1111657 : frame_mode = MASA_FRAME_4SF; /* default mode: 4sf */
2383 1111657 : if ( sync_state->prev_offset > MAX_PARAM_SPATIAL_SUBFRAMES - 2 )
2384 : {
2385 : /* earlier offset was large => reset the offset */
2386 31804 : found_offset = 0;
2387 : }
2388 : else
2389 : {
2390 : /* keep previous offset unless something else is found. alternatively, we could reset always */
2391 1079853 : found_offset = sync_state->prev_offset;
2392 : }
2393 :
2394 1111657 : if ( ( n_sim_start == MAX_PARAM_SPATIAL_SUBFRAMES ) && ( n_sim_stop == MAX_PARAM_SPATIAL_SUBFRAMES ) )
2395 : {
2396 : /* full frame consists of similar sub-frames */
2397 267467 : frame_mode = MASA_FRAME_1SF;
2398 267467 : if ( ( sync_state->prev_sim_stop != 0 ) && ( are_masa_subframes_similar( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ) == TRUE ) )
2399 : {
2400 : /* > 4 sub-frames of similar data */
2401 69377 : if ( sync_state->prev_sim_stop < 3 )
2402 : {
2403 : /* can nicely align the framing with the earlier data and a small offset */
2404 5671 : found_offset = sync_state->prev_sim_stop;
2405 : }
2406 : else
2407 : {
2408 : /* too many similar sub-frames to determine the offset accurately => keep earlier value */
2409 63706 : found_offset = sync_state->prev_offset;
2410 : }
2411 : }
2412 : else
2413 : {
2414 : /* earlier window was different => reset the offset */
2415 198090 : found_offset = 0;
2416 : }
2417 : }
2418 844190 : else if ( n_sim_stop == 3 )
2419 : {
2420 : /* first sub-frame different that the rest 3
2421 : => make a risky guess that the future sf would be the same too and we're in an offset case */
2422 22961 : frame_mode = MASA_FRAME_1SF;
2423 22961 : found_offset = 3;
2424 : }
2425 821229 : else if ( ( sync_state->prev_sim_stop > 0 ) && ( are_masa_subframes_similar( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ) == TRUE ) )
2426 : {
2427 : /* seeing data similar to past */
2428 165296 : if ( ( n_sim_start > 1 ) && ( n_sim_start + sync_state->prev_sim_stop >= MAX_PARAM_SPATIAL_SUBFRAMES ) )
2429 : {
2430 : /* with the past, would have at least one long frame similar subframes */
2431 87884 : frame_mode = MASA_FRAME_1SF;
2432 :
2433 87884 : if ( sync_state->prev_offset == 0 )
2434 : {
2435 5466 : found_offset = min( 2, sync_state->prev_sim_stop );
2436 : }
2437 : else
2438 : {
2439 82418 : found_offset = sync_state->prev_offset;
2440 : }
2441 : }
2442 : }
2443 :
2444 : /* keep the original contents of the frame, but then perform interpolation later */
2445 : /* just copy current frame to storage */
2446 1111657 : copy_masa_metadata( current_meta, previous_meta );
2447 :
2448 1111657 : sync_state->prev_sim_stop = n_sim_stop;
2449 1111657 : sync_state->prev_offset = found_offset;
2450 1111657 : sync_state->frame_mode = frame_mode;
2451 :
2452 1111657 : return;
2453 : }
2454 :
2455 :
2456 : /*-------------------------------------------------------------------*
2457 : * masa_metadata_direction_alignment()
2458 : *
2459 : * In 2dir MASA metadata, determine the ordering of the directional
2460 : * fields such that the azi/ele change across time is minimized.
2461 : *-------------------------------------------------------------------*/
2462 :
2463 1111657 : static void masa_metadata_direction_alignment(
2464 : MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */
2465 : )
2466 : {
2467 : uint8_t band, n_dirs;
2468 : MASA_DIR_ALIGN_HANDLE hAlignState;
2469 : MASA_METADATA_HANDLE hMeta;
2470 :
2471 1111657 : hAlignState = &( hMasa->data.dir_align_state );
2472 1111657 : hMeta = &( hMasa->masaMetadata );
2473 :
2474 1111657 : n_dirs = hMeta->descriptive_meta.numberOfDirections + 1; /* 1-based */
2475 27791425 : for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
2476 : {
2477 : uint8_t sf;
2478 : float diff_swap, diff_no_swap;
2479 :
2480 : /* trade 2*(cos+sin) against storing the values between frames */
2481 : float prev_ele_dir1_sin, prev_ele_dir2_sin;
2482 : float prev_ele_dir1_cos, prev_ele_dir2_cos;
2483 :
2484 26679768 : prev_ele_dir1_sin = sinf( hAlignState->previous_ele_dir1[band] );
2485 26679768 : prev_ele_dir2_sin = sinf( hAlignState->previous_ele_dir2[band] );
2486 :
2487 26679768 : prev_ele_dir1_cos = cosf( hAlignState->previous_ele_dir1[band] );
2488 26679768 : prev_ele_dir2_cos = cosf( hAlignState->previous_ele_dir2[band] );
2489 :
2490 133398840 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2491 : {
2492 : float azi_rad1, ele_rad1;
2493 : float azi_rad2, ele_rad2;
2494 : float cos_ele1, cos_ele2;
2495 : float sin_ele1, sin_ele2;
2496 :
2497 106719072 : azi_rad1 = hMeta->directional_meta[0].azimuth[sf][band] * PI_OVER_180;
2498 106719072 : ele_rad1 = hMeta->directional_meta[0].elevation[sf][band] * PI_OVER_180;
2499 :
2500 106719072 : if ( n_dirs > 1 )
2501 : {
2502 42813312 : azi_rad2 = hMeta->directional_meta[1].azimuth[sf][band] * PI_OVER_180;
2503 42813312 : ele_rad2 = hMeta->directional_meta[1].elevation[sf][band] * PI_OVER_180;
2504 :
2505 : /* quick checks to detect constant data and earlier flip */
2506 42813312 : if ( fabsf( azi_rad1 - hAlignState->previous_azi_dir1[band] ) < EPSILON &&
2507 11181739 : fabsf( azi_rad2 - hAlignState->previous_azi_dir2[band] ) < EPSILON &&
2508 10551575 : fabsf( ele_rad1 - hAlignState->previous_ele_dir1[band] ) < EPSILON &&
2509 10550315 : fabsf( ele_rad2 - hAlignState->previous_ele_dir2[band] ) < EPSILON )
2510 : {
2511 10550309 : diff_swap = 1.0f;
2512 10550309 : diff_no_swap = 0.0f;
2513 : /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
2514 10550309 : sin_ele1 = prev_ele_dir1_sin;
2515 10550309 : sin_ele2 = prev_ele_dir2_sin;
2516 10550309 : cos_ele1 = prev_ele_dir1_cos;
2517 10550309 : cos_ele2 = prev_ele_dir2_cos;
2518 : }
2519 32263003 : else if ( fabsf( azi_rad1 - hAlignState->previous_azi_dir2[band] ) < EPSILON &&
2520 8582747 : fabsf( azi_rad2 - hAlignState->previous_azi_dir1[band] ) < EPSILON &&
2521 8551810 : fabsf( ele_rad1 - hAlignState->previous_ele_dir2[band] ) < EPSILON &&
2522 8551587 : fabsf( ele_rad2 - hAlignState->previous_ele_dir1[band] ) < EPSILON )
2523 : {
2524 8551554 : diff_swap = 0.0f;
2525 8551554 : diff_no_swap = 1.0f;
2526 : /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
2527 8551554 : sin_ele1 = prev_ele_dir2_sin;
2528 8551554 : sin_ele2 = prev_ele_dir1_sin;
2529 8551554 : cos_ele1 = prev_ele_dir2_cos;
2530 8551554 : cos_ele2 = prev_ele_dir1_cos;
2531 : }
2532 : else
2533 : {
2534 : /* angular distance of the two vectors */
2535 : /* pre-compute values for re-use */
2536 23711449 : sin_ele1 = sinf( ele_rad1 );
2537 23711449 : sin_ele2 = sinf( ele_rad2 );
2538 :
2539 23711449 : cos_ele1 = cosf( ele_rad1 );
2540 23711449 : cos_ele2 = cosf( ele_rad2 );
2541 :
2542 23711449 : diff_no_swap = acosf( cos_ele1 * prev_ele_dir1_cos * cosf( azi_rad1 - hAlignState->previous_azi_dir1[band] ) + sin_ele1 * prev_ele_dir1_sin ) +
2543 23711449 : acosf( cos_ele2 * prev_ele_dir2_cos * cosf( azi_rad2 - hAlignState->previous_azi_dir2[band] ) + sin_ele2 * prev_ele_dir2_sin );
2544 :
2545 23711449 : diff_swap = acosf( cos_ele1 * prev_ele_dir2_cos * cosf( azi_rad1 - hAlignState->previous_azi_dir2[band] ) + sin_ele1 * prev_ele_dir2_sin ) +
2546 23711449 : acosf( cos_ele2 * prev_ele_dir1_cos * cosf( azi_rad2 - hAlignState->previous_azi_dir1[band] ) + sin_ele2 * prev_ele_dir1_sin );
2547 : }
2548 : }
2549 : else
2550 : {
2551 : /* 1dir */
2552 63905760 : sin_ele1 = sinf( ele_rad1 );
2553 63905760 : cos_ele1 = cosf( ele_rad1 );
2554 :
2555 63905760 : azi_rad2 = 0.0f;
2556 63905760 : ele_rad2 = 0.0f;
2557 :
2558 63905760 : sin_ele2 = 0.0f; /* sin(0) */
2559 63905760 : cos_ele2 = 1.0f; /* cos(0) */
2560 :
2561 63905760 : diff_swap = 1.0f;
2562 63905760 : diff_no_swap = 0.0f;
2563 : }
2564 :
2565 106719072 : if ( n_dirs > 1 && diff_no_swap > diff_swap )
2566 17077310 : {
2567 : /* swap the metadata of the two directions in this TF-tile */
2568 : float tmp_val;
2569 : uint16_t tmp_int_val;
2570 17077310 : tmp_val = hMeta->directional_meta[0].azimuth[sf][band];
2571 17077310 : hMeta->directional_meta[0].azimuth[sf][band] = hMeta->directional_meta[1].azimuth[sf][band];
2572 17077310 : hMeta->directional_meta[1].azimuth[sf][band] = tmp_val;
2573 :
2574 17077310 : tmp_val = hMeta->directional_meta[0].elevation[sf][band];
2575 17077310 : hMeta->directional_meta[0].elevation[sf][band] = hMeta->directional_meta[1].elevation[sf][band];
2576 17077310 : hMeta->directional_meta[1].elevation[sf][band] = tmp_val;
2577 17077310 : tmp_int_val = hMeta->directional_meta[0].spherical_index[sf][band];
2578 17077310 : hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band];
2579 17077310 : hMeta->directional_meta[1].spherical_index[sf][band] = tmp_int_val;
2580 17077310 : tmp_val = hMeta->directional_meta[0].energy_ratio[sf][band];
2581 17077310 : hMeta->directional_meta[0].energy_ratio[sf][band] = hMeta->directional_meta[1].energy_ratio[sf][band];
2582 17077310 : hMeta->directional_meta[1].energy_ratio[sf][band] = tmp_val;
2583 :
2584 17077310 : tmp_val = hMeta->directional_meta[0].spread_coherence[sf][band];
2585 17077310 : hMeta->directional_meta[0].spread_coherence[sf][band] = hMeta->directional_meta[1].spread_coherence[sf][band];
2586 17077310 : hMeta->directional_meta[1].spread_coherence[sf][band] = tmp_val;
2587 :
2588 17077310 : hAlignState->previous_azi_dir1[band] = azi_rad2;
2589 17077310 : hAlignState->previous_ele_dir1[band] = ele_rad2;
2590 :
2591 17077310 : hAlignState->previous_azi_dir2[band] = azi_rad1;
2592 17077310 : hAlignState->previous_ele_dir2[band] = ele_rad1;
2593 :
2594 17077310 : prev_ele_dir1_cos = cos_ele2;
2595 17077310 : prev_ele_dir1_sin = sin_ele2;
2596 :
2597 17077310 : prev_ele_dir2_cos = cos_ele1;
2598 17077310 : prev_ele_dir2_sin = sin_ele1;
2599 : }
2600 : else
2601 : {
2602 89641762 : hAlignState->previous_azi_dir1[band] = azi_rad1;
2603 89641762 : hAlignState->previous_ele_dir1[band] = ele_rad1;
2604 :
2605 89641762 : hAlignState->previous_azi_dir2[band] = azi_rad2;
2606 89641762 : hAlignState->previous_ele_dir2[band] = ele_rad2;
2607 :
2608 89641762 : prev_ele_dir1_cos = cos_ele1;
2609 89641762 : prev_ele_dir1_sin = sin_ele1;
2610 :
2611 89641762 : prev_ele_dir2_cos = cos_ele2;
2612 89641762 : prev_ele_dir2_sin = sin_ele2;
2613 : }
2614 : } /* sf */
2615 : } /* band */
2616 :
2617 1111657 : return;
2618 : }
2619 :
2620 :
2621 : /*-------------------------------------------------------------------*
2622 : * ivas_merge_masa_metadata()
2623 : *
2624 : *
2625 : *-------------------------------------------------------------------*/
2626 :
2627 178138 : void ivas_merge_masa_metadata(
2628 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */
2629 : OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i : ISM-object metadata to be merged with the MASA metadata */
2630 : )
2631 : {
2632 : int16_t sf, band;
2633 : uint8_t numCodingBands;
2634 : uint8_t numDirections;
2635 : uint8_t numSf;
2636 : MASA_METADATA_HANDLE hMeta;
2637 : float energyTimesRatioISM;
2638 : float energyTimesRatioMASA[2];
2639 : float total_diff_nrg;
2640 : float eneBand;
2641 : float energyMerged[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
2642 178138 : OMASA_ENCODER_ENERGY_HANDLE hOmasaEnergy = hMasa->data.hOmasaData->hOmasaEnergy;
2643 :
2644 178138 : numCodingBands = hMasa->config.numCodingBands;
2645 178138 : numDirections = hMasa->config.numberOfDirections;
2646 178138 : numSf = hMasa->config.joinedSubframes == TRUE ? 1 : MAX_PARAM_SPATIAL_SUBFRAMES;
2647 178138 : hMeta = &( hMasa->masaMetadata );
2648 :
2649 890690 : for ( sf = 0; sf < numSf; sf++ )
2650 : {
2651 17654000 : for ( band = 0; band < numCodingBands; band++ )
2652 : {
2653 : int16_t merge_dest;
2654 : float dir_sum;
2655 : uint8_t band_n_dirs;
2656 16941448 : if ( numDirections == 1 || ( numDirections == 2 && hMasa->data.twoDirBands[band] == 0 ) )
2657 : {
2658 16941448 : band_n_dirs = 1;
2659 : }
2660 : else
2661 : {
2662 0 : band_n_dirs = 2;
2663 : }
2664 :
2665 : /* Compute energies */
2666 16941448 : eneBand = hMasa->data.energy[sf][band];
2667 16941448 : energyMerged[sf][band] = eneBand + hOmasaEnergy->energy_ism[sf][band];
2668 :
2669 : /* Compute weights */
2670 16941448 : energyTimesRatioMASA[0] = eneBand * hMeta->directional_meta[0].energy_ratio[sf][band];
2671 16941448 : if ( band_n_dirs == 2 )
2672 : {
2673 0 : energyTimesRatioMASA[1] = eneBand * hMeta->directional_meta[1].energy_ratio[sf][band];
2674 : }
2675 : else
2676 : {
2677 16941448 : energyTimesRatioMASA[1] = 0.0f;
2678 : }
2679 :
2680 : /* target is original MASA diffuseness */
2681 16941448 : total_diff_nrg = eneBand * hMeta->common_meta.diffuse_to_total_ratio[sf][band];
2682 :
2683 : /* criterion is mean of ISM ratio and new ratio */
2684 16941448 : energyTimesRatioISM = ( hOMasaMeta->directional_meta[0].energy_ratio[sf][band] + ( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] ) ) ) / 2.0f * hMasa->data.hOmasaData->hOmasaEnergy->energy_ism[sf][band];
2685 :
2686 : /* Determine combined metadata based on the weights */
2687 16941448 : merge_dest = -1;
2688 16941448 : if ( ( band_n_dirs == 1 && energyTimesRatioMASA[0] < energyTimesRatioISM ) ||
2689 0 : ( band_n_dirs == 2 && energyTimesRatioMASA[0] < energyTimesRatioMASA[1] && energyTimesRatioMASA[0] < energyTimesRatioISM ) )
2690 : {
2691 : /* 1dir and ISM the most energetic, or 2dir and ISM the more energetic than MASA1 */
2692 8021015 : merge_dest = 0;
2693 : }
2694 8920433 : else if ( band_n_dirs == 2 && energyTimesRatioMASA[1] <= energyTimesRatioMASA[0] && energyTimesRatioMASA[1] < energyTimesRatioISM )
2695 : {
2696 : /* 2dir and ISM the most energetic and MASA2 the least energetic */
2697 0 : merge_dest = 1;
2698 : }
2699 :
2700 16941448 : if ( merge_dest >= 0 ) /* replace one MASA with ISM */
2701 : {
2702 8021015 : hMeta->directional_meta[merge_dest].azimuth[sf][band] = hOMasaMeta->directional_meta[0].azimuth[sf][band];
2703 8021015 : hMeta->directional_meta[merge_dest].elevation[sf][band] = hOMasaMeta->directional_meta[0].elevation[sf][band];
2704 :
2705 : /* limit with the earlier direct-energy ratio */
2706 8021015 : dir_sum = 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] ); /* new dir ratio */
2707 8021015 : hMeta->directional_meta[merge_dest].energy_ratio[sf][band] = min( dir_sum, hOMasaMeta->directional_meta[0].energy_ratio[sf][band] ); /* clip with original ISM dir */
2708 8021015 : hMeta->common_meta.diffuse_to_total_ratio[sf][band] = 1.0f - hMeta->directional_meta[merge_dest].energy_ratio[sf][band];
2709 :
2710 8021015 : if ( hMasa->config.useCoherence )
2711 : {
2712 0 : hMeta->directional_meta[merge_dest].spread_coherence[sf][band] = hOMasaMeta->directional_meta[0].spread_coherence[sf][band];
2713 0 : hMeta->common_meta.surround_coherence[sf][band] = hOMasaMeta->common_meta.surround_coherence[sf][band];
2714 : }
2715 :
2716 : /* recompute direct energy ratios to match the diffuse ratio */
2717 : float direct_quota, direct_scaler;
2718 8021015 : direct_quota = 1.0f - hMeta->common_meta.diffuse_to_total_ratio[sf][band];
2719 8021015 : if ( band_n_dirs == 1 )
2720 : {
2721 8021015 : hMeta->directional_meta[0].energy_ratio[sf][band] = direct_quota;
2722 : }
2723 : else
2724 : {
2725 0 : dir_sum = hMeta->directional_meta[0].energy_ratio[sf][band] + hMeta->directional_meta[1].energy_ratio[sf][band];
2726 0 : direct_scaler = direct_quota / ( EPSILON + dir_sum );
2727 0 : hMeta->directional_meta[0].energy_ratio[sf][band] *= direct_scaler;
2728 0 : hMeta->directional_meta[1].energy_ratio[sf][band] *= direct_scaler;
2729 : }
2730 : }
2731 : }
2732 : }
2733 :
2734 890690 : for ( sf = 0; sf < numSf; sf++ )
2735 : {
2736 17654000 : for ( band = 0; band < numCodingBands; band++ )
2737 : {
2738 16941448 : hMasa->data.energy[sf][band] = energyMerged[sf][band];
2739 : }
2740 : }
2741 :
2742 178138 : return;
2743 : }
2744 :
2745 :
2746 1239089 : static void quantize_ratio_ism_vector(
2747 : const float *ratio_ism,
2748 : int16_t *idx,
2749 : const int16_t nchan_ism,
2750 : const float masa_to_total_energy_ratio,
2751 : const int16_t idx_sep_object )
2752 : {
2753 : int16_t i, j, best_i, best_i2;
2754 : float dist, div, tmp, dist2, best_dist;
2755 : int16_t part_idx_sum, max_sum_idx;
2756 : float ratio_ism_loc[MAX_NUM_OBJECTS];
2757 : int16_t no_ism_loc;
2758 :
2759 1239089 : max_sum_idx = ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1;
2760 :
2761 1239089 : if ( idx_sep_object > -1 )
2762 : {
2763 1239089 : if ( ratio_ism[idx_sep_object] < 1.0f / (float) ( max_sum_idx ) )
2764 : {
2765 : /* take it out from quantize function */
2766 854589 : mvr2r( ratio_ism, ratio_ism_loc, idx_sep_object );
2767 854589 : mvr2r( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 );
2768 854589 : no_ism_loc = nchan_ism - 1;
2769 : }
2770 : else
2771 : {
2772 384500 : no_ism_loc = nchan_ism;
2773 384500 : mvr2r( ratio_ism, ratio_ism_loc, nchan_ism );
2774 : }
2775 : }
2776 : else
2777 : {
2778 0 : no_ism_loc = nchan_ism;
2779 0 : mvr2r( ratio_ism, ratio_ism_loc, nchan_ism );
2780 : }
2781 :
2782 1239089 : if ( nchan_ism > 1 )
2783 : {
2784 1239089 : if ( masa_to_total_energy_ratio >= MASA2TOTAL_THR )
2785 : {
2786 512223 : distribute_evenly_ism( idx, max_sum_idx, nchan_ism );
2787 : }
2788 : else
2789 : {
2790 726866 : if ( no_ism_loc > 1 )
2791 : {
2792 :
2793 705910 : dist = 0.0f;
2794 705910 : div = 1.0f / (float) ( max_sum_idx );
2795 :
2796 705910 : part_idx_sum = 0;
2797 :
2798 2668612 : for ( i = 0; i < no_ism_loc; i++ )
2799 : {
2800 1962702 : idx[i] = (int16_t) ( ( ratio_ism_loc[i] ) * ( max_sum_idx ) );
2801 1962702 : part_idx_sum += idx[i];
2802 :
2803 1962702 : tmp = ( ratio_ism_loc[i] - ( idx[i] * div ) );
2804 1962702 : dist += ( tmp * tmp );
2805 : }
2806 :
2807 705910 : best_dist = dist;
2808 705910 : best_i2 = -1;
2809 1154315 : while ( part_idx_sum < max_sum_idx )
2810 : {
2811 448405 : best_i = -1;
2812 : /* check which index to increase by 1 for a possible improvement */
2813 :
2814 1735647 : for ( i = 0; i < no_ism_loc; i++ )
2815 : {
2816 1287242 : idx[i]++;
2817 1287242 : dist2 = 0.0f;
2818 :
2819 5086702 : for ( j = 0; j < no_ism_loc; j++ )
2820 : {
2821 3799460 : tmp = ( ratio_ism_loc[i] - ( idx[i] * div ) );
2822 3799460 : dist2 += ( tmp * tmp );
2823 : }
2824 :
2825 1287242 : if ( dist2 < best_dist )
2826 : {
2827 378523 : best_i2 = best_i;
2828 378523 : best_i = i;
2829 378523 : best_dist = dist2;
2830 : }
2831 1287242 : idx[i]--;
2832 : }
2833 448405 : if ( best_i > -1 )
2834 : {
2835 366228 : idx[best_i]++;
2836 366228 : part_idx_sum++;
2837 : }
2838 : else
2839 : {
2840 82177 : if ( best_i2 > -1 )
2841 : {
2842 10464 : idx[best_i2]++;
2843 10464 : part_idx_sum++;
2844 : }
2845 : else
2846 : {
2847 71713 : idx[no_ism_loc - 1] += max_sum_idx - part_idx_sum;
2848 71713 : part_idx_sum = max_sum_idx;
2849 : }
2850 : }
2851 : }
2852 705910 : assert( sum_s( idx, no_ism_loc ) == max_sum_idx );
2853 : }
2854 : else
2855 : {
2856 20956 : idx[0] = max_sum_idx;
2857 : }
2858 :
2859 726866 : if ( no_ism_loc < nchan_ism )
2860 : {
2861 : /* insert back the ratio of the separated object */
2862 1553910 : for ( i = nchan_ism - 1; i > idx_sep_object; i-- )
2863 : {
2864 897982 : idx[i] = idx[i - 1];
2865 : }
2866 655928 : idx[idx_sep_object] = 0;
2867 : }
2868 : }
2869 : }
2870 : else
2871 : {
2872 0 : idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f );
2873 : }
2874 :
2875 1239089 : return;
2876 : }
2877 :
2878 :
2879 106906 : static int16_t index_slice_enum(
2880 : const int16_t *ratio_ism_idx,
2881 : const int16_t nchan_ism )
2882 : {
2883 : int16_t i;
2884 : int16_t x, index;
2885 : int16_t base;
2886 :
2887 106906 : if ( nchan_ism == 2 )
2888 : {
2889 7703 : index = ratio_ism_idx[0];
2890 : }
2891 : else
2892 : {
2893 99203 : x = ratio_ism_idx[nchan_ism - 2];
2894 99203 : base = 10;
2895 274449 : for ( i = nchan_ism - 3; i >= 0; i-- )
2896 : {
2897 175246 : x += ratio_ism_idx[i] * base;
2898 175246 : base *= 10;
2899 : }
2900 :
2901 99203 : index = 0;
2902 99203 : i = 0;
2903 11544110 : while ( i <= x )
2904 : {
2905 11444907 : if ( valid_ratio_index( i, 7, nchan_ism - 1 ) )
2906 : {
2907 3213638 : index++;
2908 : }
2909 11444907 : i++;
2910 : }
2911 99203 : index--;
2912 : }
2913 :
2914 106906 : return index;
2915 : }
2916 :
2917 :
2918 1686755 : static void transform_difference_index(
2919 : const int16_t *diff_idx,
2920 : int16_t *idx,
2921 : const int16_t len )
2922 : {
2923 : int16_t i;
2924 5391742 : for ( i = 0; i < len; i++ )
2925 : {
2926 3704987 : if ( diff_idx[i] <= 0 )
2927 : {
2928 3358264 : idx[i] = -2 * diff_idx[i];
2929 : }
2930 : else
2931 : {
2932 346723 : idx[i] = 2 * diff_idx[i] - 1;
2933 : }
2934 : }
2935 :
2936 1686755 : return;
2937 : }
2938 :
2939 :
2940 619530 : static void transform_index_and_GR_encode(
2941 : int16_t *diff_idx, /* i : differenc eindex to encode */
2942 : const int16_t len, /* i : input length */
2943 : const int16_t GR_order, /* i : GR order */
2944 : BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */
2945 : )
2946 : {
2947 : int16_t i;
2948 : int16_t idx[IVAS_MAX_NUM_OBJECTS];
2949 :
2950 : /* transform difference index into positive */
2951 619530 : transform_difference_index( diff_idx, idx, len );
2952 :
2953 : /* GR encoding */
2954 1991054 : for ( i = 0; i < len; i++ )
2955 : {
2956 1371524 : ivas_qmetadata_encode_extended_gr( hMetaData, idx[i], 100, GR_order );
2957 : }
2958 :
2959 619530 : return;
2960 : }
2961 :
2962 :
2963 82794 : static int16_t try_differential(
2964 : const int16_t numCodingBands,
2965 : const float *masa_to_total_energy_ratio,
2966 : int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
2967 : const int16_t nchan_ism,
2968 : const int16_t bits_index,
2969 : int16_t *p_b_signif )
2970 : {
2971 : int16_t b, i;
2972 : int16_t nbits0;
2973 : int16_t b_signif;
2974 : int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS];
2975 : int16_t diff_idx[MAX_NUM_OBJECTS];
2976 :
2977 82794 : b_signif = 0;
2978 305556 : while ( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR ) )
2979 : {
2980 222762 : b_signif++;
2981 : }
2982 :
2983 82794 : nbits0 = 0;
2984 :
2985 82794 : if ( b_signif < numCodingBands )
2986 : {
2987 53170 : nbits0 = bits_index;
2988 53170 : mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
2989 :
2990 372836 : for ( b = b_signif + 1; b < numCodingBands; b++ )
2991 : {
2992 319666 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
2993 : {
2994 279276 : v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
2995 279276 : mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
2996 :
2997 : /* transform difference index into positive */
2998 279276 : transform_difference_index( diff_idx, diff_idx, nchan_ism - 1 );
2999 :
3000 : /* GR encoding */
3001 988330 : for ( i = 0; i < nchan_ism - 1; i++ )
3002 : {
3003 709054 : nbits0 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 0 );
3004 : }
3005 : }
3006 : }
3007 : }
3008 82794 : *p_b_signif = b_signif;
3009 :
3010 82794 : return nbits0;
3011 : }
3012 :
3013 :
3014 39486 : static void differential_coding_first_subframe(
3015 : BSTR_ENC_HANDLE hMetaData,
3016 : const float *masa_to_total_energy_ratio,
3017 : const int16_t b_signif,
3018 : int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
3019 : const int16_t nchan_ism,
3020 : const int16_t numCodingBands,
3021 : const int16_t bits_index )
3022 : {
3023 : int16_t index, b;
3024 : int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS];
3025 : int16_t diff_idx[MAX_NUM_OBJECTS];
3026 :
3027 : /* differential encoding*/
3028 39486 : push_next_indice( hMetaData, 0, 1 );
3029 :
3030 39486 : if ( b_signif < numCodingBands )
3031 : {
3032 39486 : index = index_slice_enum( ratio_ism_idx[b_signif], nchan_ism );
3033 39486 : push_next_indice( hMetaData, index, bits_index );
3034 :
3035 39486 : mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
3036 :
3037 296466 : for ( b = b_signif + 1; b < numCodingBands; b++ )
3038 : {
3039 256980 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3040 : {
3041 225540 : v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
3042 225540 : mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
3043 :
3044 : /* transform difference index into positive */
3045 225540 : transform_index_and_GR_encode( diff_idx, nchan_ism - 1, 0, hMetaData );
3046 : }
3047 : }
3048 : }
3049 :
3050 39486 : return;
3051 : }
3052 :
3053 :
3054 13684 : static void independent_coding_ratio_ism_idx(
3055 : int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i : ISM ratios */
3056 : const float *masa_to_total_energy_ratio, /* i : MASA to total ratios */
3057 : const int16_t nchan_ism, /* i : number of objects */
3058 : const int16_t numCodingBands, /* i : number of subbands */
3059 : const int16_t bits_index, /* i : number of bits per index */
3060 : BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */
3061 : )
3062 : {
3063 : int16_t b, index;
3064 :
3065 92504 : for ( b = 0; b < numCodingBands; b++ )
3066 : {
3067 78820 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3068 : {
3069 67420 : index = index_slice_enum( ratio_ism_idx[b], nchan_ism );
3070 67420 : push_next_indice( hMetaData, index, bits_index );
3071 : }
3072 : }
3073 :
3074 13684 : return;
3075 : }
3076 :
3077 :
3078 775842 : static void remove_sep_obj(
3079 : int16_t *diff_idx, /* i/o: array of difference of indexes */
3080 : const int16_t nchan_ism, /* i : number of objects */
3081 : const int16_t idx_sep_obj /* i : index of separated object, to be taken out of array */
3082 : )
3083 : {
3084 : int16_t i;
3085 :
3086 2431089 : for ( i = idx_sep_obj; i < nchan_ism - 1; i++ )
3087 : {
3088 1655247 : diff_idx[i] = diff_idx[i + 1];
3089 : }
3090 :
3091 775842 : return;
3092 : }
3093 :
3094 :
3095 787949 : static void estimate_bits_subband_ism_ratio(
3096 : const int16_t *ratio_ism_idx,
3097 : const int16_t *ratio_ism_idx_ref, /* ( i/o ) */
3098 : const int16_t nchan_ism,
3099 : const int16_t shift_one,
3100 : const int16_t idx_sep_obj,
3101 : int16_t *p_nbits0,
3102 : int16_t *p_nbits1 )
3103 : {
3104 : int16_t diff_idx[MAX_NUM_OBJECTS];
3105 : int16_t nbits0, nbits1;
3106 : int16_t i;
3107 :
3108 787949 : nbits0 = 0;
3109 787949 : nbits1 = 0;
3110 :
3111 : /* take difference with respect to previous subframe */
3112 787949 : v_sub_s( ratio_ism_idx, ratio_ism_idx_ref, diff_idx, nchan_ism );
3113 :
3114 787949 : if ( shift_one )
3115 : {
3116 517228 : remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj );
3117 : }
3118 :
3119 : /* transform difference index into positive */
3120 787949 : transform_difference_index( diff_idx, diff_idx, nchan_ism - 1 - shift_one );
3121 :
3122 : /* GR encoding */
3123 2412358 : for ( i = 0; i < nchan_ism - 1 - shift_one; i++ )
3124 : {
3125 1624409 : nbits0 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 0 );
3126 1624409 : nbits1 += ivas_qmetadata_encode_extended_gr_length( diff_idx[i], 100, 1 );
3127 : }
3128 :
3129 787949 : *p_nbits0 = nbits0;
3130 787949 : *p_nbits1 = nbits1;
3131 :
3132 787949 : return;
3133 : }
3134 :
3135 :
3136 212589 : static int16_t encode_ratio_ism_subframe(
3137 : int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
3138 : const int16_t nchan_ism,
3139 : const uint8_t numCodingBands,
3140 : const int16_t sf,
3141 : int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
3142 : BSTR_ENC_HANDLE hMetaData,
3143 : const float *masa_to_total_energy_ratio,
3144 : const int16_t shift_one,
3145 : const int16_t idx_separated_obj )
3146 : {
3147 : int16_t b, b_signif;
3148 : int16_t diff_idx[MAX_NUM_OBJECTS];
3149 : int16_t nbits, nbits0, nbits1, GR_order, GR_order_sb;
3150 : int16_t differential_subframe;
3151 : int16_t ratio_ism_idx_ref[MAX_NUM_OBJECTS];
3152 : int16_t bits_index;
3153 : int16_t nbits00, nbits11;
3154 : int16_t idx_sep_obj_local;
3155 : #ifdef DEBUGGING
3156 : int16_t bits_pos0;
3157 : #endif
3158 :
3159 212589 : idx_sep_obj_local = idx_separated_obj;
3160 212589 : if ( idx_separated_obj > -1 )
3161 : {
3162 212589 : if ( idx_separated_obj == nchan_ism - 1 )
3163 : {
3164 73603 : idx_sep_obj_local = 0;
3165 : }
3166 : }
3167 212589 : nbits = 0;
3168 212589 : nbits0 = 0;
3169 212589 : nbits1 = 0;
3170 :
3171 : #ifdef DEBUGGING
3172 : bits_pos0 = hMetaData->nb_bits_tot;
3173 : #endif
3174 212589 : differential_subframe = 1; /* the differences are taken with respect to previous subframe */
3175 :
3176 : /* first subframe */
3177 212589 : bits_index = 0;
3178 212589 : if ( sf == 0 )
3179 : {
3180 82794 : bits_index = bits_index_ism_ratio( nchan_ism );
3181 :
3182 82794 : nbits = 0;
3183 678392 : for ( b = 0; b < numCodingBands; b++ )
3184 : {
3185 595598 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3186 : {
3187 332446 : nbits += bits_index;
3188 : }
3189 : }
3190 :
3191 82794 : nbits0 = try_differential( numCodingBands, masa_to_total_energy_ratio, ratio_ism_idx, nchan_ism, bits_index, &b_signif );
3192 :
3193 82794 : if ( nbits <= nbits0 && nbits > 0 )
3194 : {
3195 : /* independent encoding */
3196 13684 : push_next_indice( hMetaData, 1, 1 );
3197 13684 : independent_coding_ratio_ism_idx( ratio_ism_idx, masa_to_total_energy_ratio, nchan_ism, numCodingBands, bits_index, hMetaData );
3198 13684 : nbits = nbits + 1;
3199 : }
3200 : else
3201 : {
3202 69110 : if ( nbits > 0 )
3203 : {
3204 39486 : differential_coding_first_subframe( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index );
3205 39486 : nbits = nbits0 + 1;
3206 : }
3207 : }
3208 :
3209 : #ifdef DEBUGGING
3210 : assert( nbits == ( hMetaData->nb_bits_tot - bits_pos0 ) );
3211 : #endif
3212 : }
3213 : else
3214 : {
3215 : /* not first subframe */
3216 129795 : if ( shift_one == 1 && nchan_ism == 2 )
3217 : {
3218 435 : nbits = 0;
3219 : }
3220 : else
3221 : {
3222 129360 : nbits0 = 0;
3223 129360 : nbits1 = 0;
3224 :
3225 772416 : for ( b = 0; b < numCodingBands; b++ )
3226 : {
3227 643056 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3228 : {
3229 393990 : estimate_bits_subband_ism_ratio( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
3230 393990 : nbits0 += nbits00;
3231 393990 : nbits1 += nbits11;
3232 : }
3233 : }
3234 129360 : if ( nbits0 < nbits1 )
3235 : {
3236 77053 : GR_order = 0;
3237 77053 : nbits = nbits0;
3238 : }
3239 : else
3240 : {
3241 52307 : GR_order = 1;
3242 52307 : nbits = nbits1;
3243 : }
3244 :
3245 129360 : if ( numCodingBands > 1 )
3246 : {
3247 : /* try the difference from subband to subband; first subband is compared to previous subframe first subband*/
3248 : /* take difference with respect to previous subframe only for first subband */
3249 128424 : nbits0 = 0;
3250 128424 : nbits1 = 0;
3251 128424 : b_signif = 0;
3252 333844 : while ( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR ) )
3253 : {
3254 205420 : b_signif++;
3255 : }
3256 :
3257 128424 : if ( b_signif < numCodingBands )
3258 : {
3259 90269 : estimate_bits_subband_ism_ratio( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], nchan_ism, shift_one, idx_sep_obj_local, &nbits0, &nbits1 );
3260 :
3261 90269 : mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
3262 :
3263 436700 : for ( b = b_signif + 1; b < numCodingBands; b++ )
3264 : {
3265 346431 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3266 : {
3267 303690 : estimate_bits_subband_ism_ratio( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
3268 303690 : nbits0 += nbits00;
3269 303690 : nbits1 += nbits11;
3270 303690 : mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
3271 : }
3272 : }
3273 :
3274 90269 : if ( nbits0 < nbits1 )
3275 : {
3276 57601 : GR_order_sb = 0;
3277 : }
3278 : else
3279 : {
3280 32668 : GR_order_sb = 1;
3281 32668 : nbits0 = nbits1;
3282 : }
3283 :
3284 90269 : if ( nbits0 < nbits )
3285 : {
3286 10985 : differential_subframe = 0;
3287 10985 : nbits = nbits0;
3288 10985 : GR_order = GR_order_sb;
3289 : }
3290 :
3291 90269 : if ( nbits > 0 )
3292 : {
3293 : /* write prediction type */
3294 90269 : push_next_indice( hMetaData, differential_subframe, 1 );
3295 : /* write GR order */
3296 90269 : push_next_indice( hMetaData, GR_order, 1 );
3297 90269 : nbits++; /* for the prediction type */
3298 90269 : nbits++; /* for GR_order */
3299 :
3300 : /* write data */
3301 90269 : if ( differential_subframe )
3302 : {
3303 475704 : for ( b = 0; b < numCodingBands; b++ )
3304 : {
3305 396420 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3306 : {
3307 : /* take difference with respect to previous subframe */
3308 348536 : v_sub_s( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], diff_idx, nchan_ism );
3309 :
3310 348536 : if ( shift_one )
3311 : {
3312 245682 : remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local );
3313 : }
3314 :
3315 348536 : transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData );
3316 : }
3317 : }
3318 : }
3319 : else
3320 : {
3321 10985 : v_sub_s( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], diff_idx, nchan_ism );
3322 :
3323 10985 : if ( shift_one )
3324 : {
3325 2675 : remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local );
3326 : }
3327 :
3328 10985 : transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData );
3329 :
3330 10985 : mvs2s( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism - shift_one );
3331 :
3332 53427 : for ( b = b_signif + 1; b < numCodingBands; b++ )
3333 : {
3334 : /* take difference with respect to previous subband */
3335 42442 : if ( masa_to_total_energy_ratio[b] < MASA2TOTAL_THR )
3336 : {
3337 34438 : v_sub_s( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
3338 :
3339 34438 : if ( shift_one )
3340 : {
3341 10257 : remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local );
3342 : }
3343 :
3344 34438 : transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData );
3345 :
3346 34438 : mvs2s( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism - shift_one );
3347 : }
3348 : }
3349 : }
3350 : }
3351 : }
3352 : }
3353 : else
3354 : {
3355 : /* only differential wrt previous subframe is possible */
3356 : /* write the differential to subframe case and no bit to signal the difference type */
3357 :
3358 936 : if ( nbits > 0 )
3359 : {
3360 : /* write GR order */
3361 31 : push_next_indice( hMetaData, GR_order, 1 );
3362 31 : nbits++; /* for GR_order */
3363 : /* write data */
3364 : /* only one subband */
3365 31 : if ( masa_to_total_energy_ratio[0] < MASA2TOTAL_THR )
3366 : {
3367 : /* take difference with respect to previous subframe */
3368 31 : v_sub_s( ratio_ism_idx[0], ratio_ism_idx_prev_sf[0], diff_idx, nchan_ism );
3369 :
3370 31 : if ( shift_one )
3371 : {
3372 0 : remove_sep_obj( diff_idx, nchan_ism, idx_sep_obj_local );
3373 : }
3374 :
3375 31 : transform_index_and_GR_encode( diff_idx, nchan_ism - 1 - shift_one, GR_order, hMetaData );
3376 : }
3377 : }
3378 : }
3379 :
3380 : #ifdef DEBUGGING
3381 : assert( nbits == ( hMetaData->nb_bits_tot - bits_pos0 ) );
3382 : #endif
3383 : }
3384 : }
3385 :
3386 212589 : return nbits;
3387 : }
3388 :
3389 :
3390 82794 : static void ivas_encode_masaism_metadata(
3391 : MASA_ENCODER_HANDLE hMasa,
3392 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
3393 : BSTR_ENC_HANDLE hMetaData, /* i/o: metadata bitstream handle */
3394 : ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */
3395 : const int16_t nchan_ism, /* i : number of ISM channels */
3396 : const int16_t low_bitrate_mode, /* i : is low bitrate more? 1/0 */
3397 : const int16_t omasa_nbands,
3398 : const int16_t omasa_nblocks,
3399 : const int16_t idx_separated_object,
3400 : const int16_t ism_imp )
3401 : {
3402 : int16_t sf, band;
3403 : uint8_t numCodingBands;
3404 : uint8_t numSf;
3405 : int16_t brange[2];
3406 : float eneBand;
3407 : int16_t bin;
3408 : int16_t obj;
3409 : int16_t bits_ism[MAX_NUM_OBJECTS];
3410 : uint16_t idx_sph;
3411 : float theta_q, phi_q;
3412 : uint16_t index_theta, index_phi;
3413 : float ratio_ism[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
3414 : int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
3415 : float step;
3416 : int16_t inv_step;
3417 : float energy_ism, energy_ism_ind[MAX_NUM_OBJECTS];
3418 : int16_t tmp, rotate;
3419 : int16_t n_ism_tmp, i;
3420 82794 : OMASA_ENCODER_DATA_HANDLE hOmasaData = hMasa->data.hOmasaData;
3421 82794 : OMASA_ENCODER_ENERGY_HANDLE hOmasaEnergy = hOmasaData->hOmasaEnergy;
3422 : int16_t nbands_work;
3423 :
3424 : /* use the values from hQMetaData */
3425 82794 : numCodingBands = (uint8_t) hQMetaData->q_direction->cfg.nbands;
3426 82794 : numSf = (int8_t) hQMetaData->q_direction->cfg.nblocks;
3427 82794 : nbands_work = min( numCodingBands, omasa_nbands );
3428 82794 : if ( numCodingBands == 1 )
3429 : {
3430 2285 : for ( sf = 0; sf < numSf; sf++ )
3431 : {
3432 1828 : if ( sum_f( hOmasaEnergy->energy_ism[sf], omasa_nbands ) == 0.0f )
3433 : {
3434 856 : hOmasaData->masa_to_total_energy_ratio[sf][0] = 1.0f;
3435 : }
3436 : else
3437 : {
3438 972 : brange[0] = hMasa->data.band_mapping[0];
3439 972 : brange[1] = hMasa->data.band_mapping[omasa_nbands];
3440 972 : eneBand = 0.0f;
3441 24120 : for ( bin = brange[0]; bin < brange[1]; bin++ )
3442 : {
3443 23148 : eneBand += hMasa->data.energy[sf][bin];
3444 : }
3445 :
3446 972 : energy_ism = 0.0f;
3447 2916 : for ( obj = 0; obj < nchan_ism; obj++ )
3448 : {
3449 1944 : energy_ism_ind[obj] = 0.0f;
3450 : }
3451 :
3452 5832 : for ( band = 0; band < omasa_nbands; band++ )
3453 : {
3454 4860 : energy_ism += hOmasaEnergy->energy_ism[sf][band];
3455 14580 : for ( obj = 0; obj < nchan_ism; obj++ )
3456 : {
3457 9720 : energy_ism_ind[obj] += hOmasaEnergy->energy_ism[sf][band] * hOmasaEnergy->energy_ratio_ism[sf][band][obj];
3458 : }
3459 : }
3460 :
3461 2916 : for ( obj = 0; obj < nchan_ism; obj++ )
3462 : {
3463 1944 : hOmasaEnergy->energy_ratio_ism[sf][0][obj] = energy_ism_ind[obj] / energy_ism;
3464 : }
3465 972 : hOmasaData->masa_to_total_energy_ratio[sf][0] = eneBand / ( eneBand + energy_ism + EPSILON );
3466 : }
3467 : }
3468 : }
3469 82337 : else if ( numSf == 1 )
3470 : {
3471 420630 : for ( band = 0; band < nbands_work; band++ )
3472 : {
3473 381101 : energy_ism = 0.0f; /* ISM energy for current subband */
3474 1648911 : for ( obj = 0; obj < nchan_ism; obj++ )
3475 : {
3476 1267810 : energy_ism_ind[obj] = 0.0f;
3477 : }
3478 874867 : for ( sf = 0; sf < omasa_nblocks; sf++ )
3479 : {
3480 493766 : energy_ism += hOmasaEnergy->energy_ism[sf][band];
3481 1986906 : for ( obj = 0; obj < nchan_ism; obj++ )
3482 : {
3483 1493140 : energy_ism_ind[obj] += hOmasaEnergy->energy_ism[sf][band] * hOmasaEnergy->energy_ratio_ism[sf][band][obj];
3484 : }
3485 : }
3486 :
3487 381101 : if ( energy_ism == 0.0f )
3488 : {
3489 106595 : hOmasaData->masa_to_total_energy_ratio[0][band] = 1.0f;
3490 : }
3491 : else
3492 : {
3493 1208850 : for ( obj = 0; obj < nchan_ism; obj++ )
3494 : {
3495 934344 : hOmasaEnergy->energy_ratio_ism[0][band][obj] = energy_ism_ind[obj] / energy_ism;
3496 : }
3497 274506 : brange[0] = hMasa->data.band_mapping[band];
3498 274506 : brange[1] = hMasa->data.band_mapping[band + 1];
3499 :
3500 274506 : eneBand = 0.0f;
3501 614787 : for ( sf = 0; sf < omasa_nblocks; sf++ )
3502 : {
3503 1305490 : for ( bin = brange[0]; bin < brange[1]; bin++ )
3504 : {
3505 965209 : eneBand += hMasa->data.energy[sf][bin];
3506 : }
3507 : }
3508 274506 : hOmasaData->masa_to_total_energy_ratio[0][band] = eneBand / ( eneBand + energy_ism + EPSILON );
3509 : }
3510 : }
3511 39529 : for ( band = nbands_work; band < numCodingBands; band++ )
3512 : {
3513 0 : hOmasaData->masa_to_total_energy_ratio[0][band] = 1.0f;
3514 :
3515 0 : for ( obj = 0; obj < nchan_ism; obj++ )
3516 : {
3517 0 : hOmasaEnergy->energy_ratio_ism[0][band][obj] = hOmasaEnergy->energy_ratio_ism[0][nbands_work - 1][obj];
3518 : }
3519 : }
3520 : }
3521 : else
3522 : {
3523 214040 : for ( sf = 0; sf < numSf; sf++ )
3524 : {
3525 1027392 : for ( band = 0; band < nbands_work; band++ )
3526 : {
3527 856160 : if ( hOmasaEnergy->energy_ism[sf][band] == 0.0f )
3528 : {
3529 191300 : hOmasaData->masa_to_total_energy_ratio[sf][band] = 1.0f;
3530 : }
3531 : else
3532 : {
3533 664860 : brange[0] = hMasa->data.band_mapping[band];
3534 664860 : brange[1] = hMasa->data.band_mapping[band + 1];
3535 :
3536 664860 : eneBand = 0.0f;
3537 3823912 : for ( bin = brange[0]; bin < brange[1]; bin++ )
3538 : {
3539 3159052 : eneBand += hMasa->data.energy[sf][bin];
3540 : }
3541 664860 : hOmasaData->masa_to_total_energy_ratio[sf][band] = eneBand / ( eneBand + hOmasaEnergy->energy_ism[sf][band] + EPSILON );
3542 : }
3543 : }
3544 171232 : for ( band = nbands_work; band < numCodingBands; band++ )
3545 : {
3546 0 : hOmasaData->masa_to_total_energy_ratio[sf][band] = 1.0f;
3547 :
3548 0 : for ( obj = 0; obj < nchan_ism; obj++ )
3549 : {
3550 0 : hOmasaEnergy->energy_ratio_ism[sf][band][obj] = hOmasaEnergy->energy_ratio_ism[sf][nbands_work - 1][obj];
3551 : }
3552 : }
3553 : }
3554 : }
3555 82794 : ivas_omasa_encode_masa_to_total( hOmasaData->masa_to_total_energy_ratio, hMetaData, low_bitrate_mode, numCodingBands, numSf );
3556 :
3557 : /* quantize ism_ratios */
3558 82794 : if ( nchan_ism > 1 )
3559 : {
3560 82794 : inv_step = ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 );
3561 82794 : step = 1.0f / inv_step;
3562 :
3563 82794 : rotate = 0;
3564 82794 : n_ism_tmp = 0;
3565 :
3566 295383 : for ( sf = 0; sf < numSf; sf++ )
3567 : {
3568 1451678 : for ( band = 0; band < numCodingBands; band++ )
3569 : {
3570 5649395 : for ( obj = 0; obj < nchan_ism; obj++ )
3571 : {
3572 4410306 : assert( ( hOmasaEnergy->energy_ratio_ism[sf][band][obj] >= 0 ) && ( hOmasaEnergy->energy_ratio_ism[sf][band][obj] <= 1 ) );
3573 4410306 : ratio_ism[band][obj] = hOmasaEnergy->energy_ratio_ism[sf][band][obj];
3574 : }
3575 :
3576 : /* Quantize ISM ratios */
3577 1239089 : quantize_ratio_ism_vector( ratio_ism[band], ratio_ism_idx[band], nchan_ism, hOmasaData->masa_to_total_energy_ratio[sf][band], idx_separated_object );
3578 1239089 : if ( n_ism_tmp == numCodingBands && ratio_ism_idx[band][idx_separated_object] != 0 && hOmasaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR )
3579 : {
3580 978 : i = 0;
3581 6921 : while ( ratio_ism_idx[band][idx_separated_object] > 0 )
3582 : {
3583 5943 : if ( i != idx_separated_object )
3584 : {
3585 4030 : ratio_ism_idx[band][i]++;
3586 4030 : ratio_ism_idx[band][idx_separated_object]--;
3587 : }
3588 5943 : i++;
3589 5943 : if ( i == nchan_ism )
3590 : {
3591 1269 : i = 0;
3592 : }
3593 : }
3594 : }
3595 :
3596 : /* reconstructed values */
3597 1239089 : reconstruct_ism_ratios( ratio_ism_idx[band], nchan_ism, step, hOmasaEnergy->q_energy_ratio_ism[sf][band] );
3598 : }
3599 :
3600 212589 : if ( ( nchan_ism > 2 ) && ( idx_separated_object == nchan_ism - 1 ) )
3601 : {
3602 : /* rotate components */
3603 66204 : rotate = 1;
3604 468148 : for ( band = 0; band < numCodingBands; band++ )
3605 : {
3606 401944 : if ( hOmasaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR )
3607 : {
3608 203741 : tmp = ratio_ism_idx[band][nchan_ism - 1];
3609 203741 : ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
3610 203741 : ratio_ism_idx[band][0] = tmp;
3611 203741 : if ( sf == 0 && tmp == 0 )
3612 : {
3613 74042 : n_ism_tmp += 1;
3614 : }
3615 :
3616 203741 : if ( n_ism_tmp == numCodingBands )
3617 : {
3618 75846 : assert( tmp == 0 );
3619 : }
3620 : }
3621 : }
3622 : }
3623 : else
3624 : {
3625 146385 : if ( idx_separated_object > -1 )
3626 : {
3627 983530 : for ( band = 0; band < numCodingBands; band++ )
3628 : {
3629 837145 : if ( hOmasaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR )
3630 : {
3631 523125 : if ( ratio_ism_idx[band][idx_separated_object] == 0 && sf == 0 )
3632 : {
3633 212974 : n_ism_tmp++;
3634 : }
3635 : }
3636 : }
3637 : }
3638 : }
3639 :
3640 : /* encode data for current subframe */
3641 212589 : if ( sf > 0 && n_ism_tmp == numCodingBands )
3642 : {
3643 53565 : encode_ratio_ism_subframe( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio[sf], 1, idx_separated_object );
3644 : }
3645 : else
3646 : {
3647 159024 : encode_ratio_ism_subframe( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio[sf], 0, idx_separated_object );
3648 : }
3649 :
3650 : /* calculate quantized ISM ratios */
3651 : /* save previous subframe indexes */
3652 1451678 : for ( band = 0; band < numCodingBands; band++ )
3653 : {
3654 1239089 : mvs2s( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], nchan_ism );
3655 : }
3656 :
3657 212589 : if ( rotate )
3658 : {
3659 468148 : for ( band = 0; band < numCodingBands; band++ )
3660 : {
3661 401944 : if ( hOmasaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR )
3662 : {
3663 203741 : tmp = ratio_ism_idx[band][nchan_ism - 1];
3664 203741 : ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
3665 203741 : ratio_ism_idx[band][0] = tmp;
3666 : }
3667 : }
3668 : }
3669 : }
3670 : }
3671 :
3672 82794 : calculate_nbits_meta( nchan_ism, hOmasaEnergy->q_energy_ratio_ism, hOmasaData->masa_to_total_energy_ratio, numSf, numCodingBands, bits_ism, idx_separated_object, ism_imp );
3673 :
3674 : /* quantize directions */
3675 361842 : for ( obj = 0; obj < nchan_ism; obj++ )
3676 : {
3677 279048 : if ( bits_ism[obj] < 8 )
3678 : {
3679 : /* check is same as previous */
3680 141123 : if ( ( fabs( hIsmMeta[obj]->elevation - hIsmMeta[obj]->q_elevation_old ) < 0.01f ) && ( fabs( hIsmMeta[obj]->azimuth - hIsmMeta[obj]->q_azimuth_old ) < 0.01f ) )
3681 : {
3682 13568 : push_next_indice( hMetaData, 1, 1 );
3683 : /* the old stays the same */
3684 : }
3685 : else
3686 : {
3687 127555 : push_next_indice( hMetaData, 0, 1 );
3688 127555 : idx_sph = quantize_direction( hIsmMeta[obj]->elevation, hIsmMeta[obj]->azimuth, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
3689 127555 : push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
3690 127555 : hIsmMeta[obj]->q_elevation_old = hIsmMeta[obj]->elevation;
3691 127555 : hIsmMeta[obj]->q_azimuth_old = hIsmMeta[obj]->azimuth;
3692 : }
3693 : }
3694 : else
3695 : {
3696 137925 : idx_sph = quantize_direction( hIsmMeta[obj]->elevation, hIsmMeta[obj]->azimuth, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
3697 137925 : push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
3698 137925 : hIsmMeta[obj]->q_elevation_old = hIsmMeta[obj]->elevation;
3699 137925 : hIsmMeta[obj]->q_azimuth_old = hIsmMeta[obj]->azimuth;
3700 : }
3701 : }
3702 :
3703 82794 : return;
3704 : }
3705 :
3706 :
3707 : /*-------------------------------------------------------------------*
3708 : * ivas_merge_masa_transports()
3709 : *
3710 : * Merge MASA transport channels
3711 : *-------------------------------------------------------------------*/
3712 :
3713 260932 : void ivas_merge_masa_transports(
3714 : float data_in_f1[][L_FRAME48k],
3715 : float *data_in_f2[],
3716 : float *data_out_f[],
3717 : const int16_t input_frame,
3718 : const int16_t num_transport_channels )
3719 : {
3720 : int16_t i, j;
3721 :
3722 782796 : for ( i = 0; i < num_transport_channels; i++ )
3723 : {
3724 474854024 : for ( j = 0; j < input_frame; j++ )
3725 : {
3726 474332160 : data_out_f[i][j] = data_in_f1[i][j] + data_in_f2[i][j];
3727 : }
3728 : }
3729 :
3730 260932 : return;
3731 : }
|