Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include <math.h>
35 : #include "options.h"
36 : #include "ivas_cnst.h"
37 : #include "ivas_rom_com.h"
38 : #include "ivas_stat_enc.h"
39 : #include "wmc_auto.h"
40 : #include "prot_fx.h"
41 : #include "prot_fx_enc.h"
42 : #include "ivas_prot_fx.h"
43 :
44 :
45 : /*-----------------------------------------------------------------------*
46 : * Local function prototypes
47 : *-----------------------------------------------------------------------*/
48 :
49 : static void combine_freqbands_and_subframes_fx( MASA_ENCODER_HANDLE hMasa );
50 :
51 : static void find_n_largest_fx( const Word32 *input_fx, Word16 exp_input, Word16 *largestIndices, const Word16 numElements, const Word16 numLargest );
52 :
53 : static void move_metadata_to_qmetadata_fx( const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta );
54 :
55 : static void detect_metadata_composition_fx(
56 : const MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder data */
57 : UWord8 *joinedSubframes, /* o : Result of subframe composition */
58 : UWord8 *coherencePresent, /* o : Result of coherence presence */
59 : UWord8 *isTwoDir /* o : Result of two direction check */
60 : );
61 :
62 : static void compensate_energy_ratios_fx( MASA_ENCODER_HANDLE hMasa );
63 :
64 : static Word16 encode_lfe_to_total_energy_ratio_fx( MASA_ENCODER_HANDLE hMasa, BSTR_ENC_HANDLE hMetaData, const Word32 ivas_total_brate );
65 :
66 : static void ivas_encode_masaism_metadata_fx( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMetaData, BSTR_ENC_HANDLE hMetaData, ISM_METADATA_HANDLE hIsmMeta[], const Word16 nchan_ism, const Word16 low_bitrate_mode, const Word16 omasa_nbands, const Word16 omasa_nblocks, const Word16 idx_separated_object, const Word16 ism_imp );
67 :
68 : static void reduce_metadata_further_fx( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format );
69 :
70 : static void average_masa_metadata_fx(
71 : MASA_METADATA_FRAME *hMeta,
72 : Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
73 : Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
74 : const SPHERICAL_GRID_DATA *Sph_Grid16,
75 : const UWord8 useSphGrid );
76 :
77 : static void copy_masa_metadata_subframe_fx(
78 : const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metdata to be copied */
79 : const UWord8 sfFrom, /* i : subframe index of the copy source */
80 : MASA_METADATA_HANDLE hMetaTo, /* o : MASA frame metadata copy destination */
81 : const UWord8 sfTo /* i : subframe index of the copy target */
82 : );
83 :
84 : static void copy_masa_metadata_fx( const MASA_METADATA_HANDLE hMetaFrom, MASA_METADATA_HANDLE hMetaTo );
85 :
86 : static UWord8 are_masa_subframes_similar_fx(
87 : const MASA_METADATA_HANDLE frame1, /* i : MASA metadata frame 1 */
88 : const UWord8 sf1_idx, /* i : index of the subframe of frame1 to inspect */
89 : const MASA_METADATA_HANDLE frame2, /* i : MASA metadata frame 2 */
90 : const UWord8 sf2_idx /* i : index of the subframe of frame2 to inspect */
91 : );
92 :
93 : static void detect_framing_async_fx(
94 : MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
95 : );
96 :
97 : static void masa_metadata_direction_alignment_fx( MASA_ENCODER_HANDLE hMasa );
98 :
99 :
100 : /*-----------------------------------------------------------------------*
101 : * Local constants
102 : *-----------------------------------------------------------------------*/
103 :
104 : #define LOWBITRATE_ONSET_ALPHA 0.2f /* Onset values are for processing in frames */
105 : #define LOWBITRATE_ONSET_BETA 0.92f
106 : #define LOWBITRATE_ONSET_GAIN 1.4f
107 : #define LOWBITRATE_ONSET_ALPHA_Q31 429496730 /* Onset values are for processing in frames */
108 : #define LOWBITRATE_ONSET_BETA_Q31 1975684956
109 : #define LOWBITRATE_ONSET_GAIN_Q30 1503238554
110 : #define LOWBITRATE_NUM_BANDS 5
111 :
112 :
113 : /*-----------------------------------------------------------------------*
114 : * ivas_masa_enc_open()
115 : *
116 : * open and initialize MASA encoder
117 : *-----------------------------------------------------------------------*/
118 :
119 416 : ivas_error ivas_masa_enc_open_fx(
120 : Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */
121 : )
122 : {
123 : Word16 i;
124 : MASA_ENCODER_HANDLE hMasa;
125 : ENCODER_CONFIG_HANDLE hEncoderConfig;
126 : ivas_error error;
127 : Word32 ism_total_brate;
128 :
129 416 : error = IVAS_ERR_OK;
130 416 : move32();
131 :
132 416 : IF( ( hMasa = (MASA_ENCODER_HANDLE) malloc( sizeof( MASA_ENCODER ) ) ) == NULL )
133 : {
134 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
135 : }
136 :
137 416 : hEncoderConfig = st_ivas->hEncoderConfig;
138 :
139 416 : generate_gridEq_fx( &( hMasa->data.Sph_Grid16 ) );
140 :
141 416 : test();
142 416 : IF( EQ_32( hEncoderConfig->ivas_format, MASA_FORMAT ) || EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
143 : {
144 119 : hMasa->data.num_Cldfb_instances = st_ivas->nchan_transport;
145 119 : move16();
146 : }
147 : ELSE
148 : {
149 297 : hMasa->data.num_Cldfb_instances = 0;
150 297 : move16();
151 : }
152 :
153 623 : FOR( i = 0; i < hMasa->data.num_Cldfb_instances; i++ )
154 : {
155 207 : IF( NE_32( ( error = openCldfb_ivas_fx( &( hMasa->data.cldfbAnaEnc[i] ), CLDFB_ANALYSIS, hEncoderConfig->input_Fs, CLDFB_PROTOTYPE_5_00MS, ENC ) ), IVAS_ERR_OK ) )
156 : {
157 0 : return error;
158 : }
159 : }
160 :
161 416 : ism_total_brate = 0;
162 416 : move32();
163 416 : test();
164 416 : test();
165 416 : test();
166 416 : test();
167 416 : IF( EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
168 : {
169 104 : FOR( i = 0; i < st_ivas->nSCE; i++ )
170 : {
171 67 : ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
172 : }
173 : }
174 :
175 416 : ivas_masa_set_elements_fx( 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 );
176 :
177 416 : Copy( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
178 416 : Copy( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 );
179 :
180 416 : hMasa->data.onset_detector_1_fx = 0; // hMasa->data.q_onset_detector
181 416 : hMasa->data.onset_detector_2_fx = 0; // hMasa->data.q_onset_detector
182 416 : hMasa->data.q_onset_detector = 0;
183 416 : move32();
184 416 : move32();
185 416 : move16();
186 :
187 416 : set32_fx( hMasa->data.lfeToTotalEnergyRatio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); // hMasa->data.lfeToTotalEnergyRatio_e
188 416 : set16_fx( hMasa->data.lfeToTotalEnergyRatio_e, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
189 416 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = 0; // Q31
190 416 : move32();
191 :
192 416 : hMasa->data.prevq_lfeIndex = 0;
193 416 : move16();
194 :
195 416 : hMasa->data.sync_state.prev_sim_stop = 0;
196 416 : hMasa->data.sync_state.prev_offset = 0;
197 416 : hMasa->data.sync_state.frame_mode = MASA_FRAME_4SF;
198 416 : move16();
199 416 : move16();
200 416 : move32();
201 :
202 416 : set_zero_fx( hMasa->data.dir_align_state.previous_azi_dir1_fx, MASA_FREQUENCY_BANDS ); // Q22
203 416 : set_zero_fx( hMasa->data.dir_align_state.previous_ele_dir1_fx, MASA_FREQUENCY_BANDS ); // Q22
204 416 : set_zero_fx( hMasa->data.dir_align_state.previous_azi_dir2_fx, MASA_FREQUENCY_BANDS ); // Q22
205 416 : set_zero_fx( hMasa->data.dir_align_state.previous_ele_dir2_fx, MASA_FREQUENCY_BANDS ); // Q22
206 :
207 416 : IF( EQ_32( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
208 : {
209 : OMASA_ENCODER_DATA_HANDLE hOmasaData;
210 :
211 44 : IF( ( hOmasaData = (OMASA_ENCODER_DATA_HANDLE) malloc( sizeof( OMASA_ENCODER_DATA_STATE ) ) ) == NULL )
212 : {
213 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data encoder\n" ) );
214 : }
215 :
216 220 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
217 : {
218 176 : set32_fx( hOmasaData->masa_to_total_energy_ratio_fx[i], 0, MASA_FREQUENCY_BANDS ); // Q30
219 : }
220 :
221 44 : hOmasaData->lp_noise_CPE_fx = -256; /* -1 in Q8 */
222 44 : move16();
223 44 : hOmasaData->omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX;
224 44 : move16();
225 :
226 44 : IF( NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
227 : {
228 27 : IF( ( hOmasaData->hOmasaEnergy = (OMASA_ENCODER_ENERGY_HANDLE) malloc( sizeof( OMASA_ENCODER_ENERGY_STATE ) ) ) == NULL )
229 : {
230 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA energy handle\n" ) );
231 : }
232 :
233 135 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
234 : {
235 108 : set_zero_fx( hOmasaData->hOmasaEnergy->energy_ism_fx[i], MASA_FREQUENCY_BANDS ); // hOmasaData->energy_ism_fx_e
236 108 : set16_fx( hOmasaData->hOmasaEnergy->energy_ism_fx_e[i], 0, MASA_FREQUENCY_BANDS );
237 : }
238 : }
239 : else
240 : {
241 17 : hOmasaData->hOmasaEnergy = NULL;
242 : }
243 :
244 44 : hMasa->data.hOmasaData = hOmasaData;
245 : }
246 : ELSE
247 : {
248 372 : hMasa->data.hOmasaData = NULL;
249 : }
250 :
251 416 : st_ivas->hMasa = hMasa;
252 :
253 416 : return error;
254 : }
255 :
256 :
257 : /*-----------------------------------------------------------------------*
258 : * ivas_masa_enc_close()
259 : *
260 : * close MASA encoder
261 : *-----------------------------------------------------------------------*/
262 :
263 1087 : void ivas_masa_enc_close_fx(
264 : MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */
265 : )
266 : {
267 : Word16 i;
268 :
269 1087 : test();
270 1087 : IF( hMasa == NULL || *hMasa == NULL )
271 : {
272 671 : return;
273 : }
274 :
275 623 : FOR( i = 0; i < ( *hMasa )->data.num_Cldfb_instances; i++ )
276 : {
277 207 : deleteCldfb_ivas_fx( &( ( *hMasa )->data.cldfbAnaEnc[i] ) );
278 : }
279 :
280 416 : IF( ( *hMasa )->data.hOmasaData != NULL )
281 : {
282 44 : IF( ( *hMasa )->data.hOmasaData->hOmasaEnergy != NULL )
283 : {
284 25 : free( ( *hMasa )->data.hOmasaData->hOmasaEnergy );
285 25 : ( *hMasa )->data.hOmasaData->hOmasaEnergy = NULL;
286 : }
287 :
288 44 : free( ( *hMasa )->data.hOmasaData );
289 44 : ( *hMasa )->data.hOmasaData = NULL;
290 : }
291 :
292 416 : free( ( *hMasa ) );
293 416 : ( *hMasa ) = NULL;
294 :
295 416 : return;
296 : }
297 :
298 :
299 : /*-----------------------------------------------------------------------*
300 : * ivas_masa_encode()
301 : *
302 : * main MASA encoder function
303 : *-----------------------------------------------------------------------*/
304 :
305 51306 : ivas_error ivas_masa_encode_fx(
306 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
307 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
308 : BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */
309 : Word16 *nb_bits_metadata, /* o : number of metadata bits written */
310 : const Word16 nchan_transport, /* i : number of MASA input/transport channels */
311 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
312 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
313 : const Word16 Opt_DTX_ON, /* i : DTX on flag */
314 : const Word16 element_mode, /* i : element mode */
315 : const ISM_MODE ism_mode, /* i : ISM format mode */
316 : const Word16 nchan_ism, /* i : number of ISM channels */
317 : ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata handle */
318 : const Word16 idx_separated_object, /* i : index of the separated object */
319 : OMASA_ENC_HANDLE hOMasa, /* i : OMASA encoder handle */
320 : const Word16 ism_imp, /* i : importance of separated object */
321 : const Word16 flag_omasa_ener_brate /* i : less bitrate for objects in OMASA flag */
322 : )
323 : {
324 : MASA_DIRECTIONAL_SPATIAL_META *h_orig_metadata;
325 : Word16 i, j, s;
326 : Word16 masa_sid_descriptor;
327 : Word16 low_bitrate_mode;
328 : Word32 masa_total_brate;
329 : ivas_error error;
330 : Word16 guard_bits, tmp;
331 :
332 51306 : guard_bits = find_guarded_bits_fx( 9 );
333 :
334 51306 : masa_sid_descriptor = -1;
335 51306 : h_orig_metadata = NULL;
336 51306 : low_bitrate_mode = 0;
337 51306 : move16();
338 51306 : move16();
339 :
340 51306 : test();
341 51306 : IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
342 : {
343 : /* Create the MASA SID descriptor for the metadata and CPE mode, in order to have the SID frame self-contained. */
344 39626 : IF( Opt_DTX_ON && hQMetaData != NULL )
345 : {
346 7028 : IF( EQ_16( nchan_transport, 2 ) ) /* this is MASA format in CPE only */
347 : {
348 4016 : masa_sid_descriptor = 0; /* for IVAS_CPE_DFT */
349 4016 : move16();
350 4016 : if ( EQ_16( element_mode, IVAS_CPE_MDCT ) )
351 : {
352 1648 : masa_sid_descriptor = 1;
353 1648 : move16();
354 : }
355 : }
356 : }
357 :
358 : /* Validate and compensate ratios as necessary */
359 39626 : compensate_energy_ratios_fx( hMasa );
360 :
361 39626 : IF( Opt_DTX_ON )
362 : {
363 7028 : IF( ( h_orig_metadata = (MASA_DIRECTIONAL_SPATIAL_META *) malloc( MASA_MAXIMUM_DIRECTIONS * sizeof( MASA_DIRECTIONAL_SPATIAL_META ) ) ) == NULL )
364 : {
365 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) );
366 : }
367 :
368 21084 : FOR( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
369 : {
370 70280 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
371 : {
372 56224 : Copy32( hMasa->masaMetadata.directional_meta[i].azimuth_fx[j], h_orig_metadata[i].azimuth_fx[j], MASA_FREQUENCY_BANDS ); // Q22
373 56224 : Copy32( hMasa->masaMetadata.directional_meta[i].elevation_fx[j], h_orig_metadata[i].elevation_fx[j], MASA_FREQUENCY_BANDS ); // Q22
374 56224 : Copy32( hMasa->masaMetadata.directional_meta[i].energy_ratio_fx[j], h_orig_metadata[i].energy_ratio_fx[j], MASA_FREQUENCY_BANDS ); // Q30
375 56224 : Copy( (Word16 *) ( hMasa->masaMetadata.directional_meta[i].spherical_index[j] ), (Word16 *) ( h_orig_metadata[i].spherical_index[j] ), MASA_FREQUENCY_BANDS );
376 : }
377 : }
378 : }
379 :
380 39626 : test();
381 39626 : test();
382 39626 : if ( ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) && GE_32( ivas_total_brate, IVAS_384k ) )
383 : {
384 2636 : hMasa->config.mergeRatiosOverSubframes = 0;
385 2636 : move16();
386 : }
387 :
388 : /* Combine frequency bands and sub-frames */
389 39626 : combine_freqbands_and_subframes_fx( hMasa );
390 : }
391 :
392 : /* aligning the exponents of energy_fx */
393 51306 : s = 0;
394 51306 : move16();
395 256530 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
396 : {
397 205224 : maximum_s( hMasa->data.energy_e[i], MASA_FREQUENCY_BANDS, &tmp );
398 205224 : s = s_max( s, tmp );
399 : }
400 51306 : s = add( s, guard_bits );
401 256530 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
402 : {
403 5130600 : FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
404 : {
405 4925376 : hMasa->data.energy_fx[i][j] = L_shr( hMasa->data.energy_fx[i][j], sub( s, hMasa->data.energy_e[i][j] ) ); // hMasa->data.energy_e[i][j] -> s
406 4925376 : hMasa->data.energy_e[i][j] = s;
407 4925376 : move32();
408 4925376 : move16();
409 : }
410 : }
411 51306 : hMasa->data.q_energy = sub( 31, s );
412 51306 : move16();
413 :
414 51306 : test();
415 51306 : test();
416 51306 : test();
417 51306 : IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && LT_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) && ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) )
418 : {
419 9520 : test();
420 9520 : test();
421 9520 : test();
422 9520 : IF( ( EQ_32( ivas_format, MASA_ISM_FORMAT ) && NE_32( ism_mode, ISM_MODE_NONE ) && NE_32( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) || NE_32( ivas_format, MASA_ISM_FORMAT ) )
423 : {
424 : /* Combine directions */
425 7322 : ivas_masa_combine_directions_fx( hMasa );
426 : }
427 :
428 : /* If we joined all bands, then metadata is now one directional. */
429 9520 : IF( hMasa->config.numTwoDirBands == 0 )
430 : {
431 4064 : hMasa->config.numberOfDirections = 1;
432 4064 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
433 4064 : hQMetaData->no_directions = 1;
434 4064 : move16();
435 4064 : move16();
436 4064 : move16();
437 : }
438 : }
439 :
440 : /* Reset qmetadata bit budget */
441 51306 : hQMetaData->metadata_max_bits = hMasa->config.max_metadata_bits;
442 51306 : move16();
443 51306 : test();
444 51306 : IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
445 : {
446 39626 : test();
447 39626 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && NE_32( ism_mode, ISM_MODE_NONE ) )
448 : {
449 : /* write the number of objects in ISM_MASA format*/
450 7058 : push_next_indice( hMetaData, sub( nchan_ism, 1 ), NO_BITS_MASA_ISM_NO_OBJ );
451 7058 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, NO_BITS_MASA_ISM_NO_OBJ );
452 7058 : move16();
453 :
454 : /* write index of separated object if needed */
455 7058 : test();
456 7058 : IF( EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) && GT_16( nchan_ism, 1 ) )
457 : {
458 1862 : push_next_indice( hMetaData, idx_separated_object, NO_BITS_MASA_ISM_NO_OBJ );
459 1862 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, NO_BITS_MASA_ISM_NO_OBJ );
460 1862 : move16();
461 : }
462 :
463 : /* write ISM importance flag (one per object) */
464 7058 : IF( EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
465 : {
466 1862 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
467 1862 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
468 1862 : move16();
469 : }
470 5196 : ELSE IF( EQ_32( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
471 : {
472 2054 : IF( hIsmMetaData[0]->ism_md_null_flag )
473 : {
474 : /* signal NULL metadata frame */
475 0 : push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
476 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
477 0 : move16();
478 :
479 : /* write the ISM class to ISM_NO_META and again the true ISM class */
480 0 : push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
481 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
482 0 : move16();
483 0 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
484 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
485 0 : move16();
486 : }
487 : ELSE
488 : {
489 2054 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_imp, ISM_METADATA_FLAG_BITS );
490 2054 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
491 2054 : move16();
492 :
493 2054 : IF( EQ_16( hIsmMetaData[0]->ism_imp, ISM_NO_META ) )
494 : {
495 : /* signal low-rate ISM_NO_META frame */
496 0 : push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
497 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
498 0 : move16();
499 :
500 : /* signal presence of MD in low-rate ISM_NO_META frame */
501 0 : push_next_indice( hMetaData, hIsmMetaData[0]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
502 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_INACTIVE_FLAG_BITS );
503 0 : move16();
504 : }
505 : }
506 : }
507 3142 : ELSE IF( EQ_32( ism_mode, ISM_MASA_MODE_DISC ) )
508 : {
509 11602 : FOR( i = 0; i < nchan_ism; i++ )
510 : {
511 8460 : IF( hIsmMetaData[i]->ism_md_null_flag )
512 : {
513 : /* signal NULL metadata frame */
514 0 : push_next_indice( hMetaData, 1, ISM_METADATA_MD_FLAG_BITS );
515 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
516 0 : move16();
517 :
518 : /* write the ISM class to ISM_NO_META and again the true ISM class */
519 0 : push_next_indice( hMetaData, ISM_NO_META, ISM_METADATA_FLAG_BITS );
520 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
521 0 : move16();
522 0 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
523 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
524 0 : move16();
525 : }
526 : ELSE
527 : {
528 8460 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_imp, ISM_METADATA_FLAG_BITS );
529 8460 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_FLAG_BITS );
530 8460 : move16();
531 :
532 8460 : IF( EQ_16( hIsmMetaData[i]->ism_imp, ISM_NO_META ) )
533 : {
534 : /* signal low-rate ISM_NO_META frame */
535 0 : push_next_indice( hMetaData, 0, ISM_METADATA_MD_FLAG_BITS );
536 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_MD_FLAG_BITS );
537 0 : move16();
538 :
539 : /* signal presence of MD in low-rate ISM_NO_META frame */
540 0 : push_next_indice( hMetaData, hIsmMetaData[i]->ism_md_lowrate_flag, ISM_METADATA_INACTIVE_FLAG_BITS );
541 0 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, ISM_METADATA_INACTIVE_FLAG_BITS );
542 0 : move16();
543 : }
544 : }
545 : }
546 3142 : test();
547 3142 : IF( EQ_32( ivas_total_brate, IVAS_128k ) && GE_16( nchan_ism, 3 ) )
548 : {
549 126 : push_next_indice( hMetaData, flag_omasa_ener_brate, 1 );
550 126 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, 1 );
551 126 : move16();
552 : }
553 : }
554 : }
555 : ELSE
556 : {
557 32568 : test();
558 32568 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) )
559 : {
560 : /* use the MASA number of transport channels bit to signal if there are 1 or 2 objects */
561 1942 : test();
562 1942 : IF( EQ_16( nchan_ism, 1 ) || EQ_16( nchan_ism, 2 ) )
563 : {
564 474 : push_next_indice( hMetaData, sub( nchan_ism, 1 ), MASA_TRANSP_BITS );
565 : }
566 : ELSE
567 : {
568 : /* for 3 or 4 objects write already the number of MASA directions */
569 1468 : push_next_indice( hMetaData, sub( hQMetaData->no_directions, 1 ), MASA_TRANSP_BITS );
570 : }
571 : }
572 : ELSE
573 : {
574 : /* write the number of MASA transport channels */
575 30626 : push_next_indice( hMetaData, sub( nchan_transport, 1 ), MASA_TRANSP_BITS );
576 : }
577 32568 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_TRANSP_BITS );
578 32568 : move16();
579 : }
580 :
581 39626 : test();
582 39626 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) )
583 : {
584 1942 : IF( GE_16( nchan_ism, 3 ) ) /* if 3 or 4 objects */
585 : {
586 1468 : push_next_indice( hMetaData, sub( 5, nchan_ism ), MASA_HEADER_BITS );
587 : }
588 : ELSE
589 : {
590 474 : push_next_indice( hMetaData, 3, MASA_HEADER_BITS );
591 : }
592 1942 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
593 1942 : move16();
594 : }
595 : ELSE
596 : {
597 : /* the MASA_ISM_FORMAT is not signalled here */
598 : /* write reserved bits */
599 37684 : push_next_indice( hMetaData, 0, MASA_HEADER_BITS );
600 37684 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_HEADER_BITS );
601 37684 : move16();
602 : }
603 39626 : test();
604 39626 : test();
605 39626 : test();
606 39626 : IF( !( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MODE_NONE ) && GT_16( nchan_ism, 2 ) ) )
607 : {
608 : /* write number of directions */
609 38158 : push_next_indice( hMetaData, sub( hQMetaData->no_directions, 1 ), 1 );
610 38158 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, 1 );
611 38158 : move16();
612 : }
613 :
614 : /* write subframe mode */
615 39626 : IF( EQ_16( hQMetaData->q_direction[0].cfg.nblocks, 1 ) )
616 : {
617 5550 : push_next_indice( hMetaData, 1, MASA_SUBFRAME_BITS );
618 : }
619 : ELSE
620 : {
621 34076 : push_next_indice( hMetaData, 0, MASA_SUBFRAME_BITS );
622 : }
623 39626 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_SUBFRAME_BITS );
624 39626 : move16();
625 : }
626 :
627 :
628 51306 : IF( EQ_32( ivas_format, MC_FORMAT ) )
629 : {
630 : Word16 lfeBitsWritten;
631 :
632 11680 : lfeBitsWritten = encode_lfe_to_total_energy_ratio_fx( hMasa, hMetaData, ivas_total_brate );
633 :
634 11680 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, lfeBitsWritten );
635 11680 : move16();
636 : }
637 :
638 : /* Move data from encoder to qmetadata */
639 51306 : test();
640 51306 : IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) )
641 : {
642 39626 : move_metadata_to_qmetadata_fx( hMasa, hQMetaData );
643 : }
644 :
645 51306 : test();
646 51306 : IF( LT_16( hMasa->config.max_metadata_bits, MINIMUM_BIT_BUDGET_NORMAL_META ) && !hMasa->config.joinedSubframes )
647 : {
648 25011 : reduce_metadata_further_fx( hMasa, hQMetaData, ivas_format );
649 :
650 25011 : low_bitrate_mode = (Word16) LE_32( ivas_total_brate, 32000 );
651 :
652 : /* Write low bitrate mode. 1 signals that we have merged through time, 0 signals merge through frequency. */
653 25011 : IF( EQ_16( hQMetaData->q_direction[0].cfg.nblocks, 1 ) )
654 : {
655 21010 : push_next_indice( hMetaData, 1, MASA_LOWBITRATE_MODE_BITS );
656 : }
657 : ELSE
658 : {
659 4001 : push_next_indice( hMetaData, 0, MASA_LOWBITRATE_MODE_BITS );
660 : }
661 25011 : hQMetaData->metadata_max_bits = sub( hQMetaData->metadata_max_bits, MASA_LOWBITRATE_MODE_BITS );
662 25011 : move16();
663 : }
664 :
665 : /* Encode MASA+ISM metadata */
666 51306 : test();
667 51306 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
668 : {
669 : /* encode MASA/ISM energy ratios */
670 1862 : ivas_encode_masaism_metadata_fx( hMasa, hQMetaData, hMetaData, hIsmMetaData, nchan_ism, low_bitrate_mode, hOMasa->nCodingBands, hOMasa->nSubframes, idx_separated_object, ism_imp );
671 : }
672 : ELSE
673 : {
674 49444 : if ( EQ_32( ivas_format, MASA_ISM_FORMAT ) )
675 : {
676 7138 : hMasa->data.hOmasaData->masa_to_total_energy_ratio_fx[0][0] = -ONE_IN_Q30; /* signals NOT to adjust the energy ratios */
677 7138 : move32();
678 : }
679 : }
680 :
681 : /* Encode metadata */
682 51306 : masa_total_brate = ivas_total_brate;
683 51306 : move32();
684 51306 : test();
685 51306 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_DISC ) )
686 : {
687 3142 : masa_total_brate = calculate_cpe_brate_MASA_ISM_fx( ism_mode, ivas_total_brate, nchan_ism );
688 : }
689 :
690 51306 : IF( GE_32( masa_total_brate, IVAS_384k ) )
691 : {
692 2276 : IF( GE_32( masa_total_brate, IVAS_512k ) )
693 : {
694 800 : IF( NE_32( ( error = ivas_qmetadata_enc_encode_hr_384_512_fx( hMetaData, hQMetaData, 16, 4 ) ), IVAS_ERR_OK ) )
695 : {
696 0 : return error;
697 : }
698 : }
699 : ELSE
700 : {
701 1476 : IF( NE_32( ( error = ivas_qmetadata_enc_encode_hr_384_512_fx( hMetaData, hQMetaData, 11, 3 ) ), IVAS_ERR_OK ) )
702 : {
703 0 : return error;
704 : }
705 : }
706 : }
707 : ELSE
708 : {
709 49030 : IF( NE_32( ( error = ivas_qmetadata_enc_encode_fx( hMetaData, hQMetaData, 0 ) ), IVAS_ERR_OK ) )
710 : {
711 0 : return error;
712 : }
713 : }
714 :
715 51306 : test();
716 51306 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
717 : {
718 : /* Modify spatial metadata based on the MASA-to-total energy ratios */
719 1862 : ivas_omasa_modify_masa_energy_ratios_fx( hQMetaData, hMasa->data.hOmasaData->masa_to_total_energy_ratio_fx );
720 : }
721 :
722 51306 : *nb_bits_metadata = hMetaData->nb_bits_tot;
723 51306 : move16();
724 :
725 51306 : test();
726 51306 : IF( EQ_32( ivas_format, MASA_FORMAT ) && Opt_DTX_ON )
727 : {
728 : /* save old values */
729 7028 : UWord8 numCodingBands = hMasa->config.numCodingBands;
730 7028 : UWord8 numTwoDirBands = hMasa->config.numTwoDirBands;
731 7028 : Word16 nbands = hQMetaData->q_direction[0].cfg.nbands;
732 7028 : UWord8 numberOfDirections = hMasa->config.numberOfDirections;
733 7028 : UWord8 numberOfDirectionsMeta = hMasa->masaMetadata.descriptive_meta.numberOfDirections;
734 7028 : UWord16 numberOfDirectionsQMetaData = hQMetaData->no_directions;
735 7028 : move16();
736 7028 : move16();
737 7028 : move16();
738 7028 : move16();
739 7028 : move16();
740 7028 : move16();
741 :
742 7028 : test();
743 7028 : IF( !( EQ_16( hMasa->config.numberOfDirections, 1 ) && EQ_16( hQMetaData->q_direction->cfg.nbands, 5 ) ) )
744 : {
745 5937 : FOR( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ )
746 : {
747 19790 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
748 : {
749 15832 : Copy32( h_orig_metadata[i].azimuth_fx[j], hMasa->masaMetadata.directional_meta[i].azimuth_fx[j], MASA_FREQUENCY_BANDS ); // Q22
750 15832 : Copy32( h_orig_metadata[i].elevation_fx[j], hMasa->masaMetadata.directional_meta[i].elevation_fx[j], MASA_FREQUENCY_BANDS ); // Q22
751 15832 : Copy32( h_orig_metadata[i].energy_ratio_fx[j], hMasa->masaMetadata.directional_meta[i].energy_ratio_fx[j], MASA_FREQUENCY_BANDS ); // Q30
752 : }
753 : }
754 :
755 : /* Force to have 5 bands and 1 direction */
756 1979 : hMasa->config.numCodingBands = 5;
757 1979 : hMasa->config.numTwoDirBands = 0;
758 1979 : move16();
759 1979 : move16();
760 :
761 1979 : combine_freqbands_and_subframes_fx( hMasa );
762 :
763 1979 : hQMetaData->q_direction[0].cfg.nbands = 5;
764 1979 : move16();
765 :
766 1979 : test();
767 1979 : IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && LT_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
768 : {
769 : /* Combine directions */
770 0 : ivas_masa_combine_directions_fx( hMasa );
771 :
772 : /* If we joined all bands, then metadata is now one directional. */
773 0 : IF( hMasa->config.numTwoDirBands == 0 )
774 : {
775 0 : hMasa->config.numberOfDirections = 1;
776 0 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = 0;
777 0 : hQMetaData->no_directions = 1;
778 0 : move16();
779 0 : move16();
780 0 : move16();
781 : }
782 : }
783 :
784 1979 : move_metadata_to_qmetadata_fx( hMasa, hQMetaData );
785 :
786 11874 : FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
787 : {
788 9895 : hQMetaData->q_direction[0].band_data[j].energy_ratio_index[0] = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
789 9895 : move32();
790 : }
791 : }
792 :
793 7028 : free( h_orig_metadata );
794 :
795 7028 : ivas_qmetadata_enc_sid_encode_fx( hMetaData, hQMetaData, masa_sid_descriptor, 0, ivas_format );
796 :
797 : /* restore old values */
798 7028 : hMasa->config.numCodingBands = numCodingBands;
799 7028 : hMasa->config.numTwoDirBands = numTwoDirBands;
800 7028 : hQMetaData->q_direction[0].cfg.nbands = nbands;
801 7028 : hMasa->config.numberOfDirections = numberOfDirections;
802 7028 : hMasa->masaMetadata.descriptive_meta.numberOfDirections = numberOfDirectionsMeta;
803 7028 : hQMetaData->no_directions = numberOfDirectionsQMetaData;
804 7028 : move16();
805 7028 : move16();
806 7028 : move16();
807 7028 : move16();
808 7028 : move16();
809 7028 : move16();
810 : }
811 :
812 51306 : return IVAS_ERR_OK;
813 : }
814 :
815 :
816 : /*-----------------------------------------------------------------------*
817 : * ivas_masa_estimate_energy_fx()
818 : *
819 : *
820 : *-----------------------------------------------------------------------*/
821 :
822 39626 : void ivas_masa_estimate_energy_fx(
823 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
824 : Word32 *data_fx[], /* i : Input audio channels Q(q_data) */
825 : const Word16 input_frame, /* i : frame length */
826 : const Word16 nchan_transport, /* i : number of MASA input/transport channels */
827 : Word16 q_data /* i : q for data_fx */
828 : )
829 : {
830 : Word32 Input_RealBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
831 : Word32 Input_ImagBuffer[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
832 : Word16 block_m_idx, band_m_idx;
833 : Word16 mrange[2], brange[2];
834 : Word16 i, j, ts, l_ts, maxBin;
835 : Word64 energy_fx_temp[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
836 39626 : Word16 scale = 63;
837 39626 : move16();
838 : Word16 q_buf;
839 39626 : maxBin = extract_l( Mpy_32_32( 134217728 /*CLDFB_NO_CHANNELS_MAX / L_FRAME48k in Q31*/, input_frame ) );
840 39626 : l_ts = shr( input_frame, CLDFB_NO_COL_MAX_LOG2 );
841 :
842 198130 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
843 : {
844 3962600 : FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
845 : {
846 3804096 : energy_fx_temp[i][j] = 0;
847 3804096 : move64();
848 : }
849 : }
850 :
851 198130 : FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
852 : {
853 158504 : mrange[0] = hMasa->config.block_grouping[block_m_idx];
854 158504 : move16();
855 158504 : mrange[1] = hMasa->config.block_grouping[block_m_idx + 1];
856 158504 : move16();
857 158504 : set_zero_fx( hMasa->data.energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
858 158504 : set16_fx( hMasa->data.energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
859 :
860 792520 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
861 : {
862 1676608 : FOR( i = 0; i < nchan_transport; i++ )
863 : {
864 1042592 : q_buf = q_data;
865 1042592 : move16();
866 1042592 : scale_sig32( hMasa->data.cldfbAnaEnc[i]->cldfb_state_fx, hMasa->data.cldfbAnaEnc[i]->cldfb_state_length, sub( q_buf, hMasa->data.cldfbAnaEnc[i]->Q_cldfb_state ) );
867 1042592 : hMasa->data.cldfbAnaEnc[i]->Q_cldfb_state = q_buf;
868 1042592 : move16();
869 1042592 : cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][l_ts * ts] ), Input_RealBuffer[i], Input_ImagBuffer[i], l_ts, hMasa->data.cldfbAnaEnc[i], &q_buf ); // (q_data - 5) for Input_RealBuffer[i], Input_ImagBuffer[i]
870 : }
871 :
872 15850400 : FOR( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
873 : {
874 15216384 : brange[0] = hMasa->config.band_grouping[band_m_idx];
875 15216384 : move16();
876 15216384 : brange[1] = hMasa->config.band_grouping[band_m_idx + 1];
877 15216384 : move16();
878 :
879 40238592 : FOR( i = 0; i < nchan_transport; i++ )
880 : {
881 25022208 : IF( GT_16( brange[0], maxBin ) )
882 : {
883 72000 : hMasa->data.energy_fx[block_m_idx][band_m_idx] = 0;
884 72000 : move32();
885 72000 : CONTINUE;
886 : }
887 24950208 : ELSE IF( GE_16( brange[1], maxBin ) )
888 : {
889 1116992 : brange[1] = maxBin;
890 1116992 : move16();
891 : }
892 :
893 85537728 : FOR( j = brange[0]; j < brange[1]; j++ )
894 : {
895 60587520 : energy_fx_temp[block_m_idx][band_m_idx] = W_add( energy_fx_temp[block_m_idx][band_m_idx], W_mac_32_32( W_mult_32_32( Input_RealBuffer[i][j], Input_RealBuffer[i][j] ), Input_ImagBuffer[i][j], Input_ImagBuffer[i][j] ) ); // Q: 2 * (q_data - 5) + 1 for energy_fx_temp
896 60587520 : move64();
897 : }
898 24950208 : IF( energy_fx_temp[block_m_idx][band_m_idx] != 0 )
899 : {
900 24875808 : scale = s_min( scale, W_norm( energy_fx_temp[block_m_idx][band_m_idx] ) ); // scale calculates minimum shift can be done across a buffer
901 : }
902 : }
903 : }
904 : }
905 : }
906 :
907 198130 : FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
908 : {
909 3962600 : FOR( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
910 : {
911 3804096 : energy_fx_temp[block_m_idx][band_m_idx] = W_shl( energy_fx_temp[block_m_idx][band_m_idx], scale ); // Q: 2 * (q_data - 5) + 1 + scale
912 3804096 : move64();
913 3804096 : hMasa->data.energy_fx[block_m_idx][band_m_idx] = W_extract_h( energy_fx_temp[block_m_idx][band_m_idx] ); // Q: 2 * (q_data - 5) + 1 + scale - 32
914 3804096 : move32();
915 3804096 : hMasa->data.energy_e[block_m_idx][band_m_idx] = sub( 31, add( add( imult1616( 2, q_data ), scale ), 1 - 10 - 32 ) );
916 3804096 : move16();
917 : }
918 : }
919 39626 : hMasa->data.q_energy = add( add( imult1616( 2, q_data ), scale ), 1 - 10 - 32 );
920 39626 : move16();
921 :
922 39626 : return;
923 : }
924 :
925 :
926 : /*-----------------------------------------------------------------------*
927 : * ivas_masa_enc_config()
928 : *
929 : * Frame-by-frame configuration of MASA encoder
930 : *-----------------------------------------------------------------------*/
931 :
932 39923 : ivas_error ivas_masa_enc_config_fx(
933 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
934 : )
935 : {
936 : Word16 i;
937 : MASA_ENCODER_HANDLE hMasa;
938 : IVAS_QMETADATA_HANDLE hQMetaData;
939 : IVAS_FORMAT ivas_format;
940 : UWord8 joinedSubframes;
941 : UWord8 coherencePresent;
942 : UWord8 isActualTwoDir; /* Flag to tell that when there are two directions present in metadata, they both contain meaningful information. */
943 : Word32 ivas_total_brate;
944 : UWord8 maxBand;
945 : Word16 maxBin, sf;
946 : ivas_error error;
947 : Word32 ism_total_brate;
948 : Word32 masa_total_brate;
949 :
950 39923 : error = IVAS_ERR_OK;
951 39923 : move16();
952 :
953 39923 : hMasa = st_ivas->hMasa;
954 39923 : hQMetaData = st_ivas->hQMetaData;
955 39923 : ivas_format = st_ivas->hEncoderConfig->ivas_format;
956 39923 : ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
957 39923 : move16();
958 39923 : move32();
959 :
960 39923 : ism_total_brate = 0;
961 39923 : move32();
962 39923 : test();
963 39923 : test();
964 39923 : test();
965 39923 : test();
966 39923 : IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
967 : {
968 19434 : FOR( i = 0; i < st_ivas->nSCE; i++ )
969 : {
970 12376 : ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate );
971 : }
972 : }
973 :
974 39923 : ivas_masa_set_elements_fx( 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 );
975 :
976 39923 : hQMetaData->is_masa_ivas_format = 1;
977 39923 : move16();
978 :
979 39923 : test();
980 39923 : test();
981 39923 : IF( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) )
982 : {
983 39626 : masa_metadata_direction_alignment_fx( hMasa );
984 :
985 39626 : detect_framing_async_fx( hMasa ); /* detect the offset, set 1sf/4sf mode based on this. potentially also shift the metadata using a history buffer */
986 39626 : test();
987 39626 : IF( EQ_16( hMasa->data.sync_state.frame_mode, MASA_FRAME_1SF ) && hMasa->data.sync_state.prev_offset != 0 )
988 : {
989 : /* average over sub-frames */
990 0 : IF( EQ_32( ivas_total_brate, IVAS_512k ) )
991 : {
992 0 : average_masa_metadata_fx( &( hMasa->masaMetadata ), hMasa->data.energy_fx, hMasa->data.energy_e, &( hMasa->data.Sph_Grid16 ), TRUE );
993 : }
994 : ELSE
995 : {
996 0 : average_masa_metadata_fx( &( hMasa->masaMetadata ), hMasa->data.energy_fx, hMasa->data.energy_e, &( hMasa->data.Sph_Grid16 ), FALSE );
997 : }
998 : }
999 :
1000 : /* Inspect metadata for parameter changes that affect coding. */
1001 39626 : detect_metadata_composition_fx( hMasa, &joinedSubframes, &coherencePresent, &isActualTwoDir );
1002 :
1003 39626 : hMasa->config.joinedSubframes = joinedSubframes;
1004 39626 : hMasa->config.coherencePresent = coherencePresent;
1005 39626 : move16();
1006 39626 : move16();
1007 39626 : test();
1008 39626 : IF( EQ_16( add( hMasa->masaMetadata.descriptive_meta.numberOfDirections, 1 ), 2 ) && isActualTwoDir )
1009 : {
1010 9900 : hMasa->config.numberOfDirections = 2;
1011 : }
1012 : ELSE
1013 : {
1014 29726 : hMasa->config.numberOfDirections = 1;
1015 : }
1016 39626 : move16();
1017 : }
1018 297 : ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) )
1019 : {
1020 : /* For McMASA, these are set only once as this function is called only once. */
1021 297 : hMasa->config.joinedSubframes = 0;
1022 297 : hMasa->config.numberOfDirections = 1;
1023 297 : move16();
1024 297 : move16();
1025 : }
1026 :
1027 39923 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) )
1028 : {
1029 9000 : ivas_masa_set_coding_config_fx( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hCPE[0]->element_brate, st_ivas->nchan_transport, MC_MODE_NONE );
1030 : }
1031 : ELSE
1032 : {
1033 30923 : test();
1034 30923 : ivas_masa_set_coding_config_fx( &( hMasa->config ), hMasa->data.band_mapping, ivas_total_brate, st_ivas->nchan_transport, ( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) );
1035 : }
1036 :
1037 : /* Setup importance weights for two-direction band selection. */
1038 39923 : IF( EQ_16( hMasa->config.numberOfDirections, 2 ) )
1039 : {
1040 9900 : set32_fx( hMasa->data.importanceWeight_fx, ONE_IN_Q30 /*1.0f Q30*/, MASA_FREQUENCY_BANDS );
1041 :
1042 9900 : IF( EQ_16( hMasa->config.numCodingBands, 5 ) )
1043 : {
1044 6670 : hMasa->data.importanceWeight_fx[4] = 751619277 /*0.7f q30*/;
1045 6670 : move32();
1046 : }
1047 3230 : ELSE IF( EQ_16( hMasa->config.numCodingBands, 8 ) )
1048 : {
1049 354 : hMasa->data.importanceWeight_fx[7] = 751619277 /*0.7f q30*/;
1050 354 : move32();
1051 : }
1052 2876 : ELSE IF( EQ_16( hMasa->config.numCodingBands, 10 ) )
1053 : {
1054 0 : hMasa->data.importanceWeight_fx[8] = 751619277 /*0.7f q30*/;
1055 0 : hMasa->data.importanceWeight_fx[9] = 107374182 /*0.1f q30*/;
1056 0 : move32();
1057 0 : move32();
1058 : }
1059 2876 : ELSE IF( EQ_16( hMasa->config.numCodingBands, 12 ) )
1060 : {
1061 794 : hMasa->data.importanceWeight_fx[10] = 751619277 /*0.7f q30*/;
1062 794 : hMasa->data.importanceWeight_fx[11] = 107374182 /*0.1f q30*/;
1063 794 : move32();
1064 794 : move32();
1065 : }
1066 2082 : ELSE IF( EQ_16( hMasa->config.numCodingBands, 18 ) )
1067 : {
1068 798 : hMasa->data.importanceWeight_fx[14] = 858993459 /*0.8f q30*/;
1069 798 : hMasa->data.importanceWeight_fx[15] = 536870912 /*0.5f q30*/;
1070 798 : hMasa->data.importanceWeight_fx[16] = 214748365 /*0.2f q30*/;
1071 798 : hMasa->data.importanceWeight_fx[17] = 0 /*0 q30*/;
1072 798 : move32();
1073 798 : move32();
1074 798 : move32();
1075 798 : move32();
1076 : }
1077 1284 : ELSE IF( EQ_16( hMasa->config.numCodingBands, 24 ) )
1078 : {
1079 1284 : hMasa->data.importanceWeight_fx[20] = 858993459 /*0.8f q30*/;
1080 1284 : hMasa->data.importanceWeight_fx[21] = 536870912 /*0.5f q30*/;
1081 1284 : hMasa->data.importanceWeight_fx[22] = 214748365 /*0.2f q30*/;
1082 1284 : hMasa->data.importanceWeight_fx[23] = 0 /*0 q30*/;
1083 1284 : move32();
1084 1284 : move32();
1085 1284 : move32();
1086 1284 : move32();
1087 : }
1088 :
1089 9900 : IF( EQ_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
1090 : {
1091 380 : set8_fx( (Word8 *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
1092 : }
1093 : }
1094 : ELSE
1095 : {
1096 30023 : set8_fx( (Word8 *) hMasa->data.twoDirBands, 0, hMasa->config.numCodingBands );
1097 : }
1098 :
1099 : /* Set qmeta to correct values */
1100 39923 : test();
1101 39923 : IF( EQ_16( hMasa->config.numberOfDirections, 2 ) && hMasa->config.numTwoDirBands != 0 )
1102 : {
1103 5836 : IF( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( hQMetaData, hMasa->config.numCodingBands, 2, hMasa->config.useCoherence ) ), IVAS_ERR_OK ) )
1104 : {
1105 0 : return error;
1106 : }
1107 : }
1108 : ELSE
1109 : {
1110 34087 : IF( NE_32( ( error = ivas_qmetadata_allocate_memory_fx( hQMetaData, hMasa->config.numCodingBands, 1, hMasa->config.useCoherence ) ), IVAS_ERR_OK ) )
1111 : {
1112 0 : return error;
1113 : }
1114 : }
1115 :
1116 85682 : FOR( i = 0; i < hQMetaData->no_directions; i++ )
1117 : {
1118 45759 : hQMetaData->q_direction[i].cfg.nbands = hMasa->config.numCodingBands;
1119 45759 : move16();
1120 45759 : IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
1121 : {
1122 6546 : hQMetaData->q_direction[i].cfg.nblocks = 1;
1123 : }
1124 : ELSE
1125 : {
1126 39213 : hQMetaData->q_direction[i].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES;
1127 : }
1128 45759 : move16();
1129 :
1130 45759 : IF( EQ_16( ivas_format, MC_FORMAT ) )
1131 : {
1132 297 : hQMetaData->q_direction[i].cfg.mc_ls_setup = st_ivas->hEncoderConfig->mc_input_setup;
1133 297 : move16();
1134 : }
1135 : ELSE
1136 : {
1137 : /* Just to be sure that this default value is maintained */
1138 45462 : hQMetaData->q_direction[i].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
1139 45462 : move16();
1140 : }
1141 : }
1142 :
1143 39923 : hQMetaData->all_coherence_zero = !hMasa->config.coherencePresent;
1144 39923 : move16();
1145 :
1146 39923 : ivas_set_qmetadata_maxbit_req_fx( hQMetaData, ivas_format );
1147 :
1148 : /* Find maximum band usable */
1149 39923 : maxBin = extract_l( Mpy_32_32( st_ivas->hEncoderConfig->input_Fs /*q0*/, INV_CLDFB_BANDWIDTH_Q31 /*Q31*/ ) ); /*q0+q31-q31->q0*/
1150 39923 : maxBand = 0;
1151 39923 : move16();
1152 39923 : test();
1153 1033308 : WHILE( ( maxBand <= MASA_FREQUENCY_BANDS ) && ( MASA_band_grouping_24[maxBand] <= maxBin ) )
1154 : {
1155 993385 : test();
1156 993385 : maxBand = (UWord8) add( maxBand, 1 );
1157 993385 : move16(); /*because typecasting word16 to uword8*/
1158 : }
1159 39923 : maxBand = (UWord8) sub( maxBand, 1 );
1160 39923 : move16(); /*because typecasting word16 to uword8*/
1161 :
1162 39923 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
1163 39923 : masa_total_brate = ivas_total_brate;
1164 39923 : move16();
1165 39923 : move32();
1166 39923 : test();
1167 39923 : IF( EQ_32( ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
1168 : {
1169 3142 : masa_total_brate = calculate_cpe_brate_MASA_ISM_fx( st_ivas->ism_mode, ivas_total_brate, st_ivas->hEncoderConfig->nchan_ism ); /*q0*/
1170 : }
1171 39923 : test();
1172 39923 : test();
1173 39923 : IF( GE_32( masa_total_brate, IVAS_384k ) && ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) )
1174 : {
1175 : Word16 continueLoop;
1176 2276 : continueLoop = 1;
1177 2276 : move16();
1178 2276 : test();
1179 4552 : WHILE( ( maxBand > 5 ) && continueLoop )
1180 : {
1181 2276 : test();
1182 2276 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1183 : {
1184 2276 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( hMasa->data.energy_fx[sf][maxBand - 1], hMasa->data.energy_e[sf][maxBand - 1], 100000 /*q0*/, 31 ), 1 ) )
1185 : {
1186 2276 : continueLoop = 0;
1187 2276 : move16();
1188 2276 : BREAK;
1189 : }
1190 : }
1191 2276 : IF( continueLoop )
1192 : {
1193 0 : maxBand = (UWord8) sub( maxBand, 1 );
1194 0 : move16(); /*because typecasting word16 to uword8*/
1195 : }
1196 : }
1197 :
1198 2276 : IF( LT_16( maxBand, MASA_MAXIMUM_CODING_SUBBANDS ) )
1199 : {
1200 300 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = (UWord8) sub( MASA_MAXIMUM_CODING_SUBBANDS, maxBand );
1201 300 : move16(); /*because typecasting word16 to uword8*/
1202 : }
1203 : ELSE
1204 : {
1205 1976 : st_ivas->hQMetaData->q_direction->cfg.inactiveBands = 0;
1206 1976 : move16();
1207 : }
1208 : }
1209 :
1210 39923 : masa_sample_rate_band_correction_fx( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, maxBand, (UWord8) GE_32( masa_total_brate, IVAS_384k ), NULL );
1211 :
1212 39923 : IF( GE_16( hMasa->config.numTwoDirBands, hMasa->config.numCodingBands ) )
1213 : {
1214 380 : hMasa->config.numTwoDirBands = hMasa->config.numCodingBands;
1215 380 : move16();
1216 380 : set8_fx( (Word8 *) hMasa->data.twoDirBands, 1, hMasa->config.numCodingBands );
1217 : }
1218 :
1219 39923 : test();
1220 39923 : test();
1221 39923 : test();
1222 39923 : test();
1223 : /* Transmit stereo signals using a mono downmix at lowest bitrates */
1224 39923 : IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && EQ_16( st_ivas->nCPE, 1 ) && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL )
1225 : {
1226 11938 : IF( LT_32( L_sub( ivas_total_brate, ism_total_brate ), MASA_STEREO_MIN_BITRATE ) )
1227 : {
1228 5484 : st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 1;
1229 : }
1230 : ELSE
1231 : {
1232 6454 : st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0;
1233 : }
1234 11938 : move16();
1235 : }
1236 :
1237 39923 : test();
1238 39923 : test();
1239 39923 : test();
1240 39923 : IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) )
1241 : {
1242 7058 : test();
1243 7058 : IF( EQ_16( st_ivas->hCPE[0]->element_mode, IVAS_CPE_DFT ) || LT_16( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt, OMASA_STEREO_SW_CNT_MAX ) )
1244 : {
1245 3051 : st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = extract_h( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_32fx ); /*Q8*/
1246 : }
1247 : ELSE
1248 : {
1249 : /* ( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise + st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise ) / CPE_CHANNELS; */
1250 4007 : st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = extract_h( L_mac( L_mult( extract_h( st_ivas->hCPE[0]->hCoreCoder[0]->lp_noise_32fx ), ONE_IN_Q14 ), extract_h( st_ivas->hCPE[0]->hCoreCoder[1]->lp_noise_32fx ), ONE_IN_Q14 ) ); /*Q8*/
1251 : }
1252 7058 : move16();
1253 : }
1254 :
1255 39923 : return error;
1256 : }
1257 :
1258 :
1259 : /*-----------------------------------------------------------------------*
1260 : * ivas_masa_surrcoh_signicant()
1261 : *
1262 : * Determine if surrounding coherence is significant in this frame and should be encoded
1263 : *-----------------------------------------------------------------------*/
1264 :
1265 2589 : UWord8 ivas_masa_surrcoh_signicant_fx(
1266 : Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence Q31 */
1267 : Word32 diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio Q31 */
1268 : const Word16 nSubFrames, /* i : Number of sub frames */
1269 : const Word16 nBands /* i : Number of frequency bands */
1270 : )
1271 : {
1272 : Word32 significanceMeasure1, significanceMeasure2, significanceMeasure;
1273 : Word32 surrCohToTotal, surrCohToTotalSum, surrCohToTotalTimesDiffSum, diffSum;
1274 : Word32 sf, band;
1275 : Word16 surrCohToTotalSum_e, surrCohToTotalTimesDiffSum_e, diffSum_e;
1276 :
1277 : // input buffers Q=31
1278 2589 : Word32 surrCohSignificanceCoef = 858993459; //( 0.4 * ( 1 << q ) ) 0.4 scaled to Q=31
1279 2589 : move32();
1280 2589 : Word32 threshold = 214748365; //( 0.1 * ( 1 << q ) ) 0.1 scaled to Q=31
1281 2589 : move32();
1282 5802 : FOR( sf = 0; sf < nSubFrames; sf++ )
1283 : {
1284 3630 : surrCohToTotalSum = 0;
1285 3630 : move32();
1286 3630 : surrCohToTotalSum_e = 0;
1287 3630 : move16();
1288 3630 : surrCohToTotalTimesDiffSum = 0;
1289 3630 : move32();
1290 3630 : surrCohToTotalTimesDiffSum_e = 0;
1291 3630 : move16();
1292 3630 : diffSum = 0;
1293 3630 : move32();
1294 3630 : diffSum_e = 0;
1295 3630 : move16();
1296 :
1297 75702 : FOR( band = 0; band < nBands; band++ )
1298 : {
1299 72072 : surrCohToTotal = Mpy_32_32( diffuse_to_total_ratio[sf][band], surroundingCoherence[sf][band] ); // Q31
1300 72072 : surrCohToTotalSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalSum, surrCohToTotalSum_e, surrCohToTotal, 0, &surrCohToTotalSum_e );
1301 72072 : surrCohToTotalTimesDiffSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalTimesDiffSum, surrCohToTotalTimesDiffSum_e, Mpy_32_32( (Word32) diffuse_to_total_ratio[sf][band], surrCohToTotal ), 0, &surrCohToTotalTimesDiffSum_e );
1302 72072 : diffSum = BASOP_Util_Add_Mant32Exp( diffSum, diffSum_e, diffuse_to_total_ratio[sf][band], 0, &diffSum_e );
1303 : }
1304 :
1305 : Word16 significanceMeasure1_e, significanceMeasure2_e;
1306 : Word16 significanceMeasure_e;
1307 3630 : significanceMeasure1 = L_deposit_h( BASOP_Util_Divide3216_Scale( surrCohToTotalSum, nBands, &significanceMeasure1_e ) );
1308 3630 : significanceMeasure1_e = add( significanceMeasure1_e, sub( surrCohToTotalSum_e, 15 ) );
1309 3630 : significanceMeasure2 = L_deposit_h( BASOP_Util_Divide3232_Scale( Mpy_32_32( surrCohSignificanceCoef, surrCohToTotalTimesDiffSum ), L_add( diffSum, EPSILON_FX ), &significanceMeasure2_e ) );
1310 3630 : significanceMeasure2_e = add( significanceMeasure2_e, sub( surrCohToTotalTimesDiffSum_e, diffSum_e ) );
1311 :
1312 3630 : IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure1, significanceMeasure1_e, significanceMeasure2, significanceMeasure2_e ) > 0 )
1313 : {
1314 3605 : significanceMeasure = significanceMeasure1;
1315 3605 : move32();
1316 3605 : significanceMeasure_e = significanceMeasure1_e;
1317 3605 : move16();
1318 : }
1319 : ELSE
1320 : {
1321 25 : significanceMeasure = significanceMeasure2;
1322 25 : move32();
1323 25 : significanceMeasure_e = significanceMeasure2_e;
1324 25 : move16();
1325 : }
1326 3630 : IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure, significanceMeasure_e, threshold, 0 ) > 0 )
1327 : {
1328 417 : return 1;
1329 : }
1330 : }
1331 :
1332 2172 : return 0;
1333 : }
1334 :
1335 :
1336 : /*-----------------------------------------------------------------------*
1337 : * Local functions
1338 : *-----------------------------------------------------------------------*/
1339 :
1340 41605 : static void combine_freqbands_and_subframes_fx(
1341 : MASA_ENCODER_HANDLE hMasa )
1342 : {
1343 : Word16 i, j, k, m;
1344 : Word16 aziRad, eleRad;
1345 : Word32 x[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1346 : Word32 y[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1347 : Word32 z[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1348 : Word16 x_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1349 : Word16 y_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1350 : Word16 z_e[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1351 : Word32 vecLen;
1352 : Word16 vecLen_e;
1353 : Word32 xSum, ySum, zSum;
1354 : Word16 xSum_e, ySum_e, zSum_e, common_e;
1355 : Word64 xSum_sq, ySum_sq, zSum_sq;
1356 : Word32 energySum;
1357 : Word16 energySum_e;
1358 : Word32 spreadCohSum;
1359 : Word16 spreadCohSum_e;
1360 : Word32 surrCohSum;
1361 : Word16 surrCohSum_e;
1362 : Word32 energyRatioSum;
1363 : Word16 energyRatioSum_e;
1364 : Word16 surrCohTemp;
1365 : Word32 energyRatioTemp;
1366 : Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1367 : Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1368 : Word16 brange[2];
1369 : UWord8 numCodingBands;
1370 : UWord8 numSf;
1371 : UWord8 numDirections;
1372 : MASA_METADATA_HANDLE hMeta;
1373 : UWord8 mergeRatiosOverSubframes;
1374 : UWord8 computeCoherence;
1375 : Word16 exp_diff;
1376 : Word32 L_tmp;
1377 : Word64 W_tmp;
1378 : Word16 q_shift;
1379 :
1380 41605 : numCodingBands = hMasa->config.numCodingBands;
1381 41605 : move16();
1382 41605 : numDirections = hMasa->config.numberOfDirections;
1383 41605 : move16();
1384 41605 : IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
1385 : {
1386 5550 : numSf = 1;
1387 5550 : move16();
1388 : }
1389 : ELSE
1390 : {
1391 36055 : numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
1392 36055 : move16();
1393 : }
1394 41605 : hMeta = &( hMasa->masaMetadata );
1395 :
1396 41605 : mergeRatiosOverSubframes = hMasa->config.mergeRatiosOverSubframes;
1397 41605 : move16();
1398 41605 : test();
1399 41605 : IF( hMasa->config.useCoherence && hMasa->config.coherencePresent )
1400 : {
1401 20604 : computeCoherence = 1;
1402 20604 : move16();
1403 : }
1404 : ELSE
1405 : {
1406 21001 : computeCoherence = 0;
1407 21001 : move16();
1408 : }
1409 :
1410 : /* If metadata subframes are joined then we need all energy to be in the first subframe for combining.
1411 : * This optimizes following computations a bit.
1412 : * Note: If energy is used elsewhere, then this can cause problems and local energy should be used. */
1413 41605 : IF( EQ_16( numSf, 1 ) )
1414 : {
1415 22200 : FOR( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
1416 : {
1417 416250 : FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
1418 : {
1419 399600 : hMasa->data.energy_fx[0][k] = BASOP_Util_Add_Mant32Exp( hMasa->data.energy_fx[0][k], hMasa->data.energy_e[0][k], hMasa->data.energy_fx[j][k], hMasa->data.energy_e[j][k], &hMasa->data.energy_e[0][k] ); // 31-hMasa->data.energy_e[0][k]
1420 399600 : move32();
1421 : }
1422 : }
1423 : }
1424 :
1425 41605 : IF( LE_16( numCodingBands, MAX_REDUCED_NBANDS ) )
1426 : {
1427 : /* reduce metadata *frequency* resolution. time resolution is not touched */
1428 84542 : FOR( i = 0; i < numDirections; i++ )
1429 : {
1430 212303 : FOR( j = 0; j < numSf; j++ ) /* NB: for numSf==1, operates only on first sub-frame */
1431 : {
1432 4143100 : FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
1433 : {
1434 3977376 : aziRad = extract_l( L_shl( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], PI_OVER_180_FX ), Q13 - Q22 ) ); // ((Q22, Q31) -> Q22) >> Q9 -> Q13
1435 3977376 : eleRad = extract_l( L_shl( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], PI_OVER_180_FX ), Q13 - Q22 ) ); // ((Q22, Q31) -> Q22) >> Q9 -> Q13
1436 3977376 : vecLen = Mpy_32_32( hMeta->directional_meta[i].energy_ratio_fx[j][k], hMasa->data.energy_fx[j][k] ); // (Q30, 31-hMasa->data.energy_e[j][k]) -> (31-hMasa->data.energy_e[j][k]) - Q1
1437 :
1438 : /* Need more precision for some DTX cases with low energy frames */
1439 3977376 : W_tmp = W_mult0_32_32( L_mult( getCosWord16( aziRad ), getCosWord16( eleRad ) ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
1440 3977376 : q_shift = W_norm( W_tmp );
1441 3977376 : x[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
1442 3977376 : move32();
1443 3977376 : x_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
1444 3977376 : move16();
1445 :
1446 3977376 : W_tmp = W_mult0_32_32( L_mult0( getSinWord16( aziRad ), getCosWord16( eleRad ) ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
1447 3977376 : q_shift = W_norm( W_tmp );
1448 3977376 : y[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
1449 3977376 : move32();
1450 3977376 : y_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
1451 3977376 : move16();
1452 :
1453 3977376 : W_tmp = W_mult0_32_32( L_mult0( getSinWord16( eleRad ), ONE_IN_Q14 ), vecLen ); // (Q29, (31-hMasa->data.energy_e[j][k]) - Q1) -> (Q59 - hMasa->data.energy_e[j][k])
1454 3977376 : q_shift = W_norm( W_tmp );
1455 3977376 : z[i][j][k] = W_extract_h( W_shl( W_tmp, q_shift ) );
1456 3977376 : move32();
1457 3977376 : z_e[i][j][k] = sub( Q31, add( sub( 59, hMasa->data.energy_e[j][k] ), sub( q_shift, 32 ) ) );
1458 3977376 : move16();
1459 : }
1460 : }
1461 : }
1462 :
1463 84542 : FOR( i = 0; i < numDirections; i++ )
1464 : {
1465 212303 : FOR( j = 0; j < numSf; j++ )
1466 : {
1467 1155432 : FOR( k = 0; k < numCodingBands; k++ )
1468 : {
1469 989708 : brange[0] = hMasa->data.band_mapping[k];
1470 989708 : move16();
1471 989708 : brange[1] = hMasa->data.band_mapping[k + 1];
1472 989708 : move16();
1473 :
1474 989708 : xSum = 0;
1475 989708 : ySum = 0;
1476 989708 : zSum = 0;
1477 989708 : energySum = 0;
1478 989708 : spreadCohSum = 0;
1479 989708 : xSum_e = 0;
1480 989708 : ySum_e = 0;
1481 989708 : zSum_e = 0;
1482 989708 : energySum_e = 0;
1483 989708 : spreadCohSum_e = 0;
1484 989708 : move32();
1485 989708 : move32();
1486 989708 : move32();
1487 989708 : move32();
1488 989708 : move32();
1489 989708 : move16();
1490 989708 : move16();
1491 989708 : move16();
1492 989708 : move16();
1493 989708 : move16();
1494 :
1495 4860002 : FOR( m = brange[0]; m < brange[1]; m++ )
1496 : {
1497 3870294 : xSum = BASOP_Util_Add_Mant32Exp( xSum, xSum_e, x[i][j][m], x_e[i][j][m], &xSum_e ); // xSum_e
1498 3870294 : ySum = BASOP_Util_Add_Mant32Exp( ySum, ySum_e, y[i][j][m], y_e[i][j][m], &ySum_e ); // ySum_e
1499 3870294 : zSum = BASOP_Util_Add_Mant32Exp( zSum, zSum_e, z[i][j][m], z_e[i][j][m], &zSum_e ); // zSum_e
1500 3870294 : energySum = BASOP_Util_Add_Mant32Exp( energySum, energySum_e, hMasa->data.energy_fx[j][m], hMasa->data.energy_e[j][m], &energySum_e ); // energySum_e
1501 : }
1502 989708 : common_e = add( s_max( xSum_e, s_max( ySum_e, zSum_e ) ), 2 ); /*2 is guard bit for addition operations*/
1503 989708 : xSum = L_shr( xSum, sub( common_e, xSum_e ) ); /*common_e*/
1504 989708 : ySum = L_shr( ySum, sub( common_e, ySum_e ) ); /*common_e*/
1505 989708 : zSum = L_shr( zSum, sub( common_e, zSum_e ) ); /*common_e*/
1506 989708 : aziRad = BASOP_util_atan2( ySum, xSum, 0 ); // Q13
1507 989708 : xSum_sq = W_mult0_32_32( xSum, xSum ); // 2 * (31-common_e)
1508 989708 : ySum_sq = W_mult0_32_32( ySum, ySum ); // 2 * (31-common_e)
1509 989708 : zSum_sq = W_mult0_32_32( zSum, zSum ); // 2 * (31-common_e)
1510 989708 : W_tmp = W_add( xSum_sq, ySum_sq ); // 2 * (31-common_e)
1511 989708 : q_shift = W_norm( W_tmp );
1512 989708 : L_tmp = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 * (31-common_e) + (q_shift -32)
1513 989708 : exp_diff = sub( Q31, add( imult1616( 2, sub( 31, common_e ) ), sub( q_shift, 32 ) ) );
1514 989708 : L_tmp = Sqrt32( L_tmp, &exp_diff );
1515 989708 : eleRad = BASOP_util_atan2( zSum, L_tmp, sub( common_e, exp_diff ) ); // Q13
1516 :
1517 989708 : hMeta->directional_meta[i].azimuth_fx[j][k] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, aziRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
1518 989708 : move32();
1519 989708 : hMeta->directional_meta[i].elevation_fx[j][k] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, eleRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
1520 989708 : move32();
1521 :
1522 989708 : W_tmp = W_add( xSum_sq, ySum_sq ); // 2 * (31-common_e)
1523 989708 : W_tmp = W_add( W_tmp, zSum_sq ); // 2 * (31-common_e)
1524 989708 : q_shift = W_norm( W_tmp );
1525 989708 : vecLen = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 * (31-common_e) + (q_shift -32)
1526 989708 : exp_diff = sub( Q31, add( imult1616( 2, sub( 31, common_e ) ), sub( q_shift, 32 ) ) );
1527 989708 : vecLen = Sqrt32( vecLen, &exp_diff );
1528 989708 : vecLen_e = exp_diff;
1529 989708 : move16();
1530 :
1531 1979416 : hMeta->directional_meta[i].energy_ratio_fx[j][k] =
1532 989708 : BASOP_Util_Divide3232_Scale_newton( vecLen, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+vecLen_e-energySum_e*/
1533 989708 : move32();
1534 989708 : exp_diff = add( exp_diff, sub( vecLen_e, energySum_e ) );
1535 1979416 : hMeta->directional_meta[i].energy_ratio_fx[j][k] =
1536 989708 : L_shl( hMeta->directional_meta[i].energy_ratio_fx[j][k], sub( exp_diff, Q1 ) ); // (Q31 - exp_diff ) -> Q30
1537 989708 : move32();
1538 :
1539 989708 : IF( computeCoherence )
1540 : {
1541 2379466 : FOR( m = brange[0]; m < brange[1]; m++ )
1542 : {
1543 1827408 : spreadCohSum = BASOP_Util_Add_Mant32Exp( spreadCohSum, spreadCohSum_e, Mpy_32_16_1( hMasa->data.energy_fx[j][m], hMeta->directional_meta[i].spread_coherence_fx[j][m] ), hMasa->data.energy_e[j][m], &spreadCohSum_e ); // 31-spreadCohSum_e
1544 : }
1545 552058 : hMeta->directional_meta[i].spread_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( spreadCohSum, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+spreadCohSum_e-energySum_e*/
1546 552058 : exp_diff = add( exp_diff, sub( spreadCohSum_e, energySum_e ) );
1547 552058 : move16();
1548 : /* Saturation - LTV fix for values close to 1.0f+ */
1549 552058 : hMeta->directional_meta[i].spread_coherence_fx[j][k] = shl_sat( hMeta->directional_meta[i].spread_coherence_fx[j][k], exp_diff ); // Q15
1550 552058 : move16();
1551 :
1552 552058 : IF( i == 0 )
1553 : {
1554 427914 : surrCohSum = 0;
1555 427914 : surrCohSum_e = 0;
1556 427914 : move32();
1557 427914 : move16();
1558 1833186 : FOR( m = brange[0]; m < brange[1]; m++ )
1559 : {
1560 1405272 : surrCohSum = BASOP_Util_Add_Mant32Exp( surrCohSum, surrCohSum_e, Mpy_32_16_1( hMasa->data.energy_fx[j][m], hMeta->common_meta.surround_coherence_fx[j][m] ), hMasa->data.energy_e[j][m], &surrCohSum_e ); // 31-surrCohSum_e
1561 : }
1562 427914 : hMeta->common_meta.surround_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( surrCohSum, L_add( energySum, EPSILON_FX ), &exp_diff ); /*exp_diff+surrCohSum_e-energySum_e*/
1563 427914 : move16();
1564 427914 : exp_diff = add( exp_diff, sub( surrCohSum_e, energySum_e ) );
1565 : /* Saturation - LTV fix for values close to 1.0f+ */
1566 427914 : hMeta->common_meta.surround_coherence_fx[j][k] = shl_sat( hMeta->common_meta.surround_coherence_fx[j][k], exp_diff ); // Q15
1567 427914 : move16();
1568 : }
1569 : }
1570 :
1571 989708 : IF( i == 0 )
1572 : {
1573 805350 : energy[j][k] = energySum; // 31-energySum_e
1574 805350 : energy_e[j][k] = energySum_e;
1575 805350 : move32();
1576 805350 : move16();
1577 : }
1578 : }
1579 : }
1580 : }
1581 : }
1582 3642 : ELSE IF( mergeRatiosOverSubframes ) /* keep frequency resolution */
1583 : {
1584 5700 : FOR( j = 0; j < numSf; j++ )
1585 : {
1586 114000 : FOR( k = 0; k < numCodingBands; k++ )
1587 : {
1588 109440 : energy[j][k] = hMasa->data.energy_fx[j][k]; // 31-hMasa->data.energy_e[j][k]
1589 109440 : energy_e[j][k] = hMasa->data.energy_e[j][k];
1590 109440 : move32();
1591 109440 : move16();
1592 : }
1593 : }
1594 : }
1595 :
1596 41605 : IF( mergeRatiosOverSubframes )
1597 : {
1598 244114 : FOR( k = 0; k < numCodingBands; k++ )
1599 : {
1600 210663 : energySum = 0;
1601 210663 : move32();
1602 210663 : energySum_e = 0;
1603 210663 : move16();
1604 1053315 : FOR( j = 0; j < numSf; j++ )
1605 : {
1606 842652 : energySum = BASOP_Util_Add_Mant32Exp( energySum, energySum_e, energy[j][k], energy_e[j][k], &energySum_e ); // 31-energySum_e
1607 : }
1608 :
1609 210663 : IF( computeCoherence )
1610 : {
1611 122333 : surrCohSum = 0;
1612 122333 : surrCohSum_e = 0;
1613 122333 : move32();
1614 122333 : move16();
1615 611665 : FOR( j = 0; j < numSf; j++ )
1616 : {
1617 489332 : surrCohSum = BASOP_Util_Add_Mant32Exp( surrCohSum, surrCohSum_e, Mpy_32_16_1( energy[j][k], hMeta->common_meta.surround_coherence_fx[j][k] ), energy_e[j][k], &surrCohSum_e ); // 31-surrCohSum_e
1618 : }
1619 122333 : surrCohTemp = BASOP_Util_Divide3232_Scale( surrCohSum, L_add( energySum, EPSILON_FX ), &exp_diff );
1620 122333 : exp_diff = add( exp_diff, sub( surrCohSum_e, energySum_e ) );
1621 122333 : surrCohTemp = shl_sat( surrCohTemp, exp_diff ); // Q15
1622 :
1623 611665 : FOR( j = 0; j < numSf; j++ )
1624 : {
1625 489332 : hMeta->common_meta.surround_coherence_fx[j][k] = surrCohTemp; // Q15
1626 489332 : move16();
1627 : }
1628 : }
1629 :
1630 459874 : FOR( i = 0; i < numDirections; i++ )
1631 : {
1632 249211 : energyRatioSum = 0;
1633 249211 : energyRatioSum_e = 0;
1634 249211 : move32();
1635 249211 : move16();
1636 1246055 : FOR( j = 0; j < numSf; j++ )
1637 : {
1638 996844 : energyRatioSum = BASOP_Util_Add_Mant32Exp( energyRatioSum, energyRatioSum_e, Mpy_32_32( energy[j][k], hMeta->directional_meta[i].energy_ratio_fx[j][k] ), add( energy_e[j][k], 1 ), &energyRatioSum_e ); // 31-energyRatioSum_e
1639 : }
1640 249211 : energyRatioTemp = BASOP_Util_Divide3232_Scale_newton( energyRatioSum, L_add( energySum, EPSILON_FX ), &exp_diff );
1641 249211 : exp_diff = add( exp_diff, sub( energyRatioSum_e, energySum_e ) );
1642 249211 : energyRatioTemp = L_shl( energyRatioTemp, sub( exp_diff, 1 ) ); // Q30
1643 :
1644 1246055 : FOR( j = 0; j < numSf; j++ )
1645 : {
1646 996844 : hMeta->directional_meta[i].energy_ratio_fx[j][k] = energyRatioTemp; // Q30
1647 996844 : move32();
1648 : }
1649 : }
1650 : }
1651 : }
1652 :
1653 41605 : return;
1654 : }
1655 :
1656 :
1657 : /*-------------------------------------------------------------------*
1658 : * ivas_masa_combine_directions()
1659 : *
1660 : *
1661 : *-------------------------------------------------------------------*/
1662 :
1663 9520 : void ivas_masa_combine_directions_fx(
1664 : MASA_ENCODER_HANDLE hMasa )
1665 : {
1666 : Word16 i, j, k;
1667 : UWord8 numCodingBands;
1668 : UWord8 numSf;
1669 : UWord8 numDirections;
1670 : UWord8 computeCoherence;
1671 : MASA_METADATA_HANDLE hMeta;
1672 :
1673 : Word16 aziRad_fx;
1674 : Word16 eleRad_fx;
1675 : Word32 x_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1676 : Word32 y_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1677 : Word32 z_fx[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1678 : Word32 vecLen_fx;
1679 : Word32 xSum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1680 : Word32 ySum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1681 : Word32 zSum_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1682 : Word32 sumVecLen_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
1683 9520 : Word16 exp_sumVecLen_buff[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], exp_sumVecLen = MIN16B_FLT_FX;
1684 9520 : move16();
1685 : Word32 tempImportance_fx;
1686 : Word32 importance_fx[MASA_FREQUENCY_BANDS];
1687 : Word16 exp_importance;
1688 : Word16 indicesOfLargest[MASA_FREQUENCY_BANDS];
1689 :
1690 : Word32 ratioSum_fx;
1691 : Word32 ambience1dir_fx;
1692 : Word32 ambience2dir_fx;
1693 : Word32 ambienceIncrease_fx;
1694 : Word32 origSurrCohEne_fx;
1695 : Word32 newSurrCohEne_fx;
1696 :
1697 9520 : numCodingBands = hMasa->config.numCodingBands;
1698 9520 : numDirections = hMasa->config.numberOfDirections;
1699 9520 : move16();
1700 9520 : move16();
1701 :
1702 9520 : IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
1703 : {
1704 1800 : numSf = 1;
1705 : }
1706 : ELSE
1707 : {
1708 7720 : numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
1709 : }
1710 9520 : move16();
1711 9520 : hMeta = &( hMasa->masaMetadata );
1712 :
1713 9520 : computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
1714 9520 : move16();
1715 9520 : Word16 azi_cos = 0, azi_sine = 0, ele_cos = 0, ele_sine = 0;
1716 9520 : move16();
1717 9520 : move16();
1718 9520 : move16();
1719 9520 : move16();
1720 28560 : FOR( i = 0; i < numDirections; i++ )
1721 : {
1722 84400 : FOR( j = 0; j < numSf; j++ )
1723 : {
1724 865744 : FOR( k = 0; k < numCodingBands; k++ )
1725 : {
1726 800384 : aziRad_fx = extract_l( L_shr( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], PI_OVER_180_Q25 ), 3 ) ); // (Q22 + Q25 - 31) - 3 = Q13
1727 800384 : azi_cos = getCosWord16( aziRad_fx ); // Q14
1728 800384 : azi_sine = getSinWord16( aziRad_fx ); // Q15
1729 :
1730 800384 : eleRad_fx = extract_l( L_shr( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], PI_OVER_180_Q25 ), 3 ) ); // (Q22 + Q25 - 31) - 3 = Q13
1731 800384 : ele_sine = getSinWord16( eleRad_fx ); // Q15
1732 800384 : ele_cos = getCosWord16( eleRad_fx ); // Q14
1733 :
1734 800384 : vecLen_fx = hMeta->directional_meta[i].energy_ratio_fx[j][k];
1735 800384 : move32();
1736 :
1737 800384 : x_fx[i][j][k] = L_mult0( azi_cos, ele_cos ); // Q14+Q14
1738 800384 : x_fx[i][j][k] = Mpy_32_32( x_fx[i][j][k], vecLen_fx ); // Q28+Q30-31
1739 800384 : y_fx[i][j][k] = L_mult0( azi_sine, ele_cos ); // Q15+Q14
1740 800384 : y_fx[i][j][k] = Mpy_32_32( y_fx[i][j][k], vecLen_fx ); // Q29+Q30-31
1741 800384 : z_fx[i][j][k] = Mpy_32_32( L_deposit_h( ele_sine ), vecLen_fx ); // Q16+Q15+Q30 - 31
1742 800384 : move32();
1743 800384 : move32();
1744 800384 : move32();
1745 800384 : move32();
1746 800384 : move32();
1747 : }
1748 : }
1749 : }
1750 :
1751 : /* Compute sum vector */
1752 42200 : FOR( j = 0; j < numSf; j++ )
1753 : {
1754 432872 : FOR( k = 0; k < numCodingBands; k++ )
1755 : {
1756 400192 : xSum_fx[j][k] = L_add( x_fx[0][j][k], x_fx[1][j][k] ); // Q27
1757 400192 : ySum_fx[j][k] = L_add( y_fx[0][j][k], y_fx[1][j][k] ); // Q28
1758 400192 : zSum_fx[j][k] = L_add( z_fx[0][j][k], z_fx[1][j][k] ); // Q30
1759 400192 : move32();
1760 400192 : move32();
1761 400192 : move32();
1762 :
1763 400192 : Word32 var1 = Mpy_32_32( xSum_fx[j][k], xSum_fx[j][k] ); // Q27 + Q27 - 31 //Q23
1764 400192 : Word32 var2 = Mpy_32_32( ySum_fx[j][k], ySum_fx[j][k] ); // Q28 + Q28 - 31 //Q25
1765 400192 : Word32 var3 = Mpy_32_32( zSum_fx[j][k], zSum_fx[j][k] ); // Q30 + Q30 - 31 //Q29
1766 400192 : Word32 var4 = L_add( L_add( var1, L_shr( var2, 2 ) ), L_shr( var3, 6 ) ); // Q23
1767 400192 : Word16 exp_var4 = 31 - Q23;
1768 400192 : move16();
1769 :
1770 400192 : Word16 exp_var5 = exp_var4;
1771 400192 : move16();
1772 400192 : Word32 var5 = 0;
1773 400192 : move32();
1774 :
1775 400192 : IF( var4 != 0 )
1776 : {
1777 400192 : var5 = Sqrt32( var4, &exp_var5 );
1778 : }
1779 400192 : sumVecLen_fx[j][k] = var5;
1780 400192 : move32();
1781 400192 : exp_sumVecLen_buff[j][k] = exp_var5;
1782 400192 : move16();
1783 : }
1784 : }
1785 :
1786 : /*make commen exp for sumVecLen_fx buffer*/
1787 42200 : FOR( j = 0; j < numSf; j++ )
1788 : {
1789 432872 : FOR( k = 0; k < numCodingBands; k++ )
1790 : {
1791 400192 : exp_sumVecLen = s_max( exp_sumVecLen_buff[j][k], exp_sumVecLen );
1792 : }
1793 : }
1794 :
1795 42200 : FOR( j = 0; j < numSf; j++ )
1796 : {
1797 432872 : FOR( k = 0; k < numCodingBands; k++ )
1798 : {
1799 400192 : sumVecLen_fx[j][k] = L_shr( sumVecLen_fx[j][k], sub( exp_sumVecLen, exp_sumVecLen_buff[j][k] ) );
1800 400192 : move32();
1801 : }
1802 : }
1803 :
1804 : /* Estimate the importance of having two directions instead of one */
1805 : /* Reduced precision of importance_fx intentionally to Q13 to maintatin 0.0001f resolution */
1806 132644 : FOR( i = 0; i < numCodingBands; i++ )
1807 : {
1808 123124 : importance_fx[i] = 0;
1809 123124 : move32();
1810 523316 : FOR( j = 0; j < numSf; j++ )
1811 : {
1812 400192 : tempImportance_fx = L_shr( L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ), Q30 - Q13 ); // Q13
1813 400192 : tempImportance_fx = L_sub( tempImportance_fx, L_shr( sumVecLen_fx[j][i], sub( sub( Q31, exp_sumVecLen ), Q13 ) ) ); // Q13
1814 400192 : importance_fx[i] = L_add( importance_fx[i], tempImportance_fx ); // Q13
1815 400192 : move32();
1816 : }
1817 :
1818 123124 : IF( NE_16( numSf, 1 ) )
1819 : {
1820 92356 : importance_fx[i] = L_shr( importance_fx[i], 2 ); // Q13
1821 92356 : move32();
1822 : }
1823 123124 : importance_fx[i] = Mpy_32_32( importance_fx[i], hMasa->data.importanceWeight_fx[i] ); //(Q13, Q30) -> Q12
1824 123124 : move32();
1825 : }
1826 9520 : exp_importance = Q31 - Q12;
1827 9520 : move16();
1828 :
1829 : /* Determine bands where to use two directions */
1830 9520 : find_n_largest_fx( importance_fx, exp_importance, indicesOfLargest, numCodingBands, hMasa->config.numTwoDirBands );
1831 :
1832 132644 : FOR( i = 0; i < numCodingBands; i++ )
1833 : {
1834 123124 : hMasa->data.twoDirBands[i] = 0;
1835 123124 : move16();
1836 : }
1837 :
1838 31054 : FOR( i = 0; i < hMasa->config.numTwoDirBands; i++ )
1839 : {
1840 21534 : hMasa->data.twoDirBands[indicesOfLargest[i]] = 1;
1841 21534 : move16();
1842 : }
1843 :
1844 : /* Combine directions on the remaining bands */
1845 132644 : FOR( i = 0; i < numCodingBands; i++ )
1846 : {
1847 123124 : IF( hMasa->data.twoDirBands[i] == 0 )
1848 : {
1849 430178 : FOR( j = 0; j < numSf; j++ )
1850 : {
1851 328588 : aziRad_fx = BASOP_util_atan2( ySum_fx[j][i], xSum_fx[j][i], Q27 - Q28 ); // Q13
1852 328588 : Word32 tmp1 = Mpy_32_32( xSum_fx[j][i], xSum_fx[j][i] ); // Q27+Q27-31 //Q23
1853 328588 : Word32 tmp2 = Mpy_32_32( ySum_fx[j][i], ySum_fx[j][i] ); // Q28+Q28-31 //Q25
1854 328588 : Word32 tmp3 = L_add( tmp1, L_shr( tmp2, 2 ) ); // Q23
1855 328588 : Word16 exp_tmp3 = 31 - Q23;
1856 328588 : move16();
1857 328588 : Word32 tmp4 = Sqrt32( tmp3, &exp_tmp3 );
1858 328588 : eleRad_fx = BASOP_util_atan2( zSum_fx[j][i], tmp4, sub( sub( 31, Q30 ), exp_tmp3 ) );
1859 :
1860 328588 : Word16 exp_tmp5 = 0;
1861 328588 : move16();
1862 328588 : Word16 tmp5 = BASOP_Util_Divide1616_Scale( aziRad_fx, EVS_PI_FX, &exp_tmp5 );
1863 328588 : Word16 Q_tmp6 = 0;
1864 328588 : move16();
1865 328588 : Word32 tmp6 = L_mult( tmp5, 23040 /*180.0f in Q7*/ );
1866 328588 : Q_tmp6 = sub( 31, add( exp_tmp5, 8 ) );
1867 :
1868 328588 : Word16 exp_tmp7 = 0;
1869 328588 : move16();
1870 328588 : Word16 tmp7 = BASOP_Util_Divide1616_Scale( eleRad_fx, EVS_PI_FX, &exp_tmp7 );
1871 328588 : Word16 Q_tmp8 = 0;
1872 328588 : move16();
1873 328588 : Word32 tmp8 = L_mult( tmp7, 23040 /*180.0f in Q7*/ );
1874 328588 : Q_tmp8 = sub( 31, add( exp_tmp7, 8 ) );
1875 :
1876 328588 : Scale_sig32( &tmp6, 1, Q22 - Q_tmp6 );
1877 328588 : Scale_sig32( &tmp8, 1, Q22 - Q_tmp8 );
1878 :
1879 328588 : hMeta->directional_meta[0].azimuth_fx[j][i] = tmp6; // Q22
1880 328588 : hMeta->directional_meta[0].elevation_fx[j][i] = tmp8; // Q22
1881 328588 : move32();
1882 328588 : move32();
1883 328588 : ratioSum_fx = L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ); // Q30
1884 328588 : IF( computeCoherence )
1885 : {
1886 127198 : Word32 var1 = Mpy_32_16_1( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[0].spread_coherence_fx[j][i] );
1887 127198 : Word32 var2 = Mpy_32_16_1( hMeta->directional_meta[1].energy_ratio_fx[j][i], hMeta->directional_meta[1].spread_coherence_fx[j][i] );
1888 127198 : Word32 var3 = L_add( var1, var2 ); // Q30
1889 127198 : Word16 exp_var4 = 0;
1890 127198 : move16();
1891 127198 : Word32 var4 = BASOP_Util_Add_Mant32Exp( ratioSum_fx, 31 - Q30, EPSILON_FX_M, EPSILON_FX_E, &exp_var4 );
1892 127198 : Word16 exp_var5 = 0;
1893 127198 : move16();
1894 127198 : Word16 var5 = BASOP_Util_Divide3232_Scale( var3, var4, &exp_var5 );
1895 127198 : exp_var5 = add( exp_var5, ( sub( sub( 31, Q30 ), exp_var4 ) ) );
1896 127198 : Scale_sig( &var5, 1, sub( Q15, sub( 15, exp_var5 ) ) );
1897 127198 : hMeta->directional_meta[0].spread_coherence_fx[j][i] = var5; // Q15
1898 127198 : move16();
1899 : }
1900 :
1901 328588 : ambience2dir_fx = L_sub( ONE_IN_Q30, ratioSum_fx ); // Q30
1902 328588 : Word32 ambience2dir_fx_by_2 = L_shr( ambience2dir_fx, 1 );
1903 328588 : Word32 var_a = L_add( L_add( hMeta->directional_meta[0].energy_ratio_fx[j][i], hMeta->directional_meta[1].energy_ratio_fx[j][i] ), ambience2dir_fx_by_2 ); // Q30
1904 328588 : Word16 exp_var_b = 0;
1905 328588 : move16();
1906 328588 : Word16 var_b = BASOP_Util_Divide3232_Scale( sumVecLen_fx[j][i], var_a, &exp_var_b );
1907 328588 : exp_var_b = add( exp_var_b, sub( exp_sumVecLen, 1 ) );
1908 328588 : Word32 var_b_32 = L_deposit_h( var_b );
1909 328588 : hMeta->directional_meta[0].energy_ratio_fx[j][i] = L_shr( var_b_32, 1 - exp_var_b ); // Q30
1910 328588 : hMeta->directional_meta[1].energy_ratio_fx[j][i] = 0; // Q30
1911 328588 : move16();
1912 328588 : move16();
1913 328588 : hMeta->common_meta.diffuse_to_total_ratio_fx[j][i] = L_sub( ONE_IN_Q30, hMeta->directional_meta[0].energy_ratio_fx[j][i] ); // Q30
1914 :
1915 328588 : IF( computeCoherence )
1916 : {
1917 127198 : ambience1dir_fx = L_sub( ONE_IN_Q30, hMeta->directional_meta[0].energy_ratio_fx[j][i] ); // Q30
1918 127198 : ambienceIncrease_fx = L_max( L_sub( ambience1dir_fx, ambience2dir_fx ), 0 ); // Q30
1919 127198 : origSurrCohEne_fx = Mpy_32_16_1( ambience2dir_fx /*Q30*/, hMeta->common_meta.surround_coherence_fx[j][i] /*Q15*/ ); // Q30
1920 127198 : newSurrCohEne_fx = Mpy_32_16_1( ambienceIncrease_fx /*Q30*/, hMeta->directional_meta[0].spread_coherence_fx[j][i] /*Q15*/ ); // Q30
1921 :
1922 127198 : Word16 exp_y = 0, exp_z = 0;
1923 127198 : move16();
1924 127198 : move16();
1925 127198 : Word32 x = L_add( origSurrCohEne_fx, newSurrCohEne_fx ); // Q30
1926 127198 : Word32 y = BASOP_Util_Add_Mant32Exp( ambience1dir_fx, 1, EPSILON_FX_M, EPSILON_FX_E, &exp_y );
1927 127198 : Word16 z = BASOP_Util_Divide3232_Scale( x, y, &exp_z );
1928 127198 : exp_z = add( exp_z, ( sub( 31 - Q30, exp_y ) ) );
1929 127198 : z = shl_sat( z, exp_z ); // Q15
1930 127198 : hMeta->common_meta.surround_coherence_fx[j][i] = s_min( MAX16B, z );
1931 127198 : move16();
1932 : }
1933 : }
1934 : }
1935 : }
1936 :
1937 9520 : return;
1938 : }
1939 :
1940 9520 : static void find_n_largest_fx(
1941 : const Word32 *input_fx, // Q(31 - exp_input)
1942 : Word16 exp_input,
1943 : Word16 *largestIndices,
1944 : const Word16 numElements,
1945 : const Word16 numLargest )
1946 : {
1947 : Word16 i, j;
1948 : Word32 largestValue;
1949 : Word16 largestIndex;
1950 : Word32 values[MASA_FREQUENCY_BANDS];
1951 :
1952 132644 : FOR( j = 0; j < numElements; j++ )
1953 : {
1954 123124 : values[j] = input_fx[j]; // Q(31 - exp_input)
1955 123124 : move32();
1956 : }
1957 :
1958 31054 : FOR( i = 0; i < numLargest; i++ )
1959 : {
1960 21534 : largestValue = values[0]; // Q(31 - exp_input)
1961 21534 : move32();
1962 21534 : largestIndex = 0;
1963 21534 : move16();
1964 342038 : FOR( j = 1; j < numElements; j++ )
1965 : {
1966 320504 : IF( GT_32( values[j], largestValue ) )
1967 : {
1968 41074 : largestValue = values[j]; // Q(31 - exp_input)
1969 41074 : largestIndex = j;
1970 41074 : move32();
1971 41074 : move16();
1972 : }
1973 : }
1974 21534 : largestIndices[i] = largestIndex;
1975 21534 : move16();
1976 21534 : IF( exp_input != 0 )
1977 : {
1978 21534 : values[largestIndex] = L_negate( 1 << ( sub( 31, exp_input ) ) ); // Q(31 - exp_input)
1979 21534 : move32();
1980 : }
1981 : ELSE
1982 : {
1983 0 : values[largestIndex] = 1 << ( sub( 31, exp_input ) ); // Q(31 - exp_input)
1984 0 : move32();
1985 : }
1986 : }
1987 :
1988 9520 : return;
1989 : }
1990 :
1991 41605 : static void move_metadata_to_qmetadata_fx(
1992 : const MASA_ENCODER_HANDLE hMasa,
1993 : IVAS_QMETADATA_HANDLE hQMeta )
1994 : {
1995 : Word16 dir, sf, band;
1996 : UWord8 numCodingBands;
1997 : UWord8 numDirections;
1998 : UWord8 numSf;
1999 : MASA_METADATA_HANDLE hMeta;
2000 :
2001 41605 : numCodingBands = hMasa->config.numCodingBands;
2002 41605 : numDirections = hMasa->config.numberOfDirections;
2003 41605 : move16();
2004 41605 : move16();
2005 41605 : move16();
2006 41605 : numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
2007 41605 : if ( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
2008 : {
2009 5550 : numSf = 1;
2010 5550 : move16();
2011 : }
2012 41605 : hMeta = &( hMasa->masaMetadata );
2013 :
2014 89046 : FOR( dir = 0; dir < numDirections; dir++ )
2015 : {
2016 217567 : FOR( sf = 0; sf < numSf; sf++ )
2017 : {
2018 1526120 : FOR( band = 0; band < numCodingBands; band++ )
2019 : {
2020 1355994 : hQMeta->q_direction[dir].band_data[band].azimuth_fx[sf] = hMeta->directional_meta[dir].azimuth_fx[sf][band]; // Q22
2021 1355994 : hQMeta->q_direction[dir].band_data[band].elevation_fx[sf] = hMeta->directional_meta[dir].elevation_fx[sf][band]; // Q22
2022 1355994 : hQMeta->q_direction[dir].band_data[band].energy_ratio_fx[sf] = hMeta->directional_meta[dir].energy_ratio_fx[sf][band]; // Q30
2023 1355994 : hQMeta->q_direction[dir].band_data[band].spherical_index[sf] = hMeta->directional_meta[dir].spherical_index[sf][band];
2024 1355994 : move32();
2025 1355994 : move32();
2026 1355994 : move32();
2027 1355994 : move16();
2028 :
2029 1355994 : IF( hQMeta->q_direction[dir].coherence_band_data != NULL )
2030 : {
2031 990540 : hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = (UWord8) mult_r( hMeta->directional_meta[dir].spread_coherence_fx[sf][band], UINT8_MAX ); // Q15
2032 990540 : move16();
2033 : }
2034 : }
2035 : }
2036 : }
2037 :
2038 191375 : FOR( sf = 0; sf < numSf; sf++ )
2039 : {
2040 1280362 : FOR( band = 0; band < numCodingBands; band++ )
2041 : {
2042 1130592 : IF( hQMeta->surcoh_band_data != NULL )
2043 : {
2044 765138 : hQMeta->surcoh_band_data[band].surround_coherence[sf] = (UWord8) mult_r( hMeta->common_meta.surround_coherence_fx[sf][band], UINT8_MAX ); // Q15
2045 765138 : move16();
2046 : }
2047 : }
2048 : }
2049 :
2050 41605 : IF( GT_16( numDirections, 1 ) )
2051 : {
2052 75232 : FOR( band = 0; band < numCodingBands; band++ )
2053 : {
2054 69396 : hQMeta->twoDirBands[band] = hMasa->data.twoDirBands[band];
2055 69396 : move16();
2056 : }
2057 5836 : hQMeta->numTwoDirBands = hMasa->config.numTwoDirBands;
2058 5836 : move16();
2059 : }
2060 :
2061 : /* Copy spread coherence for DCT-based coding */
2062 41605 : test();
2063 41605 : IF( EQ_16( numSf, 1 ) && hMasa->config.useCoherence )
2064 : {
2065 6620 : FOR( dir = 0; dir < numDirections; dir++ )
2066 : {
2067 15232 : FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2068 : {
2069 200268 : FOR( band = 0; band < numCodingBands; band++ )
2070 : {
2071 188844 : hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[sf] = hQMeta->q_direction[dir].coherence_band_data[band].spread_coherence[0];
2072 188844 : move16();
2073 : }
2074 : }
2075 : }
2076 : }
2077 :
2078 41605 : return;
2079 : }
2080 :
2081 :
2082 : /* This function studies parametric MASA metadata to provide information for codec configuration */
2083 39626 : static void detect_metadata_composition_fx(
2084 : const MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder data */
2085 : UWord8 *joinedSubframes, /* o : Result of subframe composition */
2086 : UWord8 *coherencePresent, /* o : Result of coherence presence */
2087 : UWord8 *isTwoDir /* o : Result of two direction check */
2088 : )
2089 : {
2090 : MASA_METADATA_FRAME *hMeta;
2091 : Word8 sf, band, dir, numDir;
2092 : Word16 nSubFrames;
2093 39626 : UWord8 dirValid[2] = { FALSE, FALSE };
2094 39626 : UWord8 cohPresent = FALSE;
2095 39626 : UWord8 sfDiffer = FALSE;
2096 : UWord8 sfSimilar;
2097 39626 : move16(); /*dirValid[0]*/
2098 39626 : move16(); /*dirValid[1]*/
2099 39626 : move16(); /*cohPresent*/
2100 39626 : move16(); /*sfDiffer*/
2101 :
2102 39626 : hMeta = &( hMasa->masaMetadata );
2103 39626 : numDir = (Word8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
2104 39626 : move16();
2105 :
2106 39626 : *isTwoDir = FALSE;
2107 39626 : move16();
2108 :
2109 : /* First check for valid two directions */
2110 39626 : IF( EQ_16( numDir, 1 ) )
2111 : {
2112 29726 : dirValid[0] = TRUE;
2113 29726 : move16();
2114 : }
2115 : ELSE
2116 : {
2117 : /* Default assumption */
2118 9900 : *isTwoDir = TRUE;
2119 9900 : move16();
2120 :
2121 : /* Check for direct-to-total ratio values */
2122 29700 : FOR( dir = 0; dir < numDir; dir++ )
2123 : {
2124 19800 : sf = 0;
2125 19800 : move16();
2126 39600 : WHILE( !dirValid[dir] && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) )
2127 : {
2128 19800 : test();
2129 19800 : band = 0;
2130 19800 : move16();
2131 39600 : WHILE( !dirValid[dir] && ( band < MASA_FREQUENCY_BANDS ) )
2132 : {
2133 19800 : test();
2134 19800 : IF( GE_32( hMeta->directional_meta[dir].energy_ratio_fx[sf][band] /*q30*/, MASA_RATIO_THRESHOLD_FX >> 1 /*q30*/ ) )
2135 : {
2136 19800 : dirValid[dir] = TRUE;
2137 19800 : move16();
2138 : }
2139 19800 : band = (Word8) add( band, 1 );
2140 : }
2141 19800 : sf = (Word8) add( sf, 1 );
2142 : }
2143 : }
2144 :
2145 9900 : test();
2146 9900 : IF( dirValid[1] == FALSE )
2147 : {
2148 : /* This handles also case where both are false. Then we just use first dir metadata. */
2149 0 : *isTwoDir = FALSE;
2150 0 : move16();
2151 : }
2152 9900 : ELSE IF( dirValid[0] == FALSE && EQ_16( dirValid[1], TRUE ) )
2153 : {
2154 0 : *isTwoDir = FALSE;
2155 0 : move16();
2156 : /* Copy data to first direction */
2157 0 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2158 : {
2159 0 : FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
2160 : {
2161 0 : hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band];
2162 0 : move16();
2163 0 : hMeta->directional_meta[0].azimuth_fx[sf][band] = hMeta->directional_meta[1].azimuth_fx[sf][band]; /*q22*/
2164 0 : hMeta->directional_meta[0].elevation_fx[sf][band] = hMeta->directional_meta[1].elevation_fx[sf][band]; /*q22*/
2165 0 : hMeta->directional_meta[0].energy_ratio_fx[sf][band] = hMeta->directional_meta[1].energy_ratio_fx[sf][band]; /*q30*/
2166 0 : hMeta->directional_meta[0].spread_coherence_fx[sf][band] = hMeta->directional_meta[1].spread_coherence_fx[sf][band]; /*q15*/
2167 0 : move32();
2168 0 : move16();
2169 0 : move16();
2170 0 : move16();
2171 : }
2172 : }
2173 : }
2174 :
2175 9900 : if ( *isTwoDir == FALSE )
2176 : {
2177 : /* Further checks will be done with just one direction */
2178 0 : numDir = 1;
2179 0 : move16();
2180 : }
2181 : }
2182 :
2183 : /* Check if data over subframes is identical. Check is done by comparing to first subframe. */
2184 39626 : sfSimilar = TRUE;
2185 39626 : sf = 1;
2186 39626 : move16();
2187 39626 : move16();
2188 :
2189 39626 : test();
2190 90352 : WHILE( ( sfSimilar == TRUE ) && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) )
2191 : {
2192 50726 : sfSimilar = are_masa_subframes_similar_fx( hMeta, 0, hMeta, sf );
2193 50726 : sf = (Word8) add( sf, 1 );
2194 50726 : move16();
2195 : }
2196 39626 : IF( sfSimilar == TRUE )
2197 5550 : sfDiffer = FALSE;
2198 : ELSE
2199 34076 : sfDiffer = TRUE;
2200 39626 : move16();
2201 :
2202 : /* Further checks can be done with just one subframe if they are identical */
2203 39626 : IF( EQ_16( sfDiffer, TRUE ) )
2204 34076 : nSubFrames = MAX_PARAM_SPATIAL_SUBFRAMES;
2205 : ELSE
2206 5550 : nSubFrames = 1;
2207 39626 : move16();
2208 :
2209 : /* Check spread coherence */
2210 39626 : dir = 0;
2211 39626 : move16();
2212 39626 : test();
2213 79252 : WHILE( cohPresent == FALSE && ( dir < numDir ) )
2214 : {
2215 39626 : sf = 0;
2216 39626 : move16();
2217 39626 : test();
2218 82138 : WHILE( cohPresent == FALSE && ( sf < nSubFrames ) )
2219 : {
2220 42512 : band = 0;
2221 42512 : move16();
2222 42512 : test();
2223 277843 : WHILE( cohPresent == FALSE /*has value zero*/ && ( band < MASA_FREQUENCY_BANDS ) )
2224 : {
2225 : /* Check coherences for presence of coherence */
2226 235331 : IF( GT_16( hMeta->directional_meta[dir].spread_coherence_fx[sf][band] /*Q15*/, MASA_COHERENCE_THRESHOLD_FX >> 16 ) ) /*Q15*/
2227 : {
2228 37829 : cohPresent = TRUE;
2229 37829 : move16();
2230 : }
2231 235331 : band = (Word8) add( band, 1 );
2232 235331 : move16();
2233 : }
2234 42512 : sf = (Word8) add( sf, 1 );
2235 42512 : move16();
2236 : }
2237 39626 : dir = (Word8) add( dir, 1 );
2238 39626 : move16();
2239 : }
2240 :
2241 : /* Check surround coherence separately if we do not have already knowledge of coherence */
2242 39626 : IF( cohPresent == FALSE )
2243 : {
2244 : Word32 surround_coherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
2245 : Word32 diffuse_to_total_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
2246 : Word16 i, j;
2247 8985 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
2248 : {
2249 179700 : FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ )
2250 : {
2251 172512 : surround_coherence_fx[i][j] = L_deposit_h( hMeta->common_meta.surround_coherence_fx[i][j] ); /*q31*/
2252 172512 : diffuse_to_total_ratio_fx[i][j] = L_shl_sat( hMeta->common_meta.diffuse_to_total_ratio_fx[i][j], 1 ); /*q31*/
2253 : }
2254 : }
2255 1797 : cohPresent = ivas_masa_surrcoh_signicant_fx( surround_coherence_fx, diffuse_to_total_ratio_fx, nSubFrames, MASA_FREQUENCY_BANDS );
2256 : }
2257 :
2258 : /* Set output flags */
2259 39626 : IF( EQ_16( sfDiffer, TRUE ) )
2260 : {
2261 34076 : *joinedSubframes = FALSE;
2262 : }
2263 : ELSE
2264 : {
2265 5550 : *joinedSubframes = TRUE;
2266 : }
2267 39626 : move16();
2268 39626 : *coherencePresent = cohPresent;
2269 39626 : move16();
2270 :
2271 39626 : return;
2272 : }
2273 :
2274 :
2275 : /* Check and compensate energy ratios. This function verifies that energy ratios follow the principle of summing to one.
2276 : * In addition, it implements simple remainder-to-total handling where remainder energy is proportionally added to other
2277 : * ratios. */
2278 39626 : static void compensate_energy_ratios_fx(
2279 : MASA_ENCODER_HANDLE hMasa )
2280 : {
2281 : Word16 sf, band, dir;
2282 : Word32 ratioSum;
2283 : MASA_METADATA_HANDLE hMeta;
2284 : UWord8 numDirs;
2285 :
2286 39626 : hMeta = &( hMasa->masaMetadata );
2287 39626 : numDirs = hMasa->config.numberOfDirections;
2288 39626 : move16();
2289 :
2290 198130 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2291 : {
2292 3962600 : FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
2293 : {
2294 : /* Remainder is always set to zero and energy removal is compensated in following steps
2295 : * to other ratios. */
2296 3804096 : hMeta->common_meta.remainder_to_total_ratio_fx[sf][band] = 0; // Q30
2297 3804096 : move32();
2298 :
2299 3804096 : ratioSum = 0;
2300 3804096 : move32();
2301 8558592 : FOR( dir = 0; dir < numDirs; dir++ )
2302 : {
2303 4754496 : ratioSum = L_add( ratioSum, hMeta->directional_meta[dir].energy_ratio_fx[sf][band] ); // Q30
2304 : }
2305 3804096 : ratioSum = L_add( ratioSum, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] ); // Q30
2306 :
2307 3804096 : IF( ratioSum == 0 )
2308 : {
2309 0 : FOR( dir = 0; dir < numDirs; dir++ )
2310 : {
2311 0 : hMeta->directional_meta[dir].energy_ratio_fx[sf][band] = 0; // Q30
2312 0 : move32();
2313 : }
2314 0 : hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = ONE_IN_Q30; // Q30
2315 0 : move32();
2316 : }
2317 : // ELSE IF( NE_32( ratioSum, ONE_IN_Q30 ) )
2318 : ELSE /* Removing the check against 1 works well!!! */
2319 : {
2320 : Word16 exp_diff;
2321 8558592 : FOR( dir = 0; dir < numDirs; dir++ )
2322 : {
2323 9508992 : hMeta->directional_meta[dir].energy_ratio_fx[sf][band] =
2324 4754496 : BASOP_Util_Divide3232_Scale_newton( hMeta->directional_meta[dir].energy_ratio_fx[sf][band], ratioSum, &exp_diff );
2325 4754496 : move32();
2326 4754496 : hMeta->directional_meta[dir].energy_ratio_fx[sf][band] = L_shl( hMeta->directional_meta[dir].energy_ratio_fx[sf][band], sub( exp_diff, Q1 ) ); // Q30
2327 4754496 : move32();
2328 : }
2329 7608192 : hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] =
2330 3804096 : BASOP_Util_Divide3232_Scale_newton( hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band], ratioSum, &exp_diff );
2331 3804096 : move32();
2332 3804096 : hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = L_shl( hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band], sub( exp_diff, Q1 ) ); // Q30
2333 3804096 : move32();
2334 : }
2335 : }
2336 : }
2337 :
2338 39626 : return;
2339 : }
2340 :
2341 :
2342 : /* 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 */
2343 25011 : static void reduce_metadata_further_fx(
2344 : MASA_ENCODER_HANDLE hMasa,
2345 : IVAS_QMETADATA_HANDLE hqmetadata,
2346 : const IVAS_FORMAT ivas_format )
2347 : {
2348 : Word16 sf;
2349 : Word16 band;
2350 : Word16 selectedBand;
2351 : Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][LOWBITRATE_NUM_BANDS];
2352 : Word64 W_tmp;
2353 : Word32 totalEnergySum;
2354 : UWord8 numCodingBands;
2355 : UWord8 computeCoherence;
2356 : Word32 onset_filter;
2357 : Word16 onset_filter_e, exp;
2358 : Word64 bandEnergy;
2359 : Word32 bandEnergy32;
2360 : Word16 bandEnergy_exp, shift;
2361 : UWord8 mergeOverFreqBands;
2362 : Word32 meanRatio;
2363 : Word16 tmp, tmp2, q_totalEnergySum;
2364 :
2365 25011 : numCodingBands = hMasa->config.numCodingBands;
2366 25011 : test();
2367 25011 : computeCoherence = hMasa->config.useCoherence && hMasa->config.coherencePresent;
2368 25011 : move16();
2369 25011 : move16();
2370 :
2371 : /* Set default values */
2372 25011 : selectedBand = 0;
2373 25011 : mergeOverFreqBands = 0;
2374 25011 : move16();
2375 25011 : move16();
2376 :
2377 : /* Get energy for the input data in 4-subframe, 5-band format */
2378 25011 : W_tmp = 0;
2379 25011 : move64();
2380 25011 : test();
2381 25011 : IF( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MASA_ISM_FORMAT ) ) /* Energy data is in 4-subframe, 24-band format */
2382 : {
2383 84280 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2384 : {
2385 : Word16 brange[2];
2386 : Word32 eneSum;
2387 : Word16 m;
2388 :
2389 404544 : FOR( band = 0; band < numCodingBands; band++ )
2390 : {
2391 337120 : brange[0] = hMasa->data.band_mapping[band];
2392 337120 : brange[1] = hMasa->data.band_mapping[band + 1];
2393 337120 : move16();
2394 337120 : move16();
2395 :
2396 337120 : eneSum = 0;
2397 337120 : move32();
2398 1949840 : FOR( m = brange[0]; m < brange[1]; m++ )
2399 : {
2400 1612720 : eneSum = L_add( eneSum, hMasa->data.energy_fx[sf][m] ); // hMasa->data.q_energy
2401 : }
2402 337120 : energy[sf][band] = eneSum; // hMasa->data.q_energy
2403 337120 : move32();
2404 337120 : W_tmp = W_add( W_tmp, eneSum ); // hMasa->data.q_energy
2405 : }
2406 : }
2407 : }
2408 : ELSE /* Energy data is already in 4-subframe, 5-band format */
2409 : {
2410 40775 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2411 : {
2412 195720 : FOR( band = 0; band < numCodingBands; band++ )
2413 : {
2414 163100 : energy[sf][band] = hMasa->data.energy_fx[sf][band]; // hMasa->data.q_energy
2415 163100 : move32();
2416 163100 : W_tmp = W_add( W_tmp, energy[sf][band] ); // hMasa->data.q_energy
2417 : }
2418 : }
2419 : }
2420 :
2421 25011 : IF( W_tmp != 0 )
2422 : {
2423 25011 : tmp2 = sub( W_norm( W_tmp ), 1 ); // Usage of guard bits to avoid the large values of onset_detector in multiplication
2424 : }
2425 : ELSE
2426 : {
2427 0 : tmp2 = 0;
2428 0 : move16();
2429 : }
2430 :
2431 25011 : tmp2 = s_min( 32, tmp2 );
2432 25011 : totalEnergySum = W_extract_h( W_shl( W_tmp, tmp2 ) );
2433 25011 : tmp2 = sub( tmp2, 32 );
2434 25011 : q_totalEnergySum = add( hMasa->data.q_energy, tmp2 );
2435 :
2436 : /* Determine onsets */
2437 25011 : hMasa->data.onset_detector_1_fx = Mpy_32_32( hMasa->data.onset_detector_1_fx, LOWBITRATE_ONSET_ALPHA_Q31 );
2438 25011 : move32();
2439 :
2440 25011 : tmp = hMasa->data.q_onset_detector;
2441 25011 : move16();
2442 25011 : IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.onset_detector_1_fx, sub( 31, hMasa->data.q_onset_detector ), totalEnergySum, sub( 31, q_totalEnergySum ) ) < 0 )
2443 : {
2444 24488 : hMasa->data.onset_detector_1_fx = totalEnergySum; // hMasa->data.q_energy
2445 24488 : hMasa->data.q_onset_detector = add( hMasa->data.q_energy, tmp2 );
2446 24488 : move32();
2447 24488 : move16();
2448 :
2449 24488 : shift = norm_l( hMasa->data.onset_detector_2_fx );
2450 24488 : hMasa->data.onset_detector_2_fx = L_shl( hMasa->data.onset_detector_2_fx, shift );
2451 24488 : move32();
2452 24488 : tmp = add( tmp, shift );
2453 : }
2454 25011 : IF( LT_16( tmp, hMasa->data.q_onset_detector ) )
2455 : {
2456 234 : hMasa->data.onset_detector_1_fx = L_shr( hMasa->data.onset_detector_1_fx, sub( hMasa->data.q_onset_detector, tmp ) ); // tmp
2457 234 : hMasa->data.onset_detector_2_fx = L_add( Mpy_32_32( LOWBITRATE_ONSET_BETA_Q31, hMasa->data.onset_detector_2_fx ), Mpy_32_32( ( ONE_IN_Q31 - LOWBITRATE_ONSET_BETA_Q31 ), hMasa->data.onset_detector_1_fx ) ); // tmp
2458 234 : hMasa->data.q_onset_detector = tmp;
2459 234 : move32();
2460 234 : move32();
2461 234 : move16();
2462 : }
2463 : ELSE
2464 : {
2465 24777 : hMasa->data.onset_detector_2_fx = L_add( L_shr( Mpy_32_32( LOWBITRATE_ONSET_BETA_Q31, hMasa->data.onset_detector_2_fx ), sub( tmp, hMasa->data.q_onset_detector ) ), Mpy_32_32( ( ONE_IN_Q31 - LOWBITRATE_ONSET_BETA_Q31 ), hMasa->data.onset_detector_1_fx ) ); // hMasa->data.q_onset_detector
2466 24777 : move32();
2467 : }
2468 25011 : hMasa->data.onset_detector_2_fx = L_shl( Mpy_32_32( LOWBITRATE_ONSET_GAIN_Q30, L_min( hMasa->data.onset_detector_1_fx, hMasa->data.onset_detector_2_fx ) ), 1 ); // hMasa->data.q_onset_detector
2469 25011 : move32();
2470 :
2471 25011 : IF( hMasa->data.onset_detector_1_fx != 0 )
2472 : {
2473 25011 : onset_filter = L_max( BASOP_Util_Divide3232_Scale_newton( hMasa->data.onset_detector_2_fx, hMasa->data.onset_detector_1_fx, &onset_filter_e ), 0 );
2474 :
2475 25011 : IF( BASOP_Util_Cmp_Mant32Exp( onset_filter, onset_filter_e, ONE_IN_Q31, 0 ) > 0 )
2476 : {
2477 19273 : onset_filter = ONE_IN_Q31;
2478 19273 : onset_filter_e = 0;
2479 19273 : move32();
2480 19273 : move16();
2481 : }
2482 : }
2483 : ELSE
2484 : {
2485 0 : onset_filter = ONE_IN_Q31;
2486 0 : onset_filter_e = 0;
2487 0 : move32();
2488 0 : move16();
2489 : }
2490 : /* If we have onset, continue checking if we should reduce in frequency instead of time. */
2491 25011 : IF( BASOP_Util_Cmp_Mant32Exp( onset_filter, onset_filter_e, 2126008812 /* 0.99f in Q31 */, 0 ) < 0 )
2492 : {
2493 : /* Determine one frequency band to use to represent all frequency bands */
2494 23519 : FOR( band = numCodingBands - 1; band >= 0; band-- )
2495 : {
2496 : Word32 threshold;
2497 : Word32 bandRatio;
2498 :
2499 : // threshold = totalEnergySum / ( MAX_PARAM_SPATIAL_SUBFRAMES * LOWBITRATE_NUM_BANDS ) * 0.5f; /* Average energy multiplied with energy ratio of 0.5f */
2500 23440 : threshold = BASOP_Util_Divide3232_Scale_newton( totalEnergySum, ( MAX_PARAM_SPATIAL_SUBFRAMES * LOWBITRATE_NUM_BANDS ) * 2, &exp ); /* Average energy multiplied with energy ratio of 0.5f */
2501 23440 : exp = add( exp, sub( sub( 31, add( hMasa->data.q_energy, tmp2 ) ), 31 ) );
2502 23440 : bandRatio = hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[0]; // Q30
2503 23440 : move32();
2504 :
2505 23440 : bandEnergy = 0;
2506 23440 : move64();
2507 117200 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2508 : {
2509 93760 : bandEnergy = W_mac_32_32( bandEnergy, energy[sf][band], 1 );
2510 : }
2511 23440 : shift = W_norm( bandEnergy );
2512 23440 : bandEnergy32 = W_extract_h( W_shl( bandEnergy, shift ) );
2513 23440 : bandEnergy_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
2514 :
2515 23440 : IF( BASOP_Util_Cmp_Mant32Exp( Mpy_32_32( L_shr( bandEnergy32, 2 ), bandRatio ), add( 1, bandEnergy_exp ), threshold, exp ) > 0 )
2516 : {
2517 5600 : selectedBand = band;
2518 5600 : move16();
2519 5600 : BREAK;
2520 : }
2521 : }
2522 :
2523 : /* Determine if to merge over frequency instead of time */
2524 5679 : W_tmp = 0;
2525 5679 : move64();
2526 28395 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2527 : {
2528 136296 : FOR( band = 0; band < numCodingBands; band++ )
2529 : {
2530 113580 : W_tmp = W_mac_32_16( W_tmp, Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ), 1 ); // hMasa->data.q_energy
2531 : }
2532 : }
2533 5679 : shift = W_norm( W_tmp );
2534 5679 : meanRatio = W_extract_h( W_shl( W_tmp, shift ) ); // Q:sub( add( hMasa->data.q_energy, shift ), 32 )
2535 5679 : shift = sub( 31, sub( add( hMasa->data.q_energy, shift ), 32 ) );
2536 :
2537 5679 : IF( totalEnergySum != 0 )
2538 : {
2539 5679 : meanRatio = BASOP_Util_Divide3232_Scale_newton( meanRatio, totalEnergySum, &exp );
2540 5679 : exp = add( exp, sub( shift, sub( 31, add( hMasa->data.q_energy, tmp2 ) ) ) ); // exp + (shift - (31 - hMasa->data.q_energy - tmp2)) => 1 + tmp2
2541 : }
2542 : ELSE
2543 : {
2544 0 : meanRatio = MAX_32;
2545 0 : exp = 31;
2546 0 : move32();
2547 0 : move16();
2548 : }
2549 :
2550 : /* 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.
2551 : * Otherwise, merge over subframes. */
2552 5679 : IF( BASOP_Util_Cmp_Mant32Exp( hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[0], 1, meanRatio, exp ) > 0 )
2553 : {
2554 4001 : mergeOverFreqBands = 1;
2555 4001 : move16();
2556 : }
2557 : ELSE
2558 : {
2559 1678 : mergeOverFreqBands = 0;
2560 1678 : move16();
2561 : }
2562 : }
2563 : ELSE
2564 : {
2565 19332 : mergeOverFreqBands = 0;
2566 19332 : move16();
2567 : }
2568 :
2569 : /* Merge values over subframes or frequency bands, depending on which one is less important */
2570 25011 : IF( !mergeOverFreqBands ) /* Merge values over subframes */
2571 : {
2572 : Word32 xSum, ySum, zSum;
2573 : Word64 W_xSum_sq, W_ySum_sq;
2574 : Word32 bandSumEnergy;
2575 : Word16 aziRad, eleRad, q_shift, exp_diff;
2576 : Word32 x, y, z;
2577 : Word32 veclen, L_tmp;
2578 :
2579 21010 : W_tmp = 0;
2580 21010 : move64();
2581 126060 : FOR( band = 0; band < numCodingBands; band++ )
2582 : {
2583 105050 : xSum = 0;
2584 105050 : ySum = 0;
2585 105050 : zSum = 0;
2586 105050 : bandSumEnergy = 0;
2587 105050 : move32();
2588 105050 : move32();
2589 105050 : move32();
2590 105050 : move32();
2591 :
2592 525250 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2593 : {
2594 420200 : aziRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].azimuth_fx[sf], PI_OVER_180_Q22 ) );
2595 420200 : eleRad = extract_l( Mpy_32_32( hqmetadata->q_direction[0].band_data[band].elevation_fx[sf], PI_OVER_180_Q22 ) );
2596 420200 : veclen = Mpy_32_32( hqmetadata->q_direction[0].band_data[band].energy_ratio_fx[sf], energy[sf][band] ); // hMasa->data.q_energy - 1
2597 :
2598 420200 : x = Mpy_32_32( L_mult( getCosWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
2599 420200 : move32();
2600 420200 : y = Mpy_32_32( L_mult0( getSinWord16( aziRad ), getCosWord16( eleRad ) ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
2601 420200 : move32();
2602 420200 : z = Mpy_32_32( L_mult0( getSinWord16( eleRad ), ONE_IN_Q14 ), veclen ); // (Q29, hMasa->data.q_energy - Q1) -> hMasa->data.q_energy - Q3
2603 420200 : move32();
2604 :
2605 420200 : xSum = L_add( xSum, x );
2606 420200 : ySum = L_add( ySum, y );
2607 420200 : zSum = L_add( zSum, z );
2608 :
2609 420200 : W_tmp = W_add( W_tmp, energy[sf][band] );
2610 : }
2611 :
2612 105050 : tmp2 = W_norm( W_tmp );
2613 105050 : tmp2 = s_min( 32, tmp2 );
2614 105050 : bandSumEnergy = W_extract_h( W_shl( W_tmp, tmp2 ) );
2615 105050 : tmp2 = sub( add( hMasa->data.q_energy, tmp2 ), 32 );
2616 :
2617 105050 : aziRad = BASOP_util_atan2( ySum, xSum, 0 ); // Q13
2618 105050 : W_xSum_sq = W_mult0_32_32( xSum, xSum ); // 2 * hMasa->data.q_energy - Q6
2619 105050 : W_ySum_sq = W_mult0_32_32( ySum, ySum ); // 2 * hMasa->data.q_energy - Q6
2620 105050 : W_tmp = W_add( W_xSum_sq, W_ySum_sq ); // 2 * hMasa->data.q_energy - Q6
2621 105050 : q_shift = W_norm( W_tmp );
2622 105050 : L_tmp = W_extract_h( W_shl( W_tmp, q_shift ) ); // 2 * hMasa->data.q_energy - Q6 + (q_shift -32)
2623 105050 : exp_diff = sub( Q31, add( sub( imult1616( 2, hMasa->data.q_energy ), Q6 ), sub( q_shift, 32 ) ) );
2624 105050 : L_tmp = Sqrt32( L_tmp, &exp_diff );
2625 105050 : eleRad = BASOP_util_atan2( zSum, L_tmp, sub( sub( 34, hMasa->data.q_energy ), exp_diff ) ); // Q13
2626 :
2627 105050 : hqmetadata->q_direction[0].band_data[band].azimuth_fx[0] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, aziRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
2628 105050 : hqmetadata->q_direction[0].band_data[band].elevation_fx[0] = L_shr( Mpy_32_16_1( _180_OVER_PI_Q25, eleRad ), Q1 ); // ((Q25, Q13) -> Q23) >> Q1 -> Q22
2629 :
2630 : /* Energy ratio is already merged through time */
2631 105050 : test();
2632 105050 : IF( computeCoherence && hqmetadata->q_direction[0].coherence_band_data != NULL )
2633 : {
2634 : Word16 spreadCoh;
2635 27180 : Word32 spreadCohSum = 0;
2636 27180 : move32();
2637 135900 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2638 : {
2639 108720 : spreadCoh = div_s( (Word16) hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf], 255 ); // Q15
2640 108720 : spreadCohSum = L_add( spreadCohSum, Mpy_32_16_1( energy[sf][band], spreadCoh ) );
2641 : }
2642 : // hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (uint8_t) roundf( spreadCohSum / ( bandSumEnergy + EPSILON ) * 255.0f );
2643 27180 : tmp = BASOP_Util_Divide3232_Scale( spreadCohSum, bandSumEnergy, &exp );
2644 27180 : exp = add( exp, sub( tmp2, hMasa->data.q_energy ) );
2645 27180 : tmp = mult_r( tmp, 32640 /* 255 in Q7 */ ); // 15 - exp + 7 - 15 => 7 - exp
2646 27180 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0] = (UWord8) shr( tmp, sub( 7, exp ) ); // Q0
2647 27180 : move16();
2648 :
2649 : /* Copy spread coherence to the rest of subframes for the coherence coding algorithm. */
2650 108720 : FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2651 : {
2652 81540 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[0]; // Q0
2653 81540 : move16();
2654 : }
2655 :
2656 : /* Surround coherence is already merged through time */
2657 : }
2658 : }
2659 :
2660 21010 : hqmetadata->q_direction->cfg.nblocks = 1;
2661 21010 : hMasa->config.joinedSubframes = 1;
2662 21010 : move16();
2663 21010 : move16();
2664 : }
2665 : ELSE /* Merge values over frequency bands */
2666 : {
2667 : /* Use the selected frequency band to represent all data */
2668 20005 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2669 : {
2670 16004 : hqmetadata->q_direction[0].band_data[0].azimuth_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].azimuth_fx[sf]; // Q22
2671 16004 : hqmetadata->q_direction[0].band_data[0].elevation_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].elevation_fx[sf]; // Q22
2672 16004 : hqmetadata->q_direction[0].band_data[0].energy_ratio_fx[sf] = hqmetadata->q_direction[0].band_data[selectedBand].energy_ratio_fx[sf]; // Q30
2673 16004 : move32();
2674 16004 : move32();
2675 16004 : move32();
2676 16004 : IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
2677 : {
2678 5408 : hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[selectedBand].spread_coherence[sf]; // Q0
2679 5408 : move16();
2680 : }
2681 16004 : IF( hqmetadata->surcoh_band_data != NULL )
2682 : {
2683 5408 : hqmetadata->surcoh_band_data[0].surround_coherence[sf] = hqmetadata->surcoh_band_data[selectedBand].surround_coherence[sf];
2684 5408 : move16();
2685 : }
2686 : }
2687 :
2688 : /* Copy coherence to rest of bands for the coherence coding algorithm. */
2689 20005 : FOR( band = 1; band < numCodingBands; band++ )
2690 : {
2691 16004 : IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
2692 : {
2693 27040 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2694 : {
2695 21632 : hqmetadata->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hqmetadata->q_direction[0].coherence_band_data[0].spread_coherence[sf]; // Q0
2696 21632 : move16();
2697 : }
2698 : }
2699 16004 : IF( hqmetadata->q_direction[0].coherence_band_data != NULL )
2700 : {
2701 27040 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
2702 : {
2703 21632 : hqmetadata->surcoh_band_data[band].surround_coherence[sf] = hqmetadata->surcoh_band_data[0].surround_coherence[sf];
2704 21632 : move16();
2705 : }
2706 : }
2707 : }
2708 :
2709 4001 : hqmetadata->q_direction[0].cfg.nbands = 1;
2710 4001 : move16();
2711 : }
2712 :
2713 25011 : return;
2714 : }
2715 :
2716 :
2717 11680 : static Word16 encode_lfe_to_total_energy_ratio_fx(
2718 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */
2719 : BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */
2720 : const Word32 ivas_total_brate /* i : IVAS total bitrate */
2721 : )
2722 : {
2723 : Word16 i;
2724 : Word16 xq;
2725 : Word16 VQLevels;
2726 : Word32 maxLFESubFrameEner;
2727 : Word16 maxLFESubFrameEner_e;
2728 : Word32 log2LFEaverage;
2729 : Word32 log2LFEratio[4];
2730 : Word32 xqv[4];
2731 : Word32 linearLFEaverage;
2732 : Word16 linearLFEaverage_e;
2733 : Word16 lfeToTotalEnergyRatioIndices[3];
2734 : Word16 lfeAdaptiveVQBits;
2735 : Word16 lfeBitsWritten;
2736 : Word32 maxVal;
2737 : Word16 maxVal_e;
2738 :
2739 11680 : VQLevels = 0;
2740 11680 : move16();
2741 11680 : lfeAdaptiveVQBits = 0;
2742 11680 : move16();
2743 :
2744 : /* Determine maximum amount of LFE energy in any subframe */
2745 11680 : maxLFESubFrameEner = 0; // maxLFESubFrameEner_e
2746 11680 : move32();
2747 11680 : maxLFESubFrameEner_e = 0;
2748 11680 : move16();
2749 58400 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
2750 : {
2751 46720 : IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxLFESubFrameEner, maxLFESubFrameEner_e ) > 0 )
2752 : {
2753 4607 : maxLFESubFrameEner = hMasa->data.lfeToTotalEnergyRatio_fx[i]; // hMasa->data.lfeToTotalEnergyRatio_e[i]
2754 4607 : move32();
2755 4607 : maxLFESubFrameEner_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
2756 4607 : move16();
2757 : }
2758 : }
2759 :
2760 : /* Set default values for the indices */
2761 46720 : FOR( i = 0; i < 3; i++ )
2762 : {
2763 35040 : lfeToTotalEnergyRatioIndices[i] = 0;
2764 35040 : move16();
2765 : }
2766 :
2767 : /* Check if there is enough energy in any subframe. If not, send only 1 bit (0) and abort. */
2768 : /* If there is enough LFE energy at least in one subframe, quantize it. */
2769 11680 : IF( BASOP_Util_Cmp_Mant32Exp( maxLFESubFrameEner, maxLFESubFrameEner_e, 10737418 /* 0.005f in Q31 */, 0 ) > 0 )
2770 : {
2771 : /* Convert energy to log2 domain, and clamp it to reasonable values */
2772 1904 : log2LFEaverage = 0; // Q25
2773 1904 : move32();
2774 9520 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
2775 : {
2776 : // log2LFEratio[i] = log2f( max( 0.001f, hMasa->data.lfeToTotalEnergyRatio[i] ) );
2777 7616 : maxVal = INV_1000_Q31;
2778 7616 : move32();
2779 7616 : maxVal_e = 0;
2780 7616 : move16();
2781 7616 : IF( BASOP_Util_Cmp_Mant32Exp( hMasa->data.lfeToTotalEnergyRatio_fx[i], hMasa->data.lfeToTotalEnergyRatio_e[i], maxVal, maxVal_e ) > 0 )
2782 : {
2783 7374 : maxVal = hMasa->data.lfeToTotalEnergyRatio_fx[i];
2784 7374 : move32();
2785 7374 : maxVal_e = hMasa->data.lfeToTotalEnergyRatio_e[i];
2786 7374 : move16();
2787 : }
2788 7616 : log2LFEratio[i] = L_add( BASOP_Util_Log2( maxVal ), L_shl( maxVal_e, Q25 ) ); // Q25
2789 7616 : move32();
2790 7616 : IF( GT_32( log2LFEratio[i], ONE_IN_Q25 ) ) /* Corresponds to linear value 2.0f */
2791 : {
2792 0 : log2LFEratio[i] = ONE_IN_Q25; // Q25
2793 0 : move32();
2794 : }
2795 7616 : ELSE IF( LT_32( log2LFEratio[i], -301989888 /* -9.0f in Q25 */ ) )
2796 : {
2797 289 : log2LFEratio[i] = -301989888 /* -9.0f in Q25 */; // Q25
2798 289 : move32();
2799 : }
2800 7616 : log2LFEaverage = L_add( log2LFEaverage, Mpy_32_32( 536870912 /* 0.25f in Q31 */, log2LFEratio[i] ) ); // Q25
2801 : }
2802 :
2803 1904 : IF( EQ_32( ivas_total_brate, IVAS_13k2 ) )
2804 : {
2805 : /* Calculate adaptive 1-bit LFE quantizer index */
2806 : // linearLFEaverage = exp2f( log2LFEaverage ); /* Convert back to linear domain */
2807 175 : linearLFEaverage = BASOP_util_Pow2( log2LFEaverage, Q31 - Q25, &linearLFEaverage_e ); /* Convert back to linear domain */
2808 175 : linearLFEaverage = L_shl_sat( linearLFEaverage, sub( linearLFEaverage_e, Q1 ) ); // Q30
2809 175 : test();
2810 175 : IF( GT_32( linearLFEaverage, MCMASA_LFE_1BIT_THRES_Q30 ) &&
2811 : GT_32( linearLFEaverage, L_add( L_add( MCMASA_LFE_BETA_Q30 >> Q1, L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q2 ) ),
2812 : L_shr( Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ), Q1 ) ) ) )
2813 : {
2814 128 : lfeToTotalEnergyRatioIndices[0] = 1;
2815 128 : move16();
2816 128 : IF( EQ_16( hMasa->data.prevq_lfeIndex, 1 ) )
2817 : {
2818 86 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_add( L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ), 125627793 /* MCMASA_LFE_THETA * MCMASA_LFE_BETA in Q30 */ ); /* larger "bump-up" to LFE-to-total energy ratio */ // Q30
2819 86 : move32();
2820 : }
2821 : ELSE
2822 : {
2823 42 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_add( L_shr( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ), MCMASA_LFE_BETA_Q30 ); /* default "bump-up" to LFE-to-total energy ratio */ // Q30
2824 42 : move32();
2825 : }
2826 : }
2827 : ELSE
2828 : {
2829 47 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = Mpy_32_32( MCMASA_LFE_ALPHA_Q30, hMasa->data.prevq_lfeToTotalEnergyRatio_fx ); /* exponential decay */ // Q30
2830 47 : move32();
2831 : }
2832 :
2833 175 : IF( GE_32( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, ONE_IN_Q30 ) )
2834 : {
2835 0 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = ONE_IN_Q31; // Q31
2836 0 : move32();
2837 : }
2838 : ELSE
2839 : {
2840 175 : hMasa->data.prevq_lfeToTotalEnergyRatio_fx = L_shl( hMasa->data.prevq_lfeToTotalEnergyRatio_fx, Q1 ); // Q31
2841 175 : move32();
2842 : }
2843 175 : hMasa->data.prevq_lfeIndex = lfeToTotalEnergyRatioIndices[0]; /* Update to previous frame's index memories */
2844 175 : move16();
2845 : }
2846 : ELSE /* Bitrate >= 16.4 kbps */
2847 : {
2848 : /* Do 1st stage scalar quantization */
2849 1729 : lfeToTotalEnergyRatioIndices[0] = 1;
2850 1729 : move16();
2851 1729 : lfeToTotalEnergyRatioIndices[1] = usquant_fx( extract_l( L_shr( log2LFEaverage, Q14 ) ), &xq, MCMASA_LFE_QLOW_Q11, MCMASA_LFE_DELTA_Q10, 8 );
2852 1729 : move16();
2853 :
2854 1729 : IF( GE_32( ivas_total_brate, IVAS_24k4 ) ) /* Vector quantization is applied if bitrate >= 24.4 kbps */
2855 : {
2856 : /* Remove scalar value from the vector*/
2857 8120 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
2858 : {
2859 6496 : log2LFEratio[i] = L_sub( log2LFEratio[i], L_shl( xq, Q14 ) ); // Q25
2860 6496 : move32();
2861 : }
2862 :
2863 : /* Vector quantize residual with energy adaptive bit allocation */
2864 1624 : SWITCH( lfeToTotalEnergyRatioIndices[1] )
2865 : {
2866 222 : case 0:
2867 : case 1:
2868 222 : VQLevels = 0;
2869 222 : move16();
2870 222 : lfeAdaptiveVQBits = 0;
2871 222 : move16();
2872 222 : BREAK;
2873 98 : case 2:
2874 98 : VQLevels = 2;
2875 98 : move16();
2876 98 : lfeAdaptiveVQBits = 1;
2877 98 : move16();
2878 98 : BREAK;
2879 97 : case 3:
2880 97 : VQLevels = 4;
2881 97 : move16();
2882 97 : lfeAdaptiveVQBits = 2;
2883 97 : move16();
2884 97 : BREAK;
2885 246 : case 4:
2886 246 : VQLevels = 8;
2887 246 : move16();
2888 246 : lfeAdaptiveVQBits = 3;
2889 246 : move16();
2890 246 : BREAK;
2891 961 : default:
2892 961 : VQLevels = 16;
2893 961 : move16();
2894 961 : lfeAdaptiveVQBits = 4;
2895 961 : move16();
2896 : }
2897 :
2898 1624 : IF( VQLevels > 0 )
2899 : {
2900 1402 : lfeToTotalEnergyRatioIndices[2] = vquant_ivas_fx( log2LFEratio, 0, xqv, McMASA_LFEGain_vectors_fx, 4, VQLevels );
2901 1402 : move16();
2902 : }
2903 : }
2904 : }
2905 : }
2906 :
2907 : /* Write first LFE bit */
2908 11680 : lfeBitsWritten = 0;
2909 11680 : move16();
2910 11680 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[0], 1 );
2911 11680 : lfeBitsWritten = add( lfeBitsWritten, 1 );
2912 :
2913 11680 : test();
2914 11680 : IF( EQ_16( lfeToTotalEnergyRatioIndices[0], 1 ) && GE_32( ivas_total_brate, IVAS_16k4 ) )
2915 : {
2916 : /* If bitrate >= 16.4kbit/s, send 1-bit on/off + 3-bit scalar */
2917 1729 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[1], 3 );
2918 1729 : lfeBitsWritten = add( lfeBitsWritten, 3 );
2919 :
2920 : /* If bitrate >= 24.4kbit/s, use adaptive 1 + (3.. 7) bit quantizer */
2921 1729 : IF( GE_32( ivas_total_brate, IVAS_24k4 ) )
2922 : {
2923 : /* Vector quantize residual with energy adaptive bit allocation */
2924 1624 : IF( lfeAdaptiveVQBits > 0 )
2925 : {
2926 1402 : push_next_indice( hMetaData, lfeToTotalEnergyRatioIndices[2], lfeAdaptiveVQBits );
2927 1402 : lfeBitsWritten = add( lfeBitsWritten, lfeAdaptiveVQBits );
2928 : }
2929 : }
2930 : }
2931 :
2932 11680 : return lfeBitsWritten;
2933 : }
2934 :
2935 :
2936 : /*-------------------------------------------------------------------*
2937 : * ivas_masa_enc_reconfigure()
2938 : *
2939 : * Reconfigure IVAS MASA encoder
2940 : *-------------------------------------------------------------------*/
2941 :
2942 30626 : void ivas_masa_enc_reconfigure_fx(
2943 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
2944 : )
2945 : {
2946 : Word16 n, tmp;
2947 : Word16 sce_id, cpe_id;
2948 : Word32 ivas_total_brate;
2949 : Word32 ism_total_brate;
2950 : Word32 tmp_br;
2951 :
2952 30626 : ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate;
2953 30626 : move32();
2954 :
2955 30626 : ism_total_brate = 0;
2956 30626 : move32();
2957 30626 : test();
2958 30626 : test();
2959 30626 : test();
2960 30626 : test();
2961 30626 : IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) )
2962 : {
2963 0 : FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
2964 : {
2965 0 : ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[sce_id]->element_brate );
2966 : }
2967 : }
2968 :
2969 30626 : IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) )
2970 : {
2971 1269 : tmp_br = Mpy_32_32_r( ivas_total_brate, one_by_q_level[st_ivas->nchan_transport] );
2972 1934 : FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
2973 : {
2974 665 : copy_encoder_config_fx( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 );
2975 665 : st_ivas->hSCE[sce_id]->element_brate = tmp_br;
2976 665 : 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() */
2977 665 : move32();
2978 665 : move32();
2979 : }
2980 :
2981 1873 : FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ )
2982 : {
2983 604 : st_ivas->hCPE[cpe_id]->element_brate = imult3216( tmp_br, 2 ); //( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS;
2984 604 : move32();
2985 :
2986 604 : IF( GT_16( st_ivas->nCPE, 1 ) )
2987 : {
2988 0 : tmp = 1;
2989 : }
2990 : ELSE
2991 : {
2992 604 : tmp = CPE_CHANNELS;
2993 : }
2994 604 : move16();
2995 : /* prepare bitstream buffers */
2996 1812 : FOR( n = 0; n < CPE_CHANNELS; n++ )
2997 : {
2998 1208 : copy_encoder_config_fx( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 );
2999 : /* st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); */
3000 1208 : st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = L_shr( st_ivas->hCPE[cpe_id]->element_brate, sub( tmp, 1 ) ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */
3001 1208 : move32();
3002 : }
3003 :
3004 604 : IF( LT_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) )
3005 : {
3006 218 : st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_DFT;
3007 : }
3008 : ELSE
3009 : {
3010 386 : st_ivas->hCPE[cpe_id]->element_mode = IVAS_CPE_MDCT;
3011 : }
3012 604 : move16();
3013 : }
3014 :
3015 1269 : ivas_masa_set_elements_fx( 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 );
3016 : }
3017 :
3018 30626 : return;
3019 : }
3020 :
3021 :
3022 : /*-------------------------------------------------------------------*
3023 : * average_masa_metadata()
3024 : *
3025 : * Average MASA metadata frame subframe contents: applies aggregation over time
3026 : *-------------------------------------------------------------------*/
3027 :
3028 0 : static void average_masa_metadata_fx(
3029 : MASA_METADATA_FRAME *hMeta,
3030 : Word32 energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*i Q(31 - energy_e) */
3031 : Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*i:stores exponent values for energy_e*/
3032 : const SPHERICAL_GRID_DATA *Sph_Grid16,
3033 : const UWord8 useSphGrid )
3034 : {
3035 : Word16 i, j, k;
3036 : Word16 azi_rad_fx, ele_rad_fx;
3037 : UWord8 numDirections;
3038 :
3039 : /* use the nominal values without data-adaptivity */
3040 0 : numDirections = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 );
3041 0 : move16();
3042 :
3043 : /* azi/ele/nrg into vectors for each sub-frame and band */
3044 0 : FOR( i = 0; i < numDirections; i++ )
3045 : {
3046 0 : FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
3047 : {
3048 : Word32 x_sum_fx, y_sum_fx, z_sum_fx, energy_sum_fx, vec_len_fx, spread_coh_sum_fx, surr_coh_sum_fx, temp1, temp2;
3049 : Word16 vec_len_e, x_sum_e, y_sum_e, z_sum_e, energy_sum_e, spread_coh_sum_e, surr_coh_sum_e, temp1_e, temp2_e;
3050 0 : x_sum_fx = 0;
3051 0 : y_sum_fx = 0;
3052 0 : z_sum_fx = 0;
3053 0 : energy_sum_fx = 0;
3054 0 : spread_coh_sum_fx = 0;
3055 0 : surr_coh_sum_fx = 0;
3056 0 : x_sum_e = 0; /*exponent for x_sum_fx*/
3057 0 : y_sum_e = 0; /*exponent for y_sum_fx*/
3058 0 : z_sum_e = 0; /*exponent for z_sum_fx*/
3059 0 : energy_sum_e = 0; /*exponent for energy_sum_fx*/
3060 0 : spread_coh_sum_e = 0; /*exponent for spread_coh_sum_fx*/
3061 0 : surr_coh_sum_e = 0; /*exponent for surr_coh_sum_fx*/
3062 0 : temp1 = 0; /* to store temporary computations*/
3063 0 : temp2 = 0; /* to store temporary computations*/
3064 0 : temp1_e = 0; /*to store temporary exponents*/
3065 0 : temp2_e = 0; /*to store temporary exponents*/
3066 0 : move32();
3067 0 : move32();
3068 0 : move32();
3069 0 : move32();
3070 0 : move32();
3071 0 : move32();
3072 0 : move32();
3073 0 : move32();
3074 0 : move16();
3075 0 : move16();
3076 0 : move16();
3077 0 : move16();
3078 0 : move16();
3079 0 : move16();
3080 0 : move16();
3081 0 : move16();
3082 :
3083 0 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
3084 : {
3085 0 : azi_rad_fx = extract_l( Mpy_32_32( hMeta->directional_meta[i].azimuth_fx[j][k], 46603 /*1/(360) in Q24*/ ) ); /*=angle *(1/2pi) brings the azi_rad_fx in -32767 to 32767 in q15 (this argument is further passed in cos and sin functions)*/ /*22+24-31=15*/
3086 0 : ele_rad_fx = extract_l( Mpy_32_32( hMeta->directional_meta[i].elevation_fx[j][k], 46603 /*1/(360) in Q24*/ ) ); /*=angle *(1/2pi) brings the azi_rad_fx in -32767 to 32767 in q15 (this argument is further passed in cos and sin functions)*/ /*22+24-31=15*/
3087 0 : vec_len_fx = Mpy_32_32( hMeta->directional_meta[i].energy_ratio_fx[j][k] /*q30*/, energy[j][k] ); /*exponent=energy_e+1*/
3088 0 : vec_len_e = add( energy_e[j][k], 1 );
3089 :
3090 : /* energy-weighted sum over subframes */
3091 0 : x_sum_fx = BASOP_Util_Add_Mant32Exp( x_sum_fx, x_sum_e, Mpy_32_32( L_mult( getCosWord16R2( azi_rad_fx ), getCosWord16R2( ele_rad_fx ) ) /*q31*/, vec_len_fx ), vec_len_e, &x_sum_e ); /*x_sum_e*/
3092 0 : y_sum_fx = BASOP_Util_Add_Mant32Exp( y_sum_fx, y_sum_e, Mpy_32_32( L_mult( getSineWord16R2( azi_rad_fx ), getCosWord16R2( ele_rad_fx ) ) /*q31*/, vec_len_fx ), vec_len_e, &y_sum_e ); /*y_sum_e*/
3093 0 : z_sum_fx = BASOP_Util_Add_Mant32Exp( z_sum_fx, z_sum_e, Mpy_32_16_1( vec_len_fx, getSineWord16R2( ele_rad_fx ) /*q15*/ ), vec_len_e, &z_sum_e ); /*z_sum_e*/
3094 :
3095 0 : energy_sum_fx = BASOP_Util_Add_Mant32Exp( energy_sum_fx, energy_sum_e, energy[j][k], energy_e[j][k], &energy_sum_e ); /*energy_sum_e*/
3096 :
3097 0 : spread_coh_sum_fx = BASOP_Util_Add_Mant32Exp( spread_coh_sum_fx, spread_coh_sum_e, Mpy_32_16_1( energy[j][k], hMeta->directional_meta[i].spread_coherence_fx[j][k] ), energy_e[j][k], &spread_coh_sum_e ); /*spread_coh_sum_e*/
3098 0 : IF( i == 0 )
3099 : {
3100 : /* this is in common metadata and not in each direction */
3101 0 : surr_coh_sum_fx = BASOP_Util_Add_Mant32Exp( surr_coh_sum_fx, surr_coh_sum_e, Mpy_32_16_1( energy[j][k], hMeta->common_meta.surround_coherence_fx[j][k] ), energy_e[j][k], &surr_coh_sum_e ); /*surr_coh_sum_e*/
3102 : }
3103 : }
3104 :
3105 : /* the data from the combined sub-frames is written into the first sub-frame band */
3106 0 : j = 0;
3107 0 : move16();
3108 0 : hMeta->directional_meta[i].azimuth_fx[j][k] = Mpy_32_16_1( 961263669 /*(1/ EVS_PI * 180.0f) in Q24*/, BASOP_util_atan2( y_sum_fx, x_sum_fx, sub( y_sum_e, x_sum_e ) ) /*q13*/ ); /*24+13-15=22*/
3109 0 : move32();
3110 0 : temp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( x_sum_fx, x_sum_fx ), shl( x_sum_e, 1 ), Mpy_32_32( y_sum_fx, y_sum_fx ), shl( y_sum_e, 1 ), &temp1_e ); /*temp1_e*/
3111 0 : temp2_e = temp1_e;
3112 0 : temp2 = Sqrt32( temp1, &temp2_e ); /*temp2_e*/
3113 0 : hMeta->directional_meta[i].elevation_fx[j][k] = Mpy_32_16_1( 961263669 /*(1/ EVS_PI * 180.0f) in Q24*/, BASOP_util_atan2( z_sum_fx, temp2, sub( z_sum_e, temp2_e ) ) /*q13*/ ); /*24+13-15=22*/
3114 0 : move32();
3115 0 : IF( EQ_16( useSphGrid, TRUE ) )
3116 : {
3117 :
3118 0 : hMeta->directional_meta[i].spherical_index[j][k] = index_theta_phi_16_fx( &( hMeta->directional_meta[i].elevation_fx[j][k] ),
3119 0 : &( hMeta->directional_meta[i].azimuth_fx[j][k] ), Sph_Grid16 );
3120 0 : move16();
3121 : }
3122 0 : vec_len_fx = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, Mpy_32_32( z_sum_fx, z_sum_fx ), shl( z_sum_e, 1 ), &vec_len_e ); /*vec_len_e*/ /*x_sum * x_sum + y_sum * y_sum + z_sum * z_sum*/
3123 0 : vec_len_fx = Sqrt32( vec_len_fx, &vec_len_e ); /*vec_len_e*/
3124 0 : hMeta->directional_meta[i].energy_ratio_fx[j][k] = BASOP_Util_Divide3232_Scale( vec_len_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e ); /*temp2_e*/
3125 0 : move32();
3126 0 : temp2_e = add( temp2_e, sub( vec_len_e, energy_sum_e ) );
3127 0 : hMeta->directional_meta[i].energy_ratio_fx[j][k] = L_shl( hMeta->directional_meta[i].energy_ratio_fx[j][k], add( temp2_e, 15 ) ); /*changing q from 15-temp2_e to q30*/
3128 0 : move32();
3129 0 : hMeta->directional_meta[i].spread_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( spread_coh_sum_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e );
3130 0 : move16();
3131 0 : temp2_e = add( temp2_e, sub( spread_coh_sum_e, energy_sum_e ) );
3132 0 : hMeta->directional_meta[i].spread_coherence_fx[j][k] = shl( hMeta->directional_meta[i].spread_coherence_fx[j][k], temp2_e ); /*changing q from 15-temp2_e to q15*/
3133 0 : move16();
3134 0 : IF( i == 0 )
3135 : {
3136 0 : hMeta->common_meta.surround_coherence_fx[j][k] = BASOP_Util_Divide3232_Scale( surr_coh_sum_fx, L_add( energy_sum_fx, EPSILON_FX ), &temp2_e );
3137 0 : move16();
3138 0 : temp2_e = add( temp2_e, sub( surr_coh_sum_e, energy_sum_e ) );
3139 0 : hMeta->common_meta.surround_coherence_fx[j][k] = shl_sat( hMeta->common_meta.surround_coherence_fx[j][k], temp2_e ); /*changing q from 15-temp2_e to q15*/
3140 0 : move16();
3141 : }
3142 :
3143 : /* copy the same value to all subframes */
3144 0 : FOR( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
3145 : {
3146 0 : hMeta->directional_meta[i].azimuth_fx[j][k] = hMeta->directional_meta[i].azimuth_fx[0][k]; /*q22*/
3147 0 : hMeta->directional_meta[i].elevation_fx[j][k] = hMeta->directional_meta[i].elevation_fx[0][k]; /*q22*/
3148 0 : hMeta->directional_meta[i].energy_ratio_fx[j][k] = hMeta->directional_meta[i].energy_ratio_fx[0][k]; /*q30*/
3149 0 : hMeta->directional_meta[i].spread_coherence_fx[j][k] = hMeta->directional_meta[i].spread_coherence_fx[0][k]; /*q15*/
3150 0 : move32();
3151 0 : move32();
3152 0 : move32();
3153 0 : move16();
3154 0 : IF( i == 0 )
3155 : {
3156 0 : hMeta->common_meta.surround_coherence_fx[j][k] = hMeta->common_meta.surround_coherence_fx[0][k]; /*q15*/
3157 0 : move16();
3158 : }
3159 : }
3160 : }
3161 : }
3162 :
3163 0 : FOR( k = 0; k < MASA_FREQUENCY_BANDS; k++ )
3164 : {
3165 0 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
3166 : {
3167 0 : IF( EQ_16( numDirections, 2 ) )
3168 : {
3169 0 : hMeta->common_meta.diffuse_to_total_ratio_fx[j][k] = L_max( 0, L_sub( L_sub( ONE_IN_Q30, hMeta->directional_meta[1].energy_ratio_fx[j][k] ), hMeta->directional_meta[0].energy_ratio_fx[j][k] ) ); /*q30*/
3170 : }
3171 : ELSE
3172 : {
3173 0 : hMeta->common_meta.diffuse_to_total_ratio_fx[j][k] = L_max( 0, L_sub( ONE_IN_Q30, hMeta->directional_meta[0].energy_ratio_fx[j][k] ) ); /*q30*/
3174 : }
3175 0 : move32();
3176 0 : hMeta->common_meta.remainder_to_total_ratio_fx[j][k] = 0; /*q30*/
3177 0 : move32();
3178 : }
3179 : }
3180 :
3181 0 : return;
3182 : }
3183 :
3184 :
3185 : /*-------------------------------------------------------------------*
3186 : * copy_masa_metadata_subframe()
3187 : *
3188 : * Copy MASA metadata frame subframe contents
3189 : *-------------------------------------------------------------------*/
3190 :
3191 158504 : static void copy_masa_metadata_subframe_fx(
3192 : const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metdata to be copied */
3193 : const UWord8 sfFrom, /* i : subframe index of the copy source */
3194 : MASA_METADATA_HANDLE hMetaTo, /* o : MASA frame metadata copy destination */
3195 : const UWord8 sfTo /* i : subframe index of the copy target */
3196 : )
3197 : {
3198 : UWord8 dir;
3199 : UWord8 band;
3200 :
3201 : /* directional metadata */
3202 475512 : FOR( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ )
3203 : {
3204 7925200 : FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
3205 : {
3206 7608192 : hMetaTo->directional_meta[dir].spherical_index[sfTo][band] = hMetaFrom->directional_meta[dir].spherical_index[sfFrom][band];
3207 7608192 : move16();
3208 : }
3209 317008 : Copy32( hMetaFrom->directional_meta[dir].azimuth_fx[sfFrom], hMetaTo->directional_meta[dir].azimuth_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q22
3210 317008 : Copy32( hMetaFrom->directional_meta[dir].elevation_fx[sfFrom], hMetaTo->directional_meta[dir].elevation_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q22
3211 317008 : Copy32( hMetaFrom->directional_meta[dir].energy_ratio_fx[sfFrom], hMetaTo->directional_meta[dir].energy_ratio_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q30
3212 317008 : Copy( hMetaFrom->directional_meta[dir].spread_coherence_fx[sfFrom], hMetaTo->directional_meta[dir].spread_coherence_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q15
3213 : }
3214 :
3215 : /* common metadata */
3216 158504 : Copy32( hMetaFrom->common_meta.diffuse_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.diffuse_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q30
3217 158504 : Copy( hMetaFrom->common_meta.surround_coherence_fx[sfFrom], hMetaTo->common_meta.surround_coherence_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q15
3218 158504 : Copy32( hMetaFrom->common_meta.remainder_to_total_ratio_fx[sfFrom], hMetaTo->common_meta.remainder_to_total_ratio_fx[sfTo], MASA_FREQUENCY_BANDS ); // Q30
3219 :
3220 158504 : return;
3221 : }
3222 :
3223 :
3224 : /*-------------------------------------------------------------------*
3225 : * copy_masa_metadata()
3226 : *
3227 : * Copy MASA metada frame contents
3228 : *-------------------------------------------------------------------*/
3229 :
3230 39626 : static void copy_masa_metadata_fx(
3231 : const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metadata to be copied */
3232 : MASA_METADATA_HANDLE hMetaTo /* o : MASA frame metadata copy destination */
3233 : )
3234 : {
3235 : UWord8 sf, byte_idx;
3236 :
3237 : /* descriptive metadata */
3238 356634 : FOR( byte_idx = 0; byte_idx < 8; byte_idx++ )
3239 : {
3240 317008 : hMetaTo->descriptive_meta.formatDescriptor[byte_idx] = hMetaFrom->descriptive_meta.formatDescriptor[byte_idx];
3241 317008 : move16();
3242 : }
3243 :
3244 39626 : hMetaTo->descriptive_meta.numberOfDirections = hMetaFrom->descriptive_meta.numberOfDirections;
3245 39626 : hMetaTo->descriptive_meta.numberOfChannels = hMetaFrom->descriptive_meta.numberOfChannels;
3246 39626 : hMetaTo->descriptive_meta.sourceFormat = hMetaFrom->descriptive_meta.sourceFormat;
3247 39626 : hMetaTo->descriptive_meta.transportDefinition = hMetaFrom->descriptive_meta.transportDefinition;
3248 39626 : hMetaTo->descriptive_meta.channelAngle = hMetaFrom->descriptive_meta.channelAngle;
3249 39626 : hMetaTo->descriptive_meta.channelDistance = hMetaFrom->descriptive_meta.channelDistance;
3250 39626 : hMetaTo->descriptive_meta.channelLayout = hMetaFrom->descriptive_meta.channelLayout;
3251 39626 : move16();
3252 39626 : move16();
3253 39626 : move16();
3254 39626 : move16();
3255 39626 : move16();
3256 39626 : move16();
3257 39626 : move16();
3258 :
3259 : /* directional and common metadata */
3260 198130 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
3261 : {
3262 158504 : copy_masa_metadata_subframe_fx( hMetaFrom, sf, hMetaTo, sf );
3263 : }
3264 :
3265 39626 : return;
3266 : }
3267 :
3268 :
3269 : /*-------------------------------------------------------------------*
3270 : * are_masa_subframes_similar()
3271 : *
3272 : * Compare the similarity of MASA metadata in two sub-frames
3273 : *-------------------------------------------------------------------*/
3274 :
3275 : /* r: similarity decision */
3276 175035 : static UWord8 are_masa_subframes_similar_fx(
3277 : const MASA_METADATA_HANDLE frame1, /* i : MASA metadata frame 1 */
3278 : const UWord8 sf1_idx, /* i : index of the subframe of frame1 to inspect */
3279 : const MASA_METADATA_HANDLE frame2, /* i : MASA metadata frame 2 */
3280 : const UWord8 sf2_idx /* i : index of the subframe of frame2 to inspect */
3281 : )
3282 : {
3283 : UWord8 num_dir;
3284 : UWord8 dir;
3285 : UWord8 band_idx;
3286 : UWord8 sf_differ;
3287 :
3288 175035 : num_dir = frame1->descriptive_meta.numberOfDirections;
3289 175035 : dir = 0;
3290 175035 : band_idx = 0;
3291 175035 : sf_differ = FALSE;
3292 175035 : move16();
3293 175035 : move16();
3294 175035 : move16();
3295 175035 : move16();
3296 :
3297 175035 : IF( NE_16( num_dir, frame2->descriptive_meta.numberOfDirections ) )
3298 : {
3299 0 : sf_differ = TRUE;
3300 0 : move16();
3301 : }
3302 : ELSE
3303 : {
3304 : /* check per-direction metadata */
3305 175035 : dir = 0;
3306 175035 : band_idx = 0;
3307 175035 : move16();
3308 175035 : move16();
3309 :
3310 360870 : WHILE( ( sf_differ == FALSE ) && ( dir <= num_dir ) )
3311 : {
3312 185835 : test();
3313 185835 : band_idx = 0;
3314 185835 : move16();
3315 1244235 : WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
3316 : {
3317 1200135 : test();
3318 : Word32 azi_dif_fx;
3319 1200135 : azi_dif_fx = L_abs( L_sub( frame1->directional_meta[dir].azimuth_fx[sf1_idx][band_idx], frame2->directional_meta[dir].azimuth_fx[sf2_idx][band_idx] ) ); // Q22
3320 1200135 : IF( GT_32( azi_dif_fx, 180 << Q22 ) )
3321 16892 : azi_dif_fx = L_sub( 360 << Q22, azi_dif_fx ); // Q22
3322 :
3323 1200135 : IF( GT_32( azi_dif_fx, ONE_IN_Q21 /*0.5 in Q22*/ ) )
3324 : {
3325 139100 : sf_differ = TRUE;
3326 139100 : move16();
3327 139100 : BREAK;
3328 : }
3329 :
3330 1061035 : IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].elevation_fx[sf1_idx][band_idx], frame2->directional_meta[dir].elevation_fx[sf2_idx][band_idx] ) ), MASA_ANGLE_TOLERANCE_FX ) )
3331 : {
3332 2616 : sf_differ = TRUE;
3333 2616 : move16();
3334 2616 : BREAK;
3335 : }
3336 :
3337 1058419 : IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].energy_ratio_fx[sf1_idx][band_idx], frame2->directional_meta[dir].energy_ratio_fx[sf2_idx][band_idx] ) ), MASA_RATIO_TOLERANCE_FX ) )
3338 : {
3339 19 : sf_differ = TRUE;
3340 19 : move16();
3341 19 : BREAK;
3342 : }
3343 :
3344 1058400 : IF( GT_32( L_abs( L_sub( frame1->directional_meta[dir].spread_coherence_fx[sf1_idx][band_idx], frame2->directional_meta[dir].spread_coherence_fx[sf2_idx][band_idx] ) ), MASA_COHERENCE_TOLERANCE_FX ) )
3345 : {
3346 0 : sf_differ = TRUE;
3347 0 : move16();
3348 0 : BREAK;
3349 : }
3350 :
3351 1058400 : band_idx = (UWord8) add( band_idx, 1 );
3352 1058400 : move16();
3353 : }
3354 185835 : dir = (UWord8) add( dir, 1 );
3355 185835 : move16();
3356 : }
3357 :
3358 : /* check the common metadata */
3359 175035 : WHILE( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) )
3360 : {
3361 0 : test();
3362 0 : IF( GT_32( L_abs( L_sub( frame1->common_meta.surround_coherence_fx[sf1_idx][band_idx], frame2->common_meta.surround_coherence_fx[sf2_idx][band_idx] ) ), MASA_COHERENCE_TOLERANCE_FX ) )
3363 : {
3364 0 : sf_differ = TRUE;
3365 0 : move16();
3366 0 : BREAK;
3367 : }
3368 :
3369 0 : band_idx = (UWord8) add( band_idx, 1 );
3370 0 : move16();
3371 : }
3372 : }
3373 :
3374 175035 : IF( sf_differ )
3375 : {
3376 141735 : return FALSE;
3377 : }
3378 : ELSE
3379 : {
3380 33300 : return TRUE;
3381 : }
3382 : }
3383 :
3384 :
3385 : /*-------------------------------------------------------------------*
3386 : * detect_framing_async()
3387 : *
3388 : * Compare the similarity of MASA metadata in two sub-frames
3389 : * Analysis result is stored in hMasa->data.sync_state, and
3390 : * potentially hMasa->masaMetadata is modified
3391 : *-------------------------------------------------------------------*/
3392 :
3393 39626 : static void detect_framing_async_fx(
3394 : MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */
3395 : )
3396 : {
3397 : MASA_METADATA_HANDLE current_meta;
3398 : MASA_METADATA_HANDLE previous_meta;
3399 : MASA_SYNC_HANDLE sync_state;
3400 : MASA_FRAME_MODE frame_mode;
3401 : UWord8 n_sim_start, n_sim_stop, sf_idx;
3402 : UWord8 found_offset;
3403 :
3404 39626 : current_meta = &( hMasa->masaMetadata ); /* metadata from current frame */
3405 39626 : sync_state = &( hMasa->data.sync_state ); /* synchronization structure */
3406 39626 : previous_meta = &( sync_state->previous_metadata );
3407 :
3408 : /* check current frame, how many are similar from the start and from the end */
3409 39626 : n_sim_start = 1;
3410 39626 : move16();
3411 56276 : FOR( sf_idx = n_sim_start; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
3412 : {
3413 50726 : IF( EQ_16( are_masa_subframes_similar_fx( current_meta, 0, current_meta, sf_idx ), TRUE ) )
3414 : {
3415 16650 : n_sim_start = (UWord8) add( sf_idx, 1 );
3416 16650 : move16();
3417 : }
3418 : ELSE
3419 : {
3420 34076 : BREAK;
3421 : }
3422 : }
3423 :
3424 : /* number of similar sub-frames starting from the end of the frame */
3425 39626 : IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) ) /* shortcut */
3426 : {
3427 5550 : n_sim_stop = n_sim_start;
3428 5550 : move16();
3429 : }
3430 : ELSE
3431 : {
3432 34076 : n_sim_stop = 1;
3433 34076 : move16();
3434 34076 : FOR( sf_idx = 2; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ )
3435 : {
3436 : /* we need to check only the two middle sub-frames, as all being the same would have taken the shortcut above */
3437 34076 : IF( EQ_16( are_masa_subframes_similar_fx( current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1, current_meta, (UWord8) sub( MAX_PARAM_SPATIAL_SUBFRAMES, sf_idx ) ), TRUE ) )
3438 : {
3439 0 : n_sim_stop = sf_idx;
3440 0 : move16();
3441 : }
3442 : ELSE
3443 : {
3444 34076 : BREAK;
3445 : }
3446 : }
3447 : }
3448 :
3449 39626 : frame_mode = MASA_FRAME_4SF; /* default mode: 4sf */
3450 39626 : move16();
3451 39626 : IF( GT_16( sync_state->prev_offset, MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) )
3452 : {
3453 : /* earlier offset was large => reset the offset */
3454 0 : found_offset = 0;
3455 : }
3456 : ELSE
3457 : {
3458 : /* keep previous offset unless something else is found. alternatively, we could reset always */
3459 39626 : found_offset = sync_state->prev_offset;
3460 : }
3461 39626 : move16();
3462 :
3463 39626 : test();
3464 39626 : test();
3465 39626 : IF( EQ_16( n_sim_start, MAX_PARAM_SPATIAL_SUBFRAMES ) && EQ_16( n_sim_stop, MAX_PARAM_SPATIAL_SUBFRAMES ) )
3466 : {
3467 : /* full frame consists of similar sub-frames */
3468 5550 : frame_mode = MASA_FRAME_1SF;
3469 5550 : move16();
3470 5550 : test();
3471 5550 : IF( ( sync_state->prev_sim_stop != 0 ) && EQ_16( are_masa_subframes_similar_fx( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ), TRUE ) )
3472 : {
3473 : /* > 4 sub-frames of similar data */
3474 0 : IF( LT_16( sync_state->prev_sim_stop, 3 ) )
3475 : {
3476 : /* can nicely align the framing with the earlier data and a small offset */
3477 0 : found_offset = sync_state->prev_sim_stop;
3478 : }
3479 : ELSE
3480 : {
3481 : /* too many similar sub-frames to determine the offset accurately => keep earlier value */
3482 0 : found_offset = sync_state->prev_offset;
3483 : }
3484 0 : move16();
3485 : }
3486 : ELSE
3487 : {
3488 : /* earlier window was different => reset the offset */
3489 5550 : found_offset = 0;
3490 5550 : move16();
3491 : }
3492 : }
3493 34076 : ELSE IF( EQ_16( n_sim_stop, 3 ) )
3494 : {
3495 : /* first sub-frame different that the rest 3
3496 : => make a risky guess that the future sf would be the same too and we're in an offset case */
3497 0 : frame_mode = MASA_FRAME_1SF;
3498 0 : found_offset = 3;
3499 0 : move16();
3500 0 : move16();
3501 : }
3502 34076 : ELSE IF( ( sync_state->prev_sim_stop > 0 ) && EQ_16( are_masa_subframes_similar_fx( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ), TRUE ) )
3503 : {
3504 : /* seeing data similar to past */
3505 0 : test();
3506 0 : IF( GT_16( n_sim_start, 1 ) && ( GE_16( add( n_sim_start, sync_state->prev_sim_stop ), MAX_PARAM_SPATIAL_SUBFRAMES ) ) )
3507 : {
3508 : /* with the past, would have at least one long frame similar subframes */
3509 0 : frame_mode = MASA_FRAME_1SF;
3510 0 : move16();
3511 :
3512 0 : IF( sync_state->prev_offset == 0 )
3513 : {
3514 0 : found_offset = (UWord8) s_min( 2, sync_state->prev_sim_stop );
3515 : }
3516 : ELSE
3517 : {
3518 0 : found_offset = sync_state->prev_offset;
3519 0 : move16();
3520 : }
3521 : }
3522 : }
3523 :
3524 : /* keep the original contents of the frame, but then perform interpolation later */
3525 : /* just copy current frame to storage */
3526 39626 : copy_masa_metadata_fx( current_meta, previous_meta );
3527 :
3528 39626 : sync_state->prev_sim_stop = n_sim_stop;
3529 39626 : sync_state->prev_offset = found_offset;
3530 39626 : sync_state->frame_mode = frame_mode;
3531 39626 : move16();
3532 39626 : move16();
3533 39626 : move16();
3534 :
3535 39626 : return;
3536 : }
3537 :
3538 :
3539 : /*-------------------------------------------------------------------*
3540 : * masa_metadata_direction_alignment()
3541 : *
3542 : * In 2dir MASA metadata, determine the ordering of the directional
3543 : * fields such that the azi/ele change across time is minimized.
3544 : *-------------------------------------------------------------------*/
3545 :
3546 39626 : static void masa_metadata_direction_alignment_fx(
3547 : MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder handle */
3548 : )
3549 : {
3550 : UWord8 band, n_dirs;
3551 : MASA_DIR_ALIGN_HANDLE hAlignState;
3552 : MASA_METADATA_HANDLE hMeta;
3553 39626 : hAlignState = &( hMasa->data.dir_align_state );
3554 39626 : hMeta = &( hMasa->masaMetadata );
3555 :
3556 39626 : n_dirs = (UWord8) add( hMeta->descriptive_meta.numberOfDirections, 1 ); /* 1-based */
3557 39626 : move16();
3558 990650 : FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
3559 : {
3560 : UWord8 sf;
3561 : Word32 diff_swap_fx;
3562 : Word32 diff_no_swap_fx;
3563 :
3564 : /* trade 2*(cos+sin) against storing the values between frames */
3565 : Word16 prev_ele_dir1_sin_fx, prev_ele_dir2_sin_fx;
3566 : Word16 prev_ele_dir1_cos_fx, prev_ele_dir2_cos_fx;
3567 :
3568 951024 : prev_ele_dir1_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3569 951024 : prev_ele_dir2_sin_fx = getSineWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3570 :
3571 951024 : prev_ele_dir1_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir1_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3572 951024 : prev_ele_dir2_cos_fx = getCosWord16R2( extract_l( Mpy_32_32( hAlignState->previous_ele_dir2_fx[band], 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3573 :
3574 4755120 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
3575 : {
3576 : Word32 azi_rad1_fx, ele_rad1_fx;
3577 : Word32 azi_rad2_fx, ele_rad2_fx;
3578 : Word16 cos_ele1_fx, cos_ele2_fx;
3579 : Word16 sin_ele1_fx, sin_ele2_fx;
3580 : Word16 temp1;
3581 : Word32 temp2;
3582 : Word16 temp1_e;
3583 :
3584 :
3585 3804096 : azi_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
3586 3804096 : ele_rad1_fx = Mpy_32_16_1( hMeta->directional_meta[0].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
3587 :
3588 3804096 : IF( GT_16( n_dirs, 1 ) )
3589 : {
3590 950400 : azi_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].azimuth_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
3591 950400 : ele_rad2_fx = Mpy_32_16_1( hMeta->directional_meta[1].elevation_fx[sf][band], 572 /*PI_OVER_180 q15*/ ); /*q22*/
3592 :
3593 950400 : test();
3594 950400 : test();
3595 950400 : test();
3596 950400 : test();
3597 950400 : test();
3598 950400 : test();
3599 : /* quick checks to detect constant data and earlier flip */
3600 950400 : IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
3601 : LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
3602 : LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) &&
3603 : LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) )
3604 : {
3605 91800 : diff_swap_fx = ONE_IN_Q13; /*1 q13*/
3606 91800 : move32();
3607 91800 : diff_no_swap_fx = 0;
3608 91800 : move32();
3609 : /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
3610 91800 : sin_ele1_fx = prev_ele_dir1_sin_fx; /*q15*/
3611 91800 : sin_ele2_fx = prev_ele_dir2_sin_fx; /*q15*/
3612 91800 : cos_ele1_fx = prev_ele_dir1_cos_fx; /*q15*/
3613 91800 : cos_ele2_fx = prev_ele_dir2_cos_fx; /*q15*/
3614 91800 : move16();
3615 91800 : move16();
3616 91800 : move16();
3617 91800 : move16();
3618 : }
3619 858600 : ELSE IF( LT_32( L_abs( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir2_fx[band] ) ), EPSILON_FX ) &&
3620 : LT_32( L_abs( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir1_fx[band] ) ), EPSILON_FX ) &&
3621 : LT_32( L_abs( L_sub( ele_rad1_fx, hAlignState->previous_ele_dir2_fx[band] ) ), EPSILON_FX ) &&
3622 : LT_32( L_abs( L_sub( ele_rad2_fx, hAlignState->previous_ele_dir1_fx[band] ) ), EPSILON_FX ) )
3623 : {
3624 37800 : diff_swap_fx = 0;
3625 37800 : move32();
3626 37800 : diff_no_swap_fx = ONE_IN_Q13; /*1.0 q13*/
3627 37800 : move32();
3628 : /* cached values that will be used for the short-cuts and over-written by the real computations, if done */
3629 37800 : sin_ele1_fx = prev_ele_dir2_sin_fx; /*q15*/
3630 37800 : sin_ele2_fx = prev_ele_dir1_sin_fx; /*q15*/
3631 37800 : cos_ele1_fx = prev_ele_dir2_cos_fx; /*q15*/
3632 37800 : cos_ele2_fx = prev_ele_dir1_cos_fx; /*q15*/
3633 37800 : move16();
3634 37800 : move16();
3635 37800 : move16();
3636 37800 : move16();
3637 : }
3638 : ELSE
3639 : {
3640 : /* angular distance of the two vectors */
3641 : /* pre-compute values for re-use */
3642 820800 : sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3643 820800 : sin_ele2_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3644 :
3645 820800 : cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3646 820800 : cos_ele2_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad2_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3647 :
3648 820800 : temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir1_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3649 820800 : temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ ); /*q15*/
3650 820800 : temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir1_sin_fx ), temp1 ); /*q15*/
3651 820800 : temp1_e = 1; /*stores expoenent for square root operation*/
3652 820800 : move16();
3653 820800 : temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
3654 820800 : temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) ); /*q13*/
3655 820800 : diff_no_swap_fx = L_deposit_l( temp1 ); /*q13*/
3656 :
3657 820800 : temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir2_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3658 820800 : temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ ); /*q15*/
3659 820800 : temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir2_sin_fx ), temp1 ); /*q15*/
3660 820800 : temp1_e = 1; /*stores expoenent for square root operation*/
3661 820800 : move16();
3662 820800 : temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
3663 820800 : temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) ); /*q13*/
3664 820800 : diff_no_swap_fx = L_add( diff_no_swap_fx, temp1 ); /*q13*/
3665 :
3666 820800 : temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad1_fx, hAlignState->previous_azi_dir2_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3667 820800 : temp1 = mult( mult( temp1, cos_ele1_fx ) /*q31*/, prev_ele_dir2_cos_fx /*q15*/ ); /*q15*/
3668 820800 : temp1 = add_sat( mult( sin_ele1_fx, prev_ele_dir2_sin_fx ), temp1 ); /*q15*/
3669 820800 : temp1_e = 1; /*stores expoenent for square root operation*/
3670 820800 : move16();
3671 820800 : temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
3672 820800 : temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) ); /*q13*/
3673 820800 : diff_swap_fx = L_deposit_l( temp1 ); /*q13*/
3674 :
3675 820800 : temp1 = getCosWord16R2( extract_l( Mpy_32_32( L_sub( azi_rad2_fx, hAlignState->previous_azi_dir1_fx[band] ), 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3676 820800 : temp1 = mult( mult( temp1, cos_ele2_fx ) /*q31*/, prev_ele_dir1_cos_fx /*q15*/ ); /*q15*/
3677 820800 : temp1 = add_sat( mult( sin_ele2_fx, prev_ele_dir1_sin_fx ), temp1 ); /*q15*/
3678 820800 : temp1_e = 1; /*stores expoenent for square root operation*/
3679 820800 : move16();
3680 820800 : temp2 = Sqrt32( L_sub( ONE_IN_Q30, L_mult0( temp1, temp1 ) ), &temp1_e ); /*31-temp1_e*/
3681 820800 : temp1 = BASOP_util_atan2( temp2, temp1, sub( temp1_e, 16 ) ); /*q13*/
3682 820800 : diff_swap_fx = L_add( diff_swap_fx, temp1 ); /*q13*/
3683 : }
3684 : }
3685 : ELSE
3686 : {
3687 : /* 1dir */
3688 2853696 : sin_ele1_fx = getSineWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3689 2853696 : cos_ele1_fx = getCosWord16R2( extract_l( Mpy_32_32( ele_rad1_fx, 2670177 /*2^24/(2*pi)*/ ) ) ); /*q15*/
3690 :
3691 2853696 : azi_rad2_fx = 0;
3692 2853696 : ele_rad2_fx = 0;
3693 2853696 : move32();
3694 2853696 : move32();
3695 :
3696 2853696 : sin_ele2_fx = 0; /* sin(0) */
3697 2853696 : cos_ele2_fx = MAX_16; /* cos(0) in Q15*/
3698 2853696 : move16();
3699 2853696 : move16();
3700 :
3701 2853696 : diff_swap_fx = ONE_IN_Q13; /*1.0 in Q13*/
3702 2853696 : diff_no_swap_fx = 0;
3703 2853696 : move32();
3704 2853696 : move32();
3705 : }
3706 :
3707 3804096 : test();
3708 3804096 : IF( GT_16( n_dirs, 1 ) && GT_32( diff_no_swap_fx, diff_swap_fx ) )
3709 121788 : {
3710 : /* swap the metadata of the two directions in this TF-tile */
3711 : Word32 tmp_val;
3712 : Word16 tmp_val_16;
3713 : UWord16 tmp_int_val;
3714 121788 : tmp_val = hMeta->directional_meta[0].azimuth_fx[sf][band]; /*q22*/
3715 121788 : hMeta->directional_meta[0].azimuth_fx[sf][band] = hMeta->directional_meta[1].azimuth_fx[sf][band]; /*q22*/
3716 121788 : hMeta->directional_meta[1].azimuth_fx[sf][band] = tmp_val; /*q22*/
3717 121788 : move32();
3718 121788 : move32();
3719 121788 : move32();
3720 :
3721 121788 : tmp_val = hMeta->directional_meta[0].elevation_fx[sf][band]; /*q22*/
3722 121788 : hMeta->directional_meta[0].elevation_fx[sf][band] = hMeta->directional_meta[1].elevation_fx[sf][band]; /*q22*/
3723 121788 : hMeta->directional_meta[1].elevation_fx[sf][band] = tmp_val; /*q22*/
3724 121788 : move32();
3725 121788 : move32();
3726 121788 : move32();
3727 :
3728 121788 : tmp_int_val = hMeta->directional_meta[0].spherical_index[sf][band]; /*q0*/
3729 121788 : hMeta->directional_meta[0].spherical_index[sf][band] = hMeta->directional_meta[1].spherical_index[sf][band]; /*q0*/
3730 121788 : hMeta->directional_meta[1].spherical_index[sf][band] = tmp_int_val; /*q0*/
3731 121788 : move32();
3732 121788 : move32();
3733 121788 : move32();
3734 :
3735 121788 : tmp_val = hMeta->directional_meta[0].energy_ratio_fx[sf][band]; /*q30*/
3736 121788 : hMeta->directional_meta[0].energy_ratio_fx[sf][band] = hMeta->directional_meta[1].energy_ratio_fx[sf][band]; /*q30*/
3737 121788 : hMeta->directional_meta[1].energy_ratio_fx[sf][band] = tmp_val; /*q30*/
3738 121788 : move32();
3739 121788 : move32();
3740 121788 : move32();
3741 :
3742 121788 : tmp_val_16 = hMeta->directional_meta[0].spread_coherence_fx[sf][band]; /*q15*/
3743 121788 : hMeta->directional_meta[0].spread_coherence_fx[sf][band] = hMeta->directional_meta[1].spread_coherence_fx[sf][band]; /*q15*/
3744 121788 : hMeta->directional_meta[1].spread_coherence_fx[sf][band] = tmp_val_16; /*q15*/
3745 121788 : move16();
3746 121788 : move16();
3747 121788 : move16();
3748 :
3749 121788 : hAlignState->previous_azi_dir1_fx[band] = azi_rad2_fx; /*q22*/
3750 121788 : hAlignState->previous_ele_dir1_fx[band] = ele_rad2_fx; /*q22*/
3751 121788 : move32();
3752 121788 : move32();
3753 :
3754 121788 : hAlignState->previous_azi_dir2_fx[band] = azi_rad1_fx; /*q22*/
3755 121788 : hAlignState->previous_ele_dir2_fx[band] = ele_rad1_fx; /*q22*/
3756 121788 : move32();
3757 121788 : move32();
3758 :
3759 121788 : prev_ele_dir1_cos_fx = cos_ele2_fx; /*q15*/
3760 121788 : prev_ele_dir1_sin_fx = sin_ele2_fx; /*q15*/
3761 121788 : move16();
3762 121788 : move16();
3763 :
3764 121788 : prev_ele_dir2_cos_fx = cos_ele1_fx; /*q15*/
3765 121788 : prev_ele_dir2_sin_fx = sin_ele1_fx; /*q15*/
3766 121788 : move16();
3767 121788 : move16();
3768 : }
3769 : ELSE
3770 : {
3771 3682308 : hAlignState->previous_azi_dir1_fx[band] = azi_rad1_fx; /*q22*/
3772 3682308 : hAlignState->previous_ele_dir1_fx[band] = ele_rad1_fx; /*q22*/
3773 3682308 : move32();
3774 3682308 : move32();
3775 :
3776 3682308 : hAlignState->previous_azi_dir2_fx[band] = azi_rad2_fx; /*q22*/
3777 3682308 : hAlignState->previous_ele_dir2_fx[band] = ele_rad2_fx; /*q22*/
3778 3682308 : move32();
3779 3682308 : move32();
3780 :
3781 3682308 : prev_ele_dir1_cos_fx = cos_ele1_fx; /*q15*/
3782 3682308 : prev_ele_dir1_sin_fx = sin_ele1_fx; /*q15*/
3783 3682308 : move16();
3784 3682308 : move16();
3785 :
3786 3682308 : prev_ele_dir2_cos_fx = cos_ele2_fx; /*q15*/
3787 3682308 : prev_ele_dir2_sin_fx = sin_ele2_fx; /*q15*/
3788 3682308 : move16();
3789 3682308 : move16();
3790 : }
3791 : } /* sf */
3792 : } /* band */
3793 :
3794 39626 : return;
3795 : }
3796 :
3797 :
3798 : /*-------------------------------------------------------------------*
3799 : * ivas_merge_masa_metadata()
3800 : *
3801 : *
3802 : *-------------------------------------------------------------------*/
3803 :
3804 3996 : void ivas_merge_masa_metadata_fx(
3805 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA enc handle. source for MASA metadata and combined metadata will be here */
3806 : OMASA_SPATIAL_META_HANDLE hOMasaMeta /* i : ISM-object metadata to be merged with the MASA metadata */
3807 : )
3808 : {
3809 : Word16 sf, band;
3810 : UWord8 numCodingBands;
3811 : UWord8 numDirections;
3812 : UWord8 numSf;
3813 : MASA_METADATA_HANDLE hMeta;
3814 : Word16 energyTimesRatioMASA_e[2];
3815 : Word16 total_diff_nrg_e;
3816 : Word16 energyMerged_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
3817 : Word32 energyTimesRatioISM_fx; /*energyTimesRatioISM_e*/
3818 : Word16 energyTimesRatioISM_e;
3819 : Word32 energyTimesRatioMASA_fx[2]; /*energyTimesRatioMASA_e*/
3820 : Word32 total_diff_nrg_fx;
3821 : Word32 eneBand_fx; /*eneBand_e*/
3822 : Word16 eneBand_e;
3823 : Word32 energyMerged_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /*energyMerged_e*/
3824 3996 : OMASA_ENCODER_ENERGY_HANDLE hOmasaEnergy = hMasa->data.hOmasaData->hOmasaEnergy;
3825 : Word32 temp1 /*temp1_e*/, temp2 /*temp2_e*/;
3826 : Word16 temp1_e, temp2_e;
3827 :
3828 3996 : numCodingBands = hMasa->config.numCodingBands;
3829 3996 : numDirections = hMasa->config.numberOfDirections;
3830 3996 : IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
3831 : {
3832 0 : numSf = 1;
3833 : }
3834 : ELSE
3835 : {
3836 3996 : numSf = MAX_PARAM_SPATIAL_SUBFRAMES;
3837 : }
3838 3996 : move16();
3839 3996 : move16();
3840 3996 : move16();
3841 3996 : hMeta = &( hMasa->masaMetadata );
3842 :
3843 19980 : FOR( sf = 0; sf < numSf; sf++ )
3844 : {
3845 396000 : FOR( band = 0; band < numCodingBands; band++ )
3846 : {
3847 : Word16 merge_dest;
3848 : Word32 dir_sum_fx; /*dir_sum_e*/
3849 : Word16 dir_sum_e;
3850 : UWord8 band_n_dirs;
3851 380016 : test();
3852 380016 : test();
3853 380016 : IF( EQ_16( numDirections, 1 ) || ( EQ_16( numDirections, 2 ) && hMasa->data.twoDirBands[band] == 0 ) )
3854 : {
3855 380016 : band_n_dirs = 1;
3856 : }
3857 : ELSE
3858 : {
3859 0 : band_n_dirs = 2;
3860 : }
3861 380016 : move16();
3862 :
3863 : /* Compute energies */
3864 380016 : eneBand_fx = hMasa->data.energy_fx[sf][band];
3865 380016 : eneBand_e = hMasa->data.energy_e[sf][band];
3866 380016 : move32();
3867 380016 : move16();
3868 380016 : energyMerged_fx[sf][band] = BASOP_Util_Add_Mant32Exp( eneBand_fx, eneBand_e, hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ism_fx_e[sf][band], &energyMerged_e[sf][band] );
3869 380016 : move32();
3870 :
3871 : /* Compute weights */
3872 380016 : energyTimesRatioMASA_fx[0] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] );
3873 380016 : energyTimesRatioMASA_e[0] = add( eneBand_e, 1 );
3874 380016 : move32();
3875 380016 : move16();
3876 380016 : IF( EQ_16( band_n_dirs, 2 ) )
3877 : {
3878 0 : energyTimesRatioMASA_fx[1] = Mpy_32_32( eneBand_fx, hMeta->directional_meta[1].energy_ratio_fx[sf][band] ); // energyTimesRatioMASA_e
3879 0 : energyTimesRatioMASA_e[1] = add( eneBand_e, 1 );
3880 : }
3881 : ELSE
3882 : {
3883 380016 : energyTimesRatioMASA_fx[1] = 0; // energyTimesRatioMASA_e
3884 380016 : energyTimesRatioMASA_e[1] = 0;
3885 : }
3886 380016 : move32();
3887 380016 : move16();
3888 :
3889 : /* target is original MASA diffuseness */
3890 380016 : total_diff_nrg_fx = Mpy_32_32( eneBand_fx, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] ); // total_diff_nrg_e
3891 380016 : total_diff_nrg_e = add( eneBand_e, 1 );
3892 :
3893 : /* criterion is mean of ISM ratio and new ratio */
3894 380016 : temp1 = BASOP_Util_Add_Mant32Exp( L_add( EPSILON_FX, eneBand_fx ), eneBand_e, hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ism_fx_e[sf][band], &temp1_e ); /* EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band]*/
3895 380016 : temp2 = L_deposit_h( BASOP_Util_Divide3232_Scale( total_diff_nrg_fx, temp1, &temp2_e ) ); /*temp2_e*/ /*total_diff_nrg / ( EPSILON + eneBand + hMasa->data.hOmasaData->energy_ism[sf][band] )*/
3896 380016 : temp2_e = add( temp2_e, sub( total_diff_nrg_e, temp1_e ) );
3897 380016 : IF( temp2_e < 0 )
3898 : {
3899 283974 : temp2 = L_shl( temp2, temp2_e );
3900 283974 : temp2_e = 0;
3901 283974 : move16();
3902 : }
3903 380016 : temp2 = L_sub( L_shl_sat( 1, sub( 31, temp2_e ) ), temp2 ); /*( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] ) )*/
3904 380016 : temp2 = BASOP_Util_Add_Mant32Exp( hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band], 1, temp2, temp2_e, &temp2_e ); /*( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] ) )*/
3905 380016 : energyTimesRatioISM_fx = Mpy_32_32( L_shr( temp2, 1 ), hOmasaEnergy->energy_ism_fx[sf][band] ); /*energyTimesRatioISM_e*/
3906 380016 : energyTimesRatioISM_e = add( temp2_e, hOmasaEnergy->energy_ism_fx_e[sf][band] );
3907 : /*energyTimesRatioISM = ( hOMasaMeta->directional_meta[0].energy_ratio[sf][band] + ( 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] ) ) ) / 2.0f * hOmasaEnergy->energy_ism[sf][band];*/
3908 :
3909 : /* Determine combined metadata based on the weights */
3910 380016 : merge_dest = -1;
3911 380016 : move16();
3912 380016 : test();
3913 380016 : test();
3914 380016 : test();
3915 380016 : test();
3916 380016 : test();
3917 380016 : test();
3918 380016 : IF( ( EQ_16( band_n_dirs, 1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) ) ||
3919 : ( EQ_16( band_n_dirs, 2 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1] ), -1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) ) )
3920 : {
3921 : /* 1dir and ISM the most energetic, or 2dir and ISM the more energetic than MASA1 */
3922 143404 : merge_dest = 0;
3923 : }
3924 236612 : ELSE IF( EQ_16( band_n_dirs, 2 ) && NE_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1], energyTimesRatioMASA_fx[0], energyTimesRatioMASA_e[0] ), 1 ) && EQ_16( BASOP_Util_Cmp_Mant32Exp( energyTimesRatioMASA_fx[1], energyTimesRatioMASA_e[1], energyTimesRatioISM_fx, energyTimesRatioISM_e ), -1 ) )
3925 : {
3926 : /* 2dir and ISM the most energetic and MASA2 the least energetic */
3927 0 : merge_dest = 1;
3928 : }
3929 380016 : move16();
3930 :
3931 380016 : IF( merge_dest >= 0 ) /* replace one MASA with ISM */
3932 : {
3933 143404 : hMeta->directional_meta[merge_dest].azimuth_fx[sf][band] = hOMasaMeta->directional_meta[0].azimuth_fx[sf][band]; /*q22*/
3934 143404 : hMeta->directional_meta[merge_dest].elevation_fx[sf][band] = hOMasaMeta->directional_meta[0].elevation_fx[sf][band]; /*q22*/
3935 143404 : move32();
3936 143404 : move32();
3937 : /* limit with the earlier direct-energy ratio */
3938 143404 : dir_sum_fx = temp2; /* new dir ratio */
3939 143404 : dir_sum_e = temp2_e;
3940 143404 : move32();
3941 143404 : move16();
3942 : /*dir_sum = 1.0f - total_diff_nrg / ( EPSILON + eneBand + hOmasaEnergy->energy_ism[sf][band] )*/
3943 143404 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( dir_sum_fx, dir_sum_e, hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band], 1 ), -1 ) )
3944 : {
3945 0 : hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = L_shl( dir_sum_fx, sub( dir_sum_e, 1 ) ); /*scaling to Q30*/
3946 : }
3947 : ELSE
3948 : {
3949 143404 : hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] = hOMasaMeta->directional_meta[0].energy_ratio_fx[sf][band]; /*q30*/
3950 143404 : move32();
3951 : }
3952 : /* clip with original ISM dir */
3953 143404 : hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = L_sub( ONE_IN_Q30, hMeta->directional_meta[merge_dest].energy_ratio_fx[sf][band] ); /*q30*/
3954 143404 : move32();
3955 143404 : move32(); /*hMeta->directional_meta[merge_dest].energy_ratio_fx*/
3956 :
3957 143404 : IF( hMasa->config.useCoherence )
3958 : {
3959 0 : hMeta->directional_meta[merge_dest].spread_coherence_fx[sf][band] = hOMasaMeta->directional_meta[0].spread_coherence_fx[sf][band]; /*q15*/
3960 0 : hMeta->common_meta.surround_coherence_fx[sf][band] = hOMasaMeta->common_meta.surround_coherence_fx[sf][band]; /*q15*/
3961 0 : move16();
3962 0 : move16();
3963 : }
3964 :
3965 : /* recompute direct energy ratios to match the diffuse ratio */
3966 : Word32 direct_quota_fx, direct_scaler_fx;
3967 : Word16 direct_scaler_e;
3968 143404 : direct_quota_fx = L_sub( ONE_IN_Q30, hMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] );
3969 143404 : IF( EQ_16( band_n_dirs, 1 ) )
3970 : {
3971 143404 : hMeta->directional_meta[0].energy_ratio_fx[sf][band] = direct_quota_fx; /*q30*/
3972 143404 : move32();
3973 : }
3974 : ELSE
3975 : {
3976 0 : dir_sum_fx = L_add( hMeta->directional_meta[0].energy_ratio_fx[sf][band], hMeta->directional_meta[1].energy_ratio_fx[sf][band] ); /*q30*/
3977 0 : direct_scaler_fx = BASOP_Util_Divide3232_Scale( direct_quota_fx, L_add( EPSILON_FX, dir_sum_fx ), &direct_scaler_e );
3978 0 : direct_scaler_fx = L_shl( direct_scaler_fx, direct_scaler_e ); /*q31*/
3979 0 : direct_scaler_e = 0;
3980 0 : move16();
3981 0 : hMeta->directional_meta[0].energy_ratio_fx[sf][band] = Mpy_32_32( direct_scaler_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] ); /*q30*/
3982 0 : hMeta->directional_meta[1].energy_ratio_fx[sf][band] = Mpy_32_32( direct_scaler_fx, hMeta->directional_meta[0].energy_ratio_fx[sf][band] ); /*q30*/
3983 0 : move32();
3984 0 : move32();
3985 : }
3986 : }
3987 : }
3988 : }
3989 :
3990 19980 : FOR( sf = 0; sf < numSf; sf++ )
3991 : {
3992 396000 : FOR( band = 0; band < numCodingBands; band++ )
3993 : {
3994 380016 : hMasa->data.energy_fx[sf][band] = energyMerged_fx[sf][band];
3995 380016 : hMasa->data.energy_e[sf][band] = energyMerged_e[sf][band];
3996 380016 : move32();
3997 380016 : move16();
3998 : }
3999 : }
4000 :
4001 3996 : return;
4002 : }
4003 :
4004 :
4005 30442 : static void quantize_ratio_ism_vector_ivas_fx(
4006 : const Word16 *ratio_ism, /* ratio_ism_e */
4007 : Word16 ratio_ism_e,
4008 : Word16 *idx, /* Q0 */
4009 : const Word16 nchan_ism,
4010 : const Word32 masa_to_total_energy_ratio,
4011 : const Word16 idx_sep_object )
4012 : {
4013 : Word16 i, j, best_i, best_i2;
4014 : Word16 dist, div, tmp, dist2, best_dist, temp, temp_e, tmp_e, idx_e, best_dist_e, dist_e, dist2_e;
4015 : Word16 part_idx_sum, max_sum_idx;
4016 : Word16 ratio_ism_loc[MAX_NUM_OBJECTS];
4017 : Word16 no_ism_loc;
4018 :
4019 30442 : max_sum_idx = sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 );
4020 :
4021 30442 : test();
4022 30442 : IF( GT_16( idx_sep_object, -1 ) )
4023 : {
4024 30442 : temp = BASOP_Util_Divide1616_Scale( 1, max_sum_idx, &temp_e );
4025 30442 : BASOP_Util_Add_MantExp( ratio_ism[idx_sep_object], ratio_ism_e, negate( temp ), temp_e, &tmp );
4026 :
4027 30442 : test();
4028 30442 : IF( tmp < 0 )
4029 : {
4030 : /* take it out from quantize function */
4031 28839 : Copy( ratio_ism, ratio_ism_loc, idx_sep_object ); // Q(15 - ratio_ism_e)
4032 28839 : Copy( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 );
4033 28839 : no_ism_loc = sub( nchan_ism, 1 );
4034 : }
4035 : ELSE
4036 : {
4037 1603 : no_ism_loc = nchan_ism;
4038 1603 : move16();
4039 1603 : Copy( ratio_ism, ratio_ism_loc, nchan_ism );
4040 : }
4041 : }
4042 : ELSE
4043 : {
4044 0 : no_ism_loc = nchan_ism;
4045 0 : move16();
4046 0 : Copy( ratio_ism, ratio_ism_loc, nchan_ism );
4047 : }
4048 :
4049 30442 : test();
4050 30442 : IF( GT_16( nchan_ism, 1 ) )
4051 : {
4052 30442 : test();
4053 30442 : IF( GE_32( masa_to_total_energy_ratio, MASA2TOTAL_THR_Q30 ) )
4054 : {
4055 3593 : distribute_evenly_ism_fx( idx, max_sum_idx, nchan_ism );
4056 : }
4057 : ELSE
4058 : {
4059 26849 : test();
4060 26849 : IF( GT_16( no_ism_loc, 1 ) )
4061 : {
4062 :
4063 26135 : dist = 0;
4064 26135 : dist_e = 0;
4065 26135 : div = div_s( 1, max_sum_idx ); // Q15
4066 26135 : move16();
4067 26135 : move16();
4068 :
4069 26135 : part_idx_sum = 0;
4070 26135 : move16();
4071 :
4072 95154 : FOR( i = 0; i < no_ism_loc; i++ )
4073 : {
4074 69019 : idx[i] = extract_l( L_shr( L_mult0( ratio_ism_loc[i], max_sum_idx ), sub( 15, ratio_ism_e ) ) ); // Q0
4075 69019 : move16();
4076 69019 : part_idx_sum = add( part_idx_sum, idx[i] );
4077 :
4078 69019 : tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( imult1616( idx[i], div ) ), 0, &tmp ); // tmp_e
4079 69019 : dist_e = BASOP_Util_Add_MantExp( dist, dist_e, mult( tmp, tmp ), add( tmp_e, tmp_e ), &dist ); // dist_e
4080 : }
4081 :
4082 26135 : best_dist = dist;
4083 26135 : best_dist_e = dist_e;
4084 26135 : best_i2 = -1;
4085 26135 : move16();
4086 26135 : move16();
4087 26135 : move16();
4088 :
4089 54125 : WHILE( ( part_idx_sum < max_sum_idx ) )
4090 : {
4091 27990 : best_i = -1;
4092 27990 : move16();
4093 : /* check which index to increase by 1 for a possible improvement */
4094 :
4095 102694 : FOR( i = 0; i < no_ism_loc; i++ )
4096 : {
4097 74704 : idx[i] = add( idx[i], 1 );
4098 74704 : move16();
4099 74704 : dist2 = 0;
4100 74704 : dist2_e = 0;
4101 74704 : move16();
4102 74704 : move16();
4103 :
4104 282160 : FOR( j = 0; j < no_ism_loc; j++ )
4105 : {
4106 207456 : Word32 temp1 = L_mult( idx[i], div ); // Q : 15 + 0 + 1
4107 207456 : Word16 temp1_n = norm_l( temp1 );
4108 207456 : Word16 temp1_16 = extract_h( L_shl( temp1, temp1_n ) ); // Q : Q + temp1_n - 16
4109 207456 : tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( temp1_16 ), sub( 15, temp1_n ), &tmp ); // tmp_e
4110 207456 : dist2_e = BASOP_Util_Add_MantExp( dist2, dist2_e, mult_sat( tmp, tmp ), add( tmp_e, tmp_e ), &dist2 ); // dist_e
4111 : }
4112 :
4113 74704 : BASOP_Util_Add_MantExp( dist2, dist2_e, negate( best_dist ), best_dist_e, &tmp );
4114 74704 : test();
4115 74704 : IF( tmp < 0 )
4116 : {
4117 22940 : best_i2 = best_i;
4118 22940 : best_i = i;
4119 22940 : best_dist = dist2;
4120 22940 : best_dist_e = dist2_e;
4121 22940 : move16();
4122 22940 : move16();
4123 22940 : move16();
4124 22940 : move16();
4125 : }
4126 74704 : idx[i] = sub( idx[i], 1 );
4127 74704 : move16();
4128 : }
4129 :
4130 27990 : test();
4131 27990 : IF( GT_16( best_i, -1 ) )
4132 : {
4133 21734 : idx[best_i] = add( idx[best_i], 1 );
4134 21734 : move16();
4135 21734 : part_idx_sum = add( part_idx_sum, 1 );
4136 : }
4137 : ELSE
4138 : {
4139 6256 : test();
4140 6256 : IF( GT_16( best_i2, -1 ) )
4141 : {
4142 1043 : idx[best_i2] = add( idx[best_i2], 1 );
4143 1043 : move16();
4144 1043 : part_idx_sum = add( part_idx_sum, 1 );
4145 : }
4146 : ELSE
4147 : {
4148 5213 : idx[no_ism_loc - 1] = add( idx[no_ism_loc - 1], sub( max_sum_idx, part_idx_sum ) );
4149 5213 : move16();
4150 5213 : part_idx_sum = max_sum_idx;
4151 5213 : move16();
4152 : }
4153 : }
4154 : }
4155 26135 : assert( sum_s( idx, no_ism_loc ) == max_sum_idx );
4156 : }
4157 : ELSE
4158 : {
4159 714 : idx[0] = max_sum_idx;
4160 714 : move16();
4161 : }
4162 :
4163 26849 : test();
4164 26849 : IF( LT_16( no_ism_loc, nchan_ism ) )
4165 : {
4166 : /* insert back the ratio of the separated object */
4167 70971 : FOR( i = nchan_ism - 1; i > idx_sep_object; i-- )
4168 : {
4169 45655 : idx[i] = idx[i - 1];
4170 45655 : move16();
4171 : }
4172 25316 : idx[idx_sep_object] = 0;
4173 25316 : move16();
4174 : }
4175 : }
4176 : }
4177 : ELSE
4178 : {
4179 : // idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f );
4180 0 : tmp = imult1616( ratio_ism[0], sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 ) ); // tmp_e
4181 0 : tmp_e = ratio_ism_e;
4182 0 : move16();
4183 0 : idx_e = BASOP_Util_Add_MantExp( tmp, tmp_e, 16384 /* 0.5 in Q15 */, 0, &idx[0] ); // idx_e
4184 0 : idx[0] = shl( idx[0], sub( idx_e, 15 ) ); // Q0
4185 0 : move16();
4186 : }
4187 :
4188 30442 : return;
4189 : }
4190 :
4191 :
4192 6665 : static Word16 index_slice_enum_fx(
4193 : const Word16 *ratio_ism_idx,
4194 : const Word16 nchan_ism )
4195 : {
4196 : Word16 i;
4197 : Word16 x, index;
4198 : Word16 base;
4199 :
4200 6665 : IF( EQ_16( nchan_ism, 2 ) )
4201 : {
4202 308 : index = ratio_ism_idx[0];
4203 308 : move16();
4204 : }
4205 : ELSE
4206 : {
4207 6357 : x = ratio_ism_idx[nchan_ism - 2];
4208 6357 : base = 10;
4209 6357 : move16();
4210 6357 : move16();
4211 17248 : FOR( i = nchan_ism - 3; i >= 0; i-- )
4212 : {
4213 10891 : x = add( x, imult1616( ratio_ism_idx[i], base ) );
4214 10891 : base = imult1616( base, 10 );
4215 : }
4216 :
4217 6357 : index = 0;
4218 6357 : i = 0;
4219 6357 : move16();
4220 6357 : move16();
4221 928866 : WHILE( LE_16( i, x ) )
4222 : {
4223 922509 : IF( valid_ratio_index_fx( i, 7, nchan_ism - 1 ) )
4224 : {
4225 252718 : index = add( index, 1 );
4226 : }
4227 922509 : i = add( i, 1 );
4228 : }
4229 6357 : index = sub( index, 1 );
4230 : }
4231 :
4232 6665 : return index;
4233 : }
4234 :
4235 61502 : static void transform_difference_index_ivas_fx(
4236 : const Word16 *diff_idx,
4237 : Word16 *idx,
4238 : const Word16 len )
4239 : {
4240 : Word16 i;
4241 189070 : FOR( i = 0; i < len; i++ )
4242 : {
4243 127568 : IF( diff_idx[i] <= 0 )
4244 : {
4245 99618 : idx[i] = negate( shl( diff_idx[i], 1 ) );
4246 99618 : move16();
4247 : }
4248 : ELSE
4249 : {
4250 27950 : idx[i] = sub( shl( diff_idx[i], 1 ), 1 );
4251 27950 : move16();
4252 : }
4253 : }
4254 :
4255 61502 : return;
4256 : }
4257 :
4258 :
4259 20139 : static void transform_index_and_GR_encode_ivas_fx(
4260 : Word16 *diff_idx, /* i : differenc eindex to encode */
4261 : const Word16 len, /* i : input length */
4262 : const Word16 GR_order, /* i : GR order */
4263 : BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */
4264 : )
4265 : {
4266 : Word16 i;
4267 : Word16 idx[IVAS_MAX_NUM_OBJECTS];
4268 :
4269 : /* transform difference index into positive */
4270 20139 : transform_difference_index_ivas_fx( diff_idx, idx, len );
4271 :
4272 : /* GR encoding */
4273 61030 : FOR( i = 0; i < len; i++ )
4274 : {
4275 40891 : ivas_qmetadata_encode_extended_gr_fx( hMetaData, idx[i], 100, GR_order );
4276 : }
4277 :
4278 20139 : return;
4279 : }
4280 :
4281 :
4282 1862 : static Word16 try_differential_fx(
4283 : const Word16 numCodingBands,
4284 : const Word32 *masa_to_total_energy_ratio, /* Q30 */
4285 : Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
4286 : const Word16 nchan_ism,
4287 : const Word16 bits_index,
4288 : Word16 *p_b_signif )
4289 : {
4290 : Word16 b, i;
4291 : Word16 nbits0;
4292 : Word16 b_signif;
4293 : Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
4294 : Word16 diff_idx[MAX_NUM_OBJECTS];
4295 :
4296 1862 : b_signif = 0;
4297 1862 : move16();
4298 2162 : WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
4299 : {
4300 300 : test();
4301 300 : b_signif = add( b_signif, 1 );
4302 : }
4303 :
4304 1862 : nbits0 = 0;
4305 1862 : move16();
4306 :
4307 1862 : IF( LT_16( b_signif, numCodingBands ) )
4308 : {
4309 1806 : nbits0 = bits_index;
4310 1806 : move16();
4311 1806 : Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
4312 :
4313 11560 : FOR( b = b_signif + 1; b < numCodingBands; b++ )
4314 : {
4315 9754 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4316 : {
4317 8627 : v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
4318 8627 : Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
4319 :
4320 : /* transform difference index into positive */
4321 8627 : transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( nchan_ism, 1 ) );
4322 :
4323 : /* GR encoding */
4324 30122 : FOR( i = 0; i < nchan_ism - 1; i++ )
4325 : {
4326 21495 : nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
4327 : }
4328 : }
4329 : }
4330 : }
4331 1862 : *p_b_signif = b_signif;
4332 1862 : move16();
4333 :
4334 1862 : return nbits0;
4335 : }
4336 :
4337 :
4338 666 : static void differential_coding_first_subframe_ivas_fx(
4339 : BSTR_ENC_HANDLE hMetaData,
4340 : const Word32 *masa_to_total_energy_ratio, // Q30
4341 : const Word16 b_signif,
4342 : Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
4343 : const Word16 nchan_ism,
4344 : const Word16 numCodingBands,
4345 : const Word16 bits_index )
4346 : {
4347 : Word16 index, b;
4348 : Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
4349 : Word16 diff_idx[MAX_NUM_OBJECTS];
4350 :
4351 : /* differential encoding*/
4352 666 : push_next_indice( hMetaData, 0, 1 );
4353 :
4354 666 : IF( LT_16( b_signif, numCodingBands ) )
4355 : {
4356 666 : index = index_slice_enum_fx( ratio_ism_idx[b_signif], nchan_ism );
4357 666 : push_next_indice( hMetaData, index, bits_index );
4358 :
4359 666 : Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
4360 :
4361 4892 : FOR( b = b_signif + 1; b < numCodingBands; b++ )
4362 : {
4363 4226 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4364 : {
4365 3768 : v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
4366 3768 : Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
4367 :
4368 : /* transform difference index into positive */
4369 3768 : transform_index_and_GR_encode_ivas_fx( diff_idx, sub( nchan_ism, 1 ), 0, hMetaData );
4370 : }
4371 : }
4372 : }
4373 :
4374 666 : return;
4375 : }
4376 :
4377 :
4378 1140 : static void independent_coding_ratio_ism_idx_fx(
4379 : Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i : ISM ratios */
4380 : const Word32 *masa_to_total_energy_ratio, /* i : MASA to total ratios, Q30 */
4381 : const Word16 nchan_ism, /* i : number of objects */
4382 : const Word16 numCodingBands, /* i : number of subbands */
4383 : const Word16 bits_index, /* i : number of bits per index */
4384 : BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */
4385 : )
4386 : {
4387 : Word16 b, index;
4388 :
4389 7844 : FOR( b = 0; b < numCodingBands; b++ )
4390 : {
4391 6704 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4392 : {
4393 5999 : index = index_slice_enum_fx( ratio_ism_idx[b], nchan_ism );
4394 5999 : push_next_indice( hMetaData, index, bits_index );
4395 : }
4396 : }
4397 :
4398 1140 : return;
4399 : }
4400 :
4401 :
4402 29124 : static void remove_sep_obj_fx(
4403 : Word16 *diff_idx, /* i/o: array of difference of indexes */
4404 : const Word16 nchan_ism, /* i : number of objects */
4405 : const Word16 idx_sep_obj /* i : index of separated object, to be taken out of array */
4406 : )
4407 : {
4408 : Word16 i;
4409 :
4410 88197 : FOR( i = idx_sep_obj; i < nchan_ism - 1; i++ )
4411 : {
4412 59073 : diff_idx[i] = diff_idx[i + 1];
4413 59073 : move16();
4414 : }
4415 :
4416 29124 : return;
4417 : }
4418 :
4419 :
4420 32736 : static void estimate_bits_subband_ism_ratio_fx(
4421 : const Word16 *ratio_ism_idx,
4422 : const Word16 *ratio_ism_idx_ref, /* ( i/o ) */
4423 : const Word16 nchan_ism,
4424 : const Word16 shift_one,
4425 : const Word16 idx_sep_obj,
4426 : Word16 *p_nbits0,
4427 : Word16 *p_nbits1 )
4428 : {
4429 : Word16 diff_idx[MAX_NUM_OBJECTS];
4430 : Word16 nbits0, nbits1;
4431 : Word16 i;
4432 :
4433 32736 : nbits0 = 0;
4434 32736 : nbits1 = 0;
4435 32736 : move16();
4436 32736 : move16();
4437 :
4438 : /* take difference with respect to previous subframe */
4439 32736 : v_sub_s16_fx( ratio_ism_idx, ratio_ism_idx_ref, diff_idx, nchan_ism );
4440 :
4441 32736 : IF( shift_one )
4442 : {
4443 19416 : remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj );
4444 : }
4445 :
4446 : /* transform difference index into positive */
4447 32736 : transform_difference_index_ivas_fx( diff_idx, diff_idx, sub( sub( nchan_ism, 1 ), shift_one ) );
4448 :
4449 : /* GR encoding */
4450 97918 : FOR( i = 0; i < nchan_ism - 1 - shift_one; i++ )
4451 : {
4452 65182 : nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 0 ) );
4453 65182 : nbits1 = add( nbits1, ivas_qmetadata_encode_extended_gr_length_fx( diff_idx[i], 100, 1 ) );
4454 : }
4455 :
4456 32736 : *p_nbits0 = nbits0;
4457 32736 : *p_nbits1 = nbits1;
4458 32736 : move16();
4459 32736 : move16();
4460 :
4461 32736 : return;
4462 : }
4463 :
4464 :
4465 5636 : static Word16 encode_ratio_ism_subframe_fx(
4466 : Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
4467 : const Word16 nchan_ism,
4468 : const UWord8 numCodingBands,
4469 : const Word16 sf,
4470 : Word16 ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS],
4471 : BSTR_ENC_HANDLE hMetaData,
4472 : const Word32 *masa_to_total_energy_ratio, /* Q30 */
4473 : const Word16 shift_one,
4474 : const Word16 idx_separated_obj )
4475 : {
4476 : Word16 b, b_signif;
4477 : Word16 diff_idx[MAX_NUM_OBJECTS];
4478 : Word16 nbits, nbits0, nbits1, GR_order, GR_order_sb;
4479 : Word16 differential_subframe;
4480 : Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS];
4481 : Word16 bits_index;
4482 : Word16 nbits00, nbits11;
4483 : Word16 idx_sep_obj_local;
4484 :
4485 5636 : idx_sep_obj_local = idx_separated_obj;
4486 5636 : move16();
4487 5636 : IF( GT_16( idx_separated_obj, -1 ) )
4488 : {
4489 5636 : if ( EQ_16( idx_separated_obj, sub( nchan_ism, 1 ) ) )
4490 : {
4491 803 : idx_sep_obj_local = 0;
4492 803 : move16();
4493 : }
4494 : }
4495 5636 : nbits = 0;
4496 5636 : nbits0 = 0;
4497 5636 : nbits1 = 0;
4498 5636 : move16();
4499 5636 : move16();
4500 5636 : move16();
4501 :
4502 5636 : differential_subframe = 1; /* the differences are taken with respect to previous subframe */
4503 5636 : move16();
4504 :
4505 : /* first subframe */
4506 5636 : bits_index = 0;
4507 5636 : move16();
4508 5636 : IF( sf == 0 )
4509 : {
4510 1862 : bits_index = bits_index_ism_ratio_fx( nchan_ism );
4511 :
4512 1862 : nbits = 0;
4513 1862 : move16();
4514 13722 : FOR( b = 0; b < numCodingBands; b++ )
4515 : {
4516 11860 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4517 : {
4518 10433 : nbits = add( nbits, bits_index );
4519 : }
4520 : }
4521 :
4522 1862 : nbits0 = try_differential_fx( numCodingBands, masa_to_total_energy_ratio, ratio_ism_idx, nchan_ism, bits_index, &b_signif );
4523 :
4524 1862 : test();
4525 1862 : IF( LE_16( nbits, nbits0 ) && nbits > 0 )
4526 : {
4527 : /* independent encoding */
4528 1140 : push_next_indice( hMetaData, 1, 1 );
4529 1140 : independent_coding_ratio_ism_idx_fx( ratio_ism_idx, masa_to_total_energy_ratio, nchan_ism, numCodingBands, bits_index, hMetaData );
4530 1140 : nbits = add( nbits, 1 );
4531 : }
4532 : ELSE
4533 : {
4534 722 : IF( nbits > 0 )
4535 : {
4536 666 : differential_coding_first_subframe_ivas_fx( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index );
4537 :
4538 666 : nbits = add( nbits0, 1 );
4539 : }
4540 : }
4541 : }
4542 : ELSE
4543 : {
4544 : /* not first subframe */
4545 3774 : test();
4546 3774 : IF( EQ_16( shift_one, 1 ) && EQ_16( nchan_ism, 2 ) )
4547 : {
4548 45 : nbits = 0;
4549 45 : move16();
4550 : }
4551 : ELSE
4552 : {
4553 3729 : nbits0 = 0;
4554 3729 : nbits1 = 0;
4555 3729 : move16();
4556 3729 : move16();
4557 :
4558 22266 : FOR( b = 0; b < numCodingBands; b++ )
4559 : {
4560 18537 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4561 : {
4562 16371 : estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
4563 16371 : nbits0 = add( nbits0, nbits00 );
4564 16371 : nbits1 = add( nbits1, nbits11 );
4565 : }
4566 : }
4567 3729 : IF( LT_16( nbits0, nbits1 ) )
4568 : {
4569 2691 : GR_order = 0;
4570 2691 : nbits = nbits0;
4571 2691 : move16();
4572 2691 : move16();
4573 : }
4574 : ELSE
4575 : {
4576 1038 : GR_order = 1;
4577 1038 : nbits = nbits1;
4578 1038 : move16();
4579 1038 : move16();
4580 : }
4581 :
4582 3729 : IF( GT_16( numCodingBands, 1 ) )
4583 : {
4584 : /* try the difference from subband to subband; first subband is compared to previous subframe first subband*/
4585 : /* take difference with respect to previous subframe only for first subband */
4586 3702 : nbits0 = 0;
4587 3702 : nbits1 = 0;
4588 3702 : b_signif = 0;
4589 3702 : move16();
4590 3702 : move16();
4591 3702 : move16();
4592 3963 : WHILE( ( b_signif < numCodingBands ) && ( masa_to_total_energy_ratio[b_signif] >= MASA2TOTAL_THR_Q30 ) )
4593 : {
4594 261 : test();
4595 261 : b_signif = add( b_signif, 1 );
4596 : }
4597 :
4598 3702 : IF( LT_16( b_signif, numCodingBands ) )
4599 : {
4600 3690 : estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], nchan_ism, shift_one, idx_sep_obj_local, &nbits0, &nbits1 );
4601 :
4602 3690 : Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism );
4603 :
4604 18249 : FOR( b = b_signif + 1; b < numCodingBands; b++ )
4605 : {
4606 14559 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4607 : {
4608 12675 : estimate_bits_subband_ism_ratio_fx( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism, shift_one, idx_sep_obj_local, &nbits00, &nbits11 );
4609 12675 : nbits0 = add( nbits0, nbits00 );
4610 12675 : nbits1 = add( nbits1, nbits11 );
4611 12675 : Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism );
4612 : }
4613 : }
4614 :
4615 3690 : IF( LT_16( nbits0, nbits1 ) )
4616 : {
4617 529 : GR_order_sb = 0;
4618 529 : move16();
4619 : }
4620 : ELSE
4621 : {
4622 3161 : GR_order_sb = 1;
4623 3161 : nbits0 = nbits1;
4624 3161 : move16();
4625 3161 : move16();
4626 : }
4627 :
4628 3690 : IF( LT_16( nbits0, nbits ) )
4629 : {
4630 343 : differential_subframe = 0;
4631 343 : nbits = nbits0;
4632 343 : GR_order = GR_order_sb;
4633 343 : move16();
4634 343 : move16();
4635 343 : move16();
4636 : }
4637 :
4638 3690 : IF( nbits > 0 )
4639 : {
4640 : /* write prediction type */
4641 3690 : push_next_indice( hMetaData, differential_subframe, 1 );
4642 : /* write GR order */
4643 3690 : push_next_indice( hMetaData, GR_order, 1 );
4644 3690 : nbits = add( nbits, 1 ); /* for the prediction type */
4645 3690 : nbits = add( nbits, 1 ); /* for GR_order */
4646 :
4647 : /* write data */
4648 3690 : IF( differential_subframe )
4649 : {
4650 20082 : FOR( b = 0; b < numCodingBands; b++ )
4651 : {
4652 16735 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4653 : {
4654 : /* take difference with respect to previous subframe */
4655 14850 : v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_prev_sf[b], diff_idx, nchan_ism );
4656 :
4657 14850 : IF( shift_one )
4658 : {
4659 9289 : remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
4660 : }
4661 :
4662 14850 : transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
4663 : }
4664 : }
4665 : }
4666 : ELSE
4667 : {
4668 343 : v_sub_s16_fx( ratio_ism_idx[b_signif], ratio_ism_idx_prev_sf[b_signif], diff_idx, nchan_ism );
4669 :
4670 343 : IF( shift_one )
4671 : {
4672 87 : remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
4673 : }
4674 :
4675 343 : transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
4676 :
4677 343 : Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
4678 :
4679 1709 : FOR( b = b_signif + 1; b < numCodingBands; b++ )
4680 : {
4681 : /* take difference with respect to previous subband */
4682 1366 : IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) )
4683 : {
4684 1172 : v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism );
4685 :
4686 1172 : IF( shift_one )
4687 : {
4688 332 : remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
4689 : }
4690 :
4691 1172 : transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
4692 :
4693 1172 : Copy( ratio_ism_idx[b], ratio_ism_idx_ref, sub( nchan_ism, shift_one ) );
4694 : }
4695 : }
4696 : }
4697 : }
4698 : }
4699 : }
4700 : ELSE
4701 : {
4702 : /* only differential wrt previous subframe is possible */
4703 : /* write the differential to subframe case and no bit to signal the difference type */
4704 :
4705 27 : IF( nbits > 0 )
4706 : {
4707 : /* write GR order */
4708 6 : push_next_indice( hMetaData, GR_order, 1 );
4709 6 : nbits = add( nbits, 1 ); /* for GR_order */
4710 : /* write data */
4711 : /* only one subband */
4712 6 : IF( LT_32( masa_to_total_energy_ratio[0], MASA2TOTAL_THR_Q30 ) )
4713 : {
4714 : /* take difference with respect to previous subframe */
4715 6 : v_sub_s16_fx( ratio_ism_idx[0], ratio_ism_idx_prev_sf[0], diff_idx, nchan_ism );
4716 :
4717 6 : IF( shift_one )
4718 : {
4719 0 : remove_sep_obj_fx( diff_idx, nchan_ism, idx_sep_obj_local );
4720 : }
4721 :
4722 6 : transform_index_and_GR_encode_ivas_fx( diff_idx, sub( sub( nchan_ism, 1 ), shift_one ), GR_order, hMetaData );
4723 : }
4724 : }
4725 : }
4726 : }
4727 : }
4728 :
4729 5636 : return nbits;
4730 : }
4731 :
4732 :
4733 1862 : static void ivas_encode_masaism_metadata_fx(
4734 : MASA_ENCODER_HANDLE hMasa,
4735 : IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */
4736 : BSTR_ENC_HANDLE hMetaData, /* i/o: metadata bitstream handle */
4737 : ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */
4738 : const Word16 nchan_ism, /* i : number of ISM channels */
4739 : const Word16 low_bitrate_mode, /* i : is low bitrate more? 1/0 */
4740 : const Word16 omasa_nbands,
4741 : const Word16 omasa_nblocks,
4742 : const Word16 idx_separated_object,
4743 : const Word16 ism_imp )
4744 : {
4745 : Word16 sf, band;
4746 : UWord8 numCodingBands;
4747 : UWord8 numSf;
4748 : Word16 brange[2];
4749 : Word64 eneBand;
4750 : Word32 eneBand32;
4751 : Word16 eneBand_exp, shift;
4752 : Word16 bin;
4753 : Word16 obj;
4754 : Word16 bits_ism[MAX_NUM_OBJECTS];
4755 : UWord16 idx_sph;
4756 : Word32 theta_q, phi_q;
4757 : UWord16 index_theta, index_phi;
4758 : Word16 ratio_ism_fx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
4759 : Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS];
4760 : Word32 energy_ism, energy_ism_ind[MAX_NUM_OBJECTS];
4761 : Word16 tmp, rotate, energy_ism_e, energy_ism_ind_e[MAX_NUM_OBJECTS];
4762 : Word16 n_ism_tmp, i;
4763 1862 : OMASA_ENCODER_DATA_HANDLE hOmasaData = hMasa->data.hOmasaData;
4764 1862 : OMASA_ENCODER_ENERGY_HANDLE hOmasaEnergy = hOmasaData->hOmasaEnergy;
4765 : Word16 nbands_work;
4766 : Word32 L_tmp;
4767 : Word16 L_tmp_e;
4768 :
4769 : /* use the values from hQMetaData */
4770 1862 : numCodingBands = (UWord8) hQMetaData->q_direction->cfg.nbands;
4771 1862 : numSf = (Word8) hQMetaData->q_direction->cfg.nblocks;
4772 1862 : nbands_work = s_min( numCodingBands, omasa_nbands );
4773 1862 : move16();
4774 1862 : move16();
4775 1862 : IF( EQ_16( numCodingBands, 1 ) )
4776 : {
4777 120 : FOR( sf = 0; sf < numSf; sf++ )
4778 : {
4779 96 : L_tmp = 0;
4780 96 : L_tmp_e = 0;
4781 96 : move32();
4782 96 : move16();
4783 576 : FOR( i = 0; i < omasa_nbands; i++ )
4784 : {
4785 480 : L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, hOmasaEnergy->energy_ism_fx[sf][i], hOmasaEnergy->energy_ism_fx_e[sf][i], &L_tmp_e );
4786 : }
4787 :
4788 : /* if ( sum_f( hOmasaEnergy->energy_ism[sf], omasa_nbands ) == 0.0f ) */
4789 96 : IF( L_tmp == 0 )
4790 : {
4791 0 : hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
4792 0 : move32();
4793 : }
4794 : ELSE
4795 : {
4796 96 : brange[0] = hMasa->data.band_mapping[0];
4797 96 : brange[1] = hMasa->data.band_mapping[omasa_nbands];
4798 96 : eneBand = 0;
4799 96 : move16();
4800 96 : move16();
4801 96 : move64();
4802 2400 : FOR( bin = brange[0]; bin < brange[1]; bin++ )
4803 : {
4804 2304 : eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
4805 : }
4806 96 : shift = W_norm( eneBand );
4807 96 : eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
4808 96 : eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
4809 :
4810 96 : energy_ism = 0;
4811 96 : energy_ism_e = 0;
4812 96 : move32();
4813 96 : move16();
4814 288 : FOR( obj = 0; obj < nchan_ism; obj++ )
4815 : {
4816 192 : energy_ism_ind[obj] = 0;
4817 192 : energy_ism_ind_e[obj] = 0;
4818 192 : move32();
4819 192 : move16();
4820 : }
4821 :
4822 576 : FOR( band = 0; band < omasa_nbands; band++ )
4823 : {
4824 480 : energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ism_fx_e[sf][band], &energy_ism_e );
4825 :
4826 1440 : FOR( obj = 0; obj < nchan_ism; obj++ )
4827 : {
4828 :
4829 960 : hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30; // 1.0f in Q30
4830 960 : move32();
4831 : }
4832 : }
4833 :
4834 288 : FOR( obj = 0; obj < nchan_ism; obj++ )
4835 : {
4836 192 : hOmasaEnergy->energy_ratio_ism_fx[sf][0][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
4837 192 : move32();
4838 192 : L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
4839 : /* Scaling to Q30 */
4840 192 : hOmasaEnergy->energy_ratio_ism_fx[sf][0][obj] = L_shl( hOmasaEnergy->energy_ratio_ism_fx[sf][0][obj], sub( L_tmp_e, 1 ) ); // Q30
4841 192 : move32();
4842 : }
4843 96 : L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
4844 96 : IF( L_tmp != 0 )
4845 : {
4846 96 : hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
4847 96 : move32();
4848 96 : tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
4849 : /* Scaling to Q30 */
4850 96 : hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[sf][0], sub( tmp, 1 ) ); // Q30
4851 96 : move32();
4852 : }
4853 : ELSE
4854 : {
4855 0 : hOmasaData->masa_to_total_energy_ratio_fx[sf][0] = ONE_IN_Q30;
4856 0 : move32();
4857 : }
4858 : }
4859 : }
4860 : }
4861 1838 : ELSE IF( EQ_16( numSf, 1 ) )
4862 : {
4863 6270 : FOR( band = 0; band < nbands_work; band++ )
4864 : {
4865 5666 : energy_ism = 0; /* ISM energy for current subband */ // energy_ism_e
4866 5666 : energy_ism_e = 0; /* ISM energy for current subband */
4867 5666 : move32();
4868 5666 : move16();
4869 24246 : FOR( obj = 0; obj < nchan_ism; obj++ )
4870 : {
4871 18580 : energy_ism_ind[obj] = 0;
4872 18580 : energy_ism_ind_e[obj] = 0;
4873 18580 : move32();
4874 18580 : move16();
4875 : }
4876 14722 : FOR( sf = 0; sf < omasa_nblocks; sf++ )
4877 : {
4878 9056 : energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ism_fx_e[sf][band], &energy_ism_e );
4879 :
4880 34416 : FOR( obj = 0; obj < nchan_ism; obj++ )
4881 : {
4882 25360 : L_tmp = Mpy_32_32( hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ratio_ism_fx[sf][band][obj] ); // Q = (31 - hOmasaEnergy->energy_ism_fx_e[sf][band]) + Q30 - 31
4883 25360 : L_tmp_e = add( 1, hOmasaEnergy->energy_ism_fx_e[sf][band] );
4884 25360 : energy_ism_ind[obj] = BASOP_Util_Add_Mant32Exp( energy_ism_ind[obj], energy_ism_ind_e[obj], L_tmp, L_tmp_e, &energy_ism_ind_e[obj] );
4885 25360 : move32();
4886 : }
4887 : }
4888 :
4889 5666 : IF( energy_ism == 0 )
4890 : {
4891 0 : hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30; // 1.0f in Q30
4892 0 : move32();
4893 : }
4894 : ELSE
4895 : {
4896 24246 : FOR( obj = 0; obj < nchan_ism; obj++ )
4897 : {
4898 18580 : hOmasaEnergy->energy_ratio_ism_fx[0][band][obj] = BASOP_Util_Divide3232_Scale_newton( energy_ism_ind[obj], energy_ism, &L_tmp_e );
4899 18580 : move32();
4900 18580 : L_tmp_e = add( L_tmp_e, sub( energy_ism_ind_e[obj], energy_ism_e ) );
4901 : /* Scaling to Q30 */
4902 18580 : hOmasaEnergy->energy_ratio_ism_fx[0][band][obj] = L_shl( hOmasaEnergy->energy_ratio_ism_fx[0][band][obj], sub( L_tmp_e, 1 ) ); // Q30
4903 18580 : move32();
4904 : }
4905 5666 : brange[0] = hMasa->data.band_mapping[band];
4906 5666 : brange[1] = hMasa->data.band_mapping[band + 1];
4907 5666 : move16();
4908 5666 : move16();
4909 :
4910 5666 : eneBand = 0;
4911 5666 : move64();
4912 14722 : FOR( sf = 0; sf < omasa_nblocks; sf++ )
4913 : {
4914 39748 : FOR( bin = brange[0]; bin < brange[1]; bin++ )
4915 : {
4916 30692 : eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
4917 : }
4918 : }
4919 5666 : shift = W_norm( eneBand );
4920 5666 : eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
4921 5666 : eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
4922 :
4923 5666 : L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, energy_ism, energy_ism_e, &L_tmp_e );
4924 5666 : IF( L_tmp != 0 )
4925 : {
4926 5666 : hOmasaData->masa_to_total_energy_ratio_fx[0][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
4927 5666 : move32();
4928 5666 : tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
4929 : /* Scaling to Q30 */
4930 5666 : hOmasaData->masa_to_total_energy_ratio_fx[0][band] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[0][band], sub( tmp, 1 ) ); // Q30
4931 5666 : move32();
4932 : }
4933 : ELSE
4934 : {
4935 0 : hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
4936 0 : move32();
4937 : }
4938 : }
4939 : }
4940 604 : FOR( band = nbands_work; band < numCodingBands; band++ )
4941 : {
4942 0 : hOmasaData->masa_to_total_energy_ratio_fx[0][band] = ONE_IN_Q30;
4943 0 : move32();
4944 :
4945 0 : FOR( obj = 0; obj < nchan_ism; obj++ )
4946 : {
4947 0 : hOmasaEnergy->energy_ratio_ism_fx[0][band][obj] = hOmasaEnergy->energy_ratio_ism_fx[0][nbands_work - 1][obj];
4948 0 : move32();
4949 : }
4950 : }
4951 : }
4952 : ELSE
4953 : {
4954 6170 : FOR( sf = 0; sf < numSf; sf++ )
4955 : {
4956 29616 : FOR( band = 0; band < nbands_work; band++ )
4957 : {
4958 24680 : IF( hOmasaEnergy->energy_ism_fx[sf][band] == 0 )
4959 : {
4960 0 : hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
4961 0 : move32();
4962 : }
4963 : ELSE
4964 : {
4965 24680 : brange[0] = hMasa->data.band_mapping[band];
4966 24680 : brange[1] = hMasa->data.band_mapping[band + 1];
4967 24680 : move16();
4968 24680 : move16();
4969 :
4970 24680 : eneBand = 0;
4971 24680 : move64();
4972 141656 : FOR( bin = brange[0]; bin < brange[1]; bin++ )
4973 : {
4974 116976 : eneBand = W_mac_32_32( eneBand, hMasa->data.energy_fx[sf][bin], 1 ); // hMasa->data.q_energy + 1
4975 : }
4976 24680 : shift = W_norm( eneBand );
4977 24680 : eneBand32 = W_extract_h( W_shl( eneBand, shift ) );
4978 24680 : eneBand_exp = sub( 63, add( add( hMasa->data.q_energy, 1 ), shift ) );
4979 :
4980 24680 : L_tmp = BASOP_Util_Add_Mant32Exp( eneBand32, eneBand_exp, hOmasaEnergy->energy_ism_fx[sf][band], hOmasaEnergy->energy_ism_fx_e[sf][band], &L_tmp_e );
4981 24680 : IF( L_tmp != 0 )
4982 : {
4983 24680 : hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = BASOP_Util_Divide3232_Scale_newton( eneBand32, L_tmp, &tmp );
4984 24680 : move32();
4985 24680 : tmp = add( tmp, sub( eneBand_exp, L_tmp_e ) );
4986 : /* Scaling to Q30 */
4987 24680 : hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = L_shl( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], sub( tmp, 1 ) ); // Q30
4988 24680 : move32();
4989 : }
4990 : ELSE
4991 : {
4992 0 : hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
4993 0 : move32();
4994 : }
4995 : }
4996 : }
4997 4936 : FOR( band = nbands_work; band < numCodingBands; band++ )
4998 : {
4999 0 : hOmasaData->masa_to_total_energy_ratio_fx[sf][band] = ONE_IN_Q30;
5000 0 : move32();
5001 :
5002 0 : FOR( obj = 0; obj < nchan_ism; obj++ )
5003 : {
5004 0 : hOmasaEnergy->energy_ratio_ism_fx[sf][band][obj] = hOmasaEnergy->energy_ratio_ism_fx[sf][nbands_work - 1][obj];
5005 0 : move32();
5006 : }
5007 : }
5008 : }
5009 : }
5010 :
5011 1862 : ivas_omasa_encode_masa_to_total_fx( hOmasaData->masa_to_total_energy_ratio_fx, hMetaData, low_bitrate_mode, numCodingBands, numSf );
5012 :
5013 : /* quantize ism_ratios */
5014 1862 : IF( GT_16( nchan_ism, 1 ) )
5015 : {
5016 1862 : rotate = 0;
5017 1862 : n_ism_tmp = 0;
5018 1862 : move16();
5019 1862 : move16();
5020 :
5021 7498 : FOR( sf = 0; sf < numSf; sf++ )
5022 : {
5023 36078 : FOR( band = 0; band < numCodingBands; band++ )
5024 : {
5025 137614 : FOR( obj = 0; obj < nchan_ism; obj++ )
5026 : {
5027 107172 : assert( ( hOmasaEnergy->energy_ratio_ism_fx[sf][band][obj] >= 0 ) && ( hOmasaEnergy->energy_ratio_ism_fx[sf][band][obj] <= ONE_IN_Q30 ) );
5028 107172 : ratio_ism_fx[band][obj] = extract_h( hOmasaEnergy->energy_ratio_ism_fx[sf][band][obj] ); // Q14
5029 107172 : move16();
5030 : }
5031 :
5032 : /* Quantize ISM ratios */
5033 30442 : quantize_ratio_ism_vector_ivas_fx( ratio_ism_fx[band], 1 /* Q14 */, ratio_ism_idx[band], nchan_ism, hOmasaData->masa_to_total_energy_ratio_fx[sf][band], idx_separated_object );
5034 :
5035 30442 : test();
5036 30442 : test();
5037 30442 : IF( EQ_16( n_ism_tmp, numCodingBands ) && ratio_ism_idx[band][idx_separated_object] != 0 && LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
5038 : {
5039 92 : i = 0;
5040 92 : move16();
5041 697 : WHILE( ratio_ism_idx[band][idx_separated_object] > 0 )
5042 : {
5043 605 : IF( NE_16( i, idx_separated_object ) )
5044 : {
5045 410 : ratio_ism_idx[band][i] = add( ratio_ism_idx[band][i], 1 );
5046 410 : ratio_ism_idx[band][idx_separated_object] = sub( ratio_ism_idx[band][idx_separated_object], 1 );
5047 410 : move16();
5048 410 : move16();
5049 : }
5050 605 : i = add( i, 1 );
5051 605 : if ( EQ_16( i, nchan_ism ) )
5052 : {
5053 138 : i = 0;
5054 138 : move16();
5055 : }
5056 : }
5057 : }
5058 :
5059 : /* reconstructed values */
5060 30442 : reconstruct_ism_ratios_fx( ratio_ism_idx[band], nchan_ism, STEP_PARAM_ISM_POW_RATIO_NBITS_Q31, hOmasaEnergy->q_energy_ratio_ism_fx[sf][band] );
5061 : }
5062 :
5063 5636 : test();
5064 5636 : IF( GT_16( nchan_ism, 2 ) && EQ_16( idx_separated_object, sub( nchan_ism, 1 ) ) )
5065 : {
5066 : /* rotate components */
5067 766 : rotate = 1;
5068 766 : move16();
5069 4610 : FOR( band = 0; band < numCodingBands; band++ )
5070 : {
5071 3844 : IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
5072 : {
5073 3352 : tmp = ratio_ism_idx[band][nchan_ism - 1];
5074 3352 : ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
5075 3352 : ratio_ism_idx[band][0] = tmp;
5076 3352 : move16();
5077 3352 : move16();
5078 3352 : move16();
5079 3352 : test();
5080 3352 : IF( sf == 0 && tmp == 0 )
5081 : {
5082 799 : n_ism_tmp = add( n_ism_tmp, 1 );
5083 : }
5084 :
5085 3352 : if ( EQ_16( n_ism_tmp, numCodingBands ) )
5086 : {
5087 1753 : assert( tmp == 0 );
5088 : }
5089 : }
5090 : }
5091 : }
5092 : ELSE
5093 : {
5094 4870 : IF( GT_16( idx_separated_object, -1 ) )
5095 : {
5096 31468 : FOR( band = 0; band < numCodingBands; band++ )
5097 : {
5098 26598 : IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
5099 : {
5100 23497 : test();
5101 23497 : IF( ratio_ism_idx[band][idx_separated_object] == 0 && sf == 0 )
5102 : {
5103 8636 : n_ism_tmp = add( n_ism_tmp, 1 );
5104 : }
5105 : }
5106 : }
5107 : }
5108 : }
5109 :
5110 : /* encode data for current subframe */
5111 5636 : test();
5112 5636 : IF( sf > 0 && EQ_16( n_ism_tmp, numCodingBands ) )
5113 : {
5114 2082 : encode_ratio_ism_subframe_fx( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio_fx[sf], 1, idx_separated_object );
5115 : }
5116 : ELSE
5117 : {
5118 3554 : encode_ratio_ism_subframe_fx( ratio_ism_idx, nchan_ism, numCodingBands, sf, ratio_ism_idx_prev_sf, hMetaData, hOmasaData->masa_to_total_energy_ratio_fx[sf], 0, idx_separated_object );
5119 : }
5120 :
5121 : /* calculate quantized ISM ratios */
5122 : /* save previous subframe indexes */
5123 36078 : FOR( band = 0; band < numCodingBands; band++ )
5124 : {
5125 30442 : Copy( ratio_ism_idx[band], ratio_ism_idx_prev_sf[band], nchan_ism );
5126 : }
5127 :
5128 5636 : IF( rotate )
5129 : {
5130 4610 : FOR( band = 0; band < numCodingBands; band++ )
5131 : {
5132 3844 : IF( LT_32( hOmasaData->masa_to_total_energy_ratio_fx[sf][band], MASA2TOTAL_THR_Q30 ) )
5133 : {
5134 3352 : tmp = ratio_ism_idx[band][nchan_ism - 1];
5135 3352 : ratio_ism_idx[band][nchan_ism - 1] = ratio_ism_idx[band][0];
5136 3352 : ratio_ism_idx[band][0] = tmp;
5137 3352 : move16();
5138 3352 : move16();
5139 3352 : move16();
5140 : }
5141 : }
5142 : }
5143 : }
5144 : }
5145 :
5146 1862 : calculate_nbits_meta_fx( nchan_ism, hOmasaEnergy->q_energy_ratio_ism_fx, hOmasaData->masa_to_total_energy_ratio_fx, numSf, numCodingBands, bits_ism, idx_separated_object, ism_imp );
5147 :
5148 : /* quantize directions */
5149 8142 : FOR( obj = 0; obj < nchan_ism; obj++ )
5150 : {
5151 6280 : IF( LT_16( bits_ism[obj], 8 ) )
5152 : {
5153 : /* check is same as previous */
5154 2009 : test();
5155 2009 : IF( LT_32( L_abs( L_sub( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->q_elevation_old_fx ) ), 41943 /* 0.01f in Q22 */ ) && LT_32( L_abs( L_sub( hIsmMeta[obj]->azimuth_fx, hIsmMeta[obj]->q_azimuth_old_fx ) ), 41943 /* 0.01f in Q22 */ ) )
5156 : {
5157 201 : push_next_indice( hMetaData, 1, 1 );
5158 : /* the old stays the same */
5159 : }
5160 : ELSE
5161 : {
5162 1808 : push_next_indice( hMetaData, 0, 1 );
5163 1808 : idx_sph = quantize_direction_fx( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->azimuth_fx, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
5164 1808 : push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
5165 1808 : hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
5166 1808 : hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
5167 1808 : move32();
5168 1808 : move32();
5169 : }
5170 : }
5171 : ELSE
5172 : {
5173 4271 : idx_sph = quantize_direction_fx( hIsmMeta[obj]->elevation_fx, hIsmMeta[obj]->azimuth_fx, bits_ism[obj], &theta_q, &phi_q, &index_theta, &index_phi, MC_LS_SETUP_INVALID );
5174 4271 : push_next_indice( hMetaData, idx_sph, bits_ism[obj] );
5175 4271 : hIsmMeta[obj]->q_elevation_old_fx = hIsmMeta[obj]->elevation_fx;
5176 4271 : hIsmMeta[obj]->q_azimuth_old_fx = hIsmMeta[obj]->azimuth_fx;
5177 4271 : move32();
5178 4271 : move32();
5179 : }
5180 : }
5181 :
5182 1862 : return;
5183 : }
5184 :
5185 :
5186 : /*-------------------------------------------------------------------*
5187 : * ivas_merge_masa_transports()
5188 : *
5189 : * Merge MASA transport channels
5190 : *-------------------------------------------------------------------*/
5191 :
5192 5858 : void ivas_merge_masa_transports_fx(
5193 : Word32 data_in_f1_fx[][L_FRAME48k], // Qx
5194 : Word32 *data_in_f2_fx[], // Qx
5195 : Word32 *data_out_f_fx[], // Qx
5196 : const Word16 input_frame,
5197 : const Word16 num_transport_channels )
5198 : {
5199 : Word16 i, j;
5200 :
5201 17574 : FOR( i = 0; i < num_transport_channels; i++ )
5202 : {
5203 10588356 : FOR( j = 0; j < input_frame; j++ )
5204 : {
5205 10576640 : data_out_f_fx[i][j] = L_add( data_in_f1_fx[i][j], data_in_f2_fx[i][j] );
5206 10576640 : move32();
5207 : }
5208 : }
5209 :
5210 5858 : return;
5211 : }
|