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 "options.h"
34 : #include <stdlib.h>
35 : #include <assert.h>
36 : #include <math.h>
37 : #include "ivas_cnst.h"
38 : #include "ivas_prot_fx.h"
39 : #include "prot_fx.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_rom_enc.h"
42 : #include "wmc_auto.h"
43 : #ifdef DEBUGGING
44 : #include "debug.h"
45 : #endif
46 :
47 :
48 : /*-------------------------------------------------------------------------
49 : * Local function prototypes
50 : *------------------------------------------------------------------------*/
51 : static void ivas_omasa_param_est_enc_fx(
52 : OMASA_ENC_HANDLE hOMasa,
53 : OMASA_ENCODER_DATA_HANDLE hOmasaData,
54 : ISM_METADATA_HANDLE hIsmMeta[],
55 : Word32 *data[], /*i:q_data*/
56 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:q22*/
57 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:q22*/
58 : Word32 energyRatio_fx[MASA_FREQUENCY_BANDS], /*o:Q30*/
59 : Word16 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:Q15*/
60 : Word16 surroundingCoherence_fx[MASA_FREQUENCY_BANDS], /*o:Q15*/
61 : Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS], /*o:q30*/
62 : const Word16 input_frame,
63 : const Word16 nchan_ism,
64 : Word16 q_data /*i: Qfactor for data*/
65 : );
66 :
67 : static void ivas_omasa_energy_and_ratio_est_fx(
68 : OMASA_ENC_HANDLE hOMasa,
69 : OMASA_ENCODER_DATA_HANDLE hOmasaData,
70 : Word32 *data_fx[],
71 : const Word16 input_frame,
72 : const Word16 nchan_ism,
73 : const Word16 q_data );
74 :
75 : static void ivas_omasa_dmx_fx(
76 : Word32 *data_in[], /*i:Qx*/
77 : Word32 data_out[][L_FRAME48k], /*i:Qx*/
78 : const Word16 input_frame, /*i:q0*/
79 : const Word16 nchan_transport, /*i:q0*/
80 : const Word16 nchan_ism, /*i:q0*/
81 : ISM_METADATA_HANDLE hIsmMeta[], /*i*/
82 : Word16 prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], /*o:q15*/
83 : const Word16 interpolator[L_FRAME48k] /*i:q15*/
84 : );
85 : static void computeIntensityVector_enc_fx(
86 : const Word16 *band_grouping, /* i : Band grouping for estimation */
87 : Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */
88 : Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal */
89 : const Word16 num_frequency_bands, /* i : Number of frequency bands */
90 : Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS], /* o : Intensity vector */
91 : Word16 guard_bits );
92 : static void computeReferencePower_omasa_ivas_fx( const Word16 *band_grouping, Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], Word32 *reference_power, const Word16 enc_param_start_band, const Word16 num_freq_bands, Word16 q_Cldfb, Word16 *ref_exp );
93 : /*--------------------------------------------------------------------------*
94 : * ivas_omasa_enc_open()
95 : *
96 : * Allocate and initialize OMASA handle
97 : *--------------------------------------------------------------------------*/
98 :
99 464 : ivas_error ivas_omasa_enc_open_fx(
100 : Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */
101 : )
102 : {
103 : Word16 i, j;
104 : OMASA_ENC_HANDLE hOMasa;
105 : Word16 numAnalysisChannels;
106 : Word16 input_frame;
107 : ivas_error error;
108 :
109 464 : error = IVAS_ERR_OK;
110 464 : move16();
111 :
112 464 : assert( st_ivas->hMasa != NULL && "MASA encoder handle is not present" );
113 :
114 464 : IF( ( hOMasa = (OMASA_ENC_HANDLE) malloc( sizeof( OMASA_ENC_STATE ) ) ) == NULL )
115 : {
116 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA encoder\n" ) );
117 : }
118 :
119 464 : numAnalysisChannels = st_ivas->hEncoderConfig->nchan_ism;
120 464 : move16();
121 :
122 : /* open/initialize CLDFB */
123 464 : hOMasa->num_Cldfb_instances = numAnalysisChannels;
124 464 : move16();
125 1906 : FOR( i = 0; i < hOMasa->num_Cldfb_instances; i++ )
126 : {
127 1442 : IF( ( error = openCldfb_ivas_fx( &( hOMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, st_ivas->hEncoderConfig->input_Fs, CLDFB_PROTOTYPE_5_00MS, ENC ) ) != IVAS_ERR_OK )
128 : {
129 0 : return error;
130 : }
131 : }
132 464 : set_zero_fx( &hOMasa->chnlToFoaMtx_fx[0][0], DIRAC_MAX_ANA_CHANS * MCMASA_MAX_ANA_CHANS );
133 :
134 : /* intensity 3-dim */
135 1856 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
136 : {
137 1392 : hOMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) );
138 :
139 6960 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
140 : {
141 5568 : IF( ( hOMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
142 : {
143 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
144 : }
145 5568 : set_zero_fx( hOMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS );
146 : }
147 1392 : hOMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) );
148 :
149 6960 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
150 : {
151 5568 : IF( ( hOMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL )
152 : {
153 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
154 : }
155 5568 : set16_fx( hOMasa->direction_vector_e[i][j], 0, MASA_FREQUENCY_BANDS );
156 : }
157 : }
158 :
159 1856 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
160 : {
161 45936 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
162 : {
163 44544 : IF( ( hOMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
164 : {
165 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
166 : }
167 44544 : set_zero_fx( hOMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS );
168 : }
169 : }
170 464 : set16_fx( hOMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF );
171 464 : set_zero_fx( hOMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
172 464 : set16_fx( hOMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF );
173 :
174 2320 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
175 : {
176 1856 : set16_fx( hOMasa->prev_object_dm_gains_fx[i], INV_SQRT_2_Q15, MASA_MAX_TRANSPORT_CHANNELS ); /*q15*/
177 : }
178 464 : set_zero_fx( hOMasa->broadband_energy_sm_fx, MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS );
179 464 : hOMasa->broadband_energy_sm_e = 0;
180 464 : move16();
181 464 : set_zero_fx( hOMasa->broadband_energy_prev_fx, MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS );
182 464 : hOMasa->broadband_energy_prev_e = 0;
183 464 : move16();
184 :
185 464 : hOMasa->prev_selected_object = 0;
186 464 : hOMasa->changing_object = 0;
187 464 : move16();
188 464 : move16();
189 :
190 464 : input_frame = extract_l( Mult_32_16( st_ivas->hEncoderConfig->input_Fs /*q0*/, INV_FRAME_PER_SEC_Q15 /*q15*/ ) ); /*Q0+Q15-Q15->Q0*/
191 420304 : FOR( i = 0; i < input_frame; i++ )
192 : {
193 419840 : hOMasa->interpolator_fx[i] = divide1616( i, input_frame ); /*q15*/
194 419840 : hOMasa->fade_out_gain_fx[i] = add( 16384 /*0.5 in q15*/, shr( getCosWord16R2( mult( hOMasa->interpolator_fx[i], 32767 / 2 ) /*15+15-15=>15*/ ), 1 ) /*q15*/ ); /*(angle in degrees=((float)i/(float)input_frame *pi)*180/pi)/360*32767 =>(float)i/(float)input_frame )*32767/2*/ /*q15*/
195 419840 : hOMasa->fade_in_gain_fx[i] = sub( 32767 /*1.0 in Q15*/, hOMasa->fade_out_gain_fx[i] ); /*q15*/
196 419840 : move16();
197 419840 : move16();
198 419840 : move16();
199 : }
200 :
201 464 : hOMasa->index_buffer_intensity = 0;
202 464 : move16();
203 :
204 464 : st_ivas->hOMasa = hOMasa;
205 :
206 464 : return error;
207 : }
208 :
209 : /*--------------------------------------------------------------------------*
210 : * ivas_omasa_enc_close()
211 : *
212 : * Close OMASA handle
213 : *--------------------------------------------------------------------------*/
214 :
215 :
216 1063 : void ivas_omasa_enc_close_fx(
217 : OMASA_ENC_HANDLE *hOMasa /* i/o: encoder OMASA handle */
218 : )
219 : {
220 : Word16 i, j;
221 :
222 1063 : test();
223 1063 : IF( hOMasa == NULL || *hOMasa == NULL )
224 : {
225 599 : return;
226 : }
227 :
228 1906 : FOR( i = 0; i < ( *hOMasa )->num_Cldfb_instances; i++ )
229 : {
230 1442 : deleteCldfb_ivas_fx( &( ( *hOMasa )->cldfbAnaEnc[i] ) );
231 : }
232 :
233 1856 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
234 : {
235 6960 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
236 : {
237 5568 : free( ( *hOMasa )->direction_vector_m_fx[i][j] );
238 5568 : ( *hOMasa )->direction_vector_m_fx[i][j] = NULL;
239 5568 : free( ( *hOMasa )->direction_vector_e[i][j] );
240 5568 : ( *hOMasa )->direction_vector_e[i][j] = NULL;
241 : }
242 :
243 45936 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
244 : {
245 44544 : free( ( *hOMasa )->buffer_intensity_real_fx[i][j] );
246 44544 : ( *hOMasa )->buffer_intensity_real_fx[i][j] = NULL;
247 : }
248 1392 : free( ( *hOMasa )->direction_vector_m_fx[i] );
249 1392 : ( *hOMasa )->direction_vector_m_fx[i] = NULL;
250 1392 : free( ( *hOMasa )->direction_vector_e[i] );
251 1392 : ( *hOMasa )->direction_vector_e[i] = NULL;
252 : }
253 :
254 464 : free( *hOMasa );
255 464 : ( *hOMasa ) = NULL;
256 :
257 464 : return;
258 : }
259 :
260 : /*--------------------------------------------------------------------------*
261 : * ivas_omasa_enc_config()
262 : *
263 : * oMASA encoder configuration
264 : *--------------------------------------------------------------------------*/
265 9000 : ivas_error ivas_omasa_enc_config_fx(
266 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
267 : )
268 : {
269 : Word16 k, sce_id, nSCE_old;
270 : Word32 ivas_total_brate, ism_total_brate;
271 : ENCODER_CONFIG_HANDLE hEncoderConfig;
272 : ivas_error error;
273 :
274 9000 : hEncoderConfig = st_ivas->hEncoderConfig;
275 9000 : ivas_total_brate = hEncoderConfig->ivas_total_brate;
276 9000 : nSCE_old = st_ivas->nSCE;
277 9000 : move16();
278 9000 : move32(); /*hEncoderConfig->ivas_total_brate*/
279 :
280 9000 : st_ivas->ism_mode = ivas_omasa_ism_mode_select_fx( ivas_total_brate, hEncoderConfig->nchan_ism );
281 9000 : move16();
282 9000 : st_ivas->nchan_transport = 2;
283 9000 : move16();
284 :
285 : /* reconfiguration in case of bitrate switching */
286 9000 : IF( NE_32( hEncoderConfig->last_ivas_total_brate, ivas_total_brate ) )
287 : {
288 1634 : ivas_set_omasa_TC_fx( st_ivas->ism_mode, hEncoderConfig->nchan_ism, &st_ivas->nSCE, &st_ivas->nCPE );
289 :
290 1634 : k = 0;
291 1634 : move16();
292 12910 : WHILE( ( k < SIZE_IVAS_BRATE_TBL ) && ( ivas_total_brate != ivas_brate_tbl[k] ) )
293 : {
294 11276 : test();
295 11276 : k = add( k, 1 );
296 : }
297 :
298 1634 : ism_total_brate = 0;
299 1634 : move32();
300 3746 : FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ )
301 : {
302 2112 : ism_total_brate = L_add( ism_total_brate, sep_object_brate[k - 2][st_ivas->nSCE - 1] );
303 : }
304 :
305 1634 : IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
306 : {
307 403 : IF( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, 1 ) ) != IVAS_ERR_OK )
308 : {
309 0 : return error;
310 : }
311 : }
312 1231 : ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
313 : {
314 439 : IF( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nSCE, NULL, 0, NULL, NULL, NULL, NULL, NULL, 1 ) ) != IVAS_ERR_OK )
315 : {
316 0 : return error;
317 : }
318 : }
319 :
320 : /* reconfigure core-coders for ISMs */
321 1634 : IF( st_ivas->nSCE > 0 )
322 : {
323 1190 : IF( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, 1, 2, sep_object_brate[k - 2][st_ivas->nSCE - 1], L_sub( ivas_total_brate, ism_total_brate ), MC_MODE_NONE ) ) != IVAS_ERR_OK )
324 : {
325 0 : return error;
326 : }
327 : }
328 : ELSE
329 : {
330 444 : IF( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, 1, 2, 0, L_sub( ivas_total_brate, ism_total_brate ), MC_MODE_NONE ) ) != IVAS_ERR_OK )
331 : {
332 0 : return error;
333 : }
334 : }
335 :
336 : /* re-write IVAS format signalling - actual 'ism_mode' was not known before */
337 1634 : IF( st_ivas->nSCE > 0 )
338 : {
339 1190 : reset_indices_enc_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hBstr, st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->nb_bits_tot );
340 : }
341 : ELSE
342 : {
343 444 : reset_indices_enc_fx( st_ivas->hCPE[0]->hCoreCoder[0]->hBstr, st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->nb_bits_tot );
344 : }
345 :
346 1634 : ivas_write_format_fx( st_ivas );
347 :
348 1634 : test();
349 1634 : test();
350 1634 : IF( NE_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && st_ivas->hOMasa == NULL )
351 : {
352 437 : IF( ( error = ivas_omasa_enc_open_fx( st_ivas ) ) != IVAS_ERR_OK )
353 : {
354 0 : return error;
355 : }
356 : }
357 1197 : ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && st_ivas->hOMasa != NULL )
358 : {
359 439 : ivas_omasa_enc_close_fx( &( st_ivas->hOMasa ) );
360 439 : st_ivas->hOMasa = NULL;
361 : }
362 :
363 1634 : st_ivas->hCPE[0]->element_brate = L_sub( ivas_total_brate, ism_total_brate );
364 1634 : move32();
365 :
366 1634 : IF( GE_32( L_sub( ivas_total_brate, ism_total_brate ), MIN_BRATE_MDCT_STEREO ) )
367 : {
368 709 : hEncoderConfig->element_mode_init = IVAS_CPE_MDCT;
369 : }
370 : ELSE
371 : {
372 925 : hEncoderConfig->element_mode_init = IVAS_CPE_DFT;
373 : }
374 1634 : move16();
375 : }
376 :
377 : /* Configure MASA encoder based on frame parameters */
378 9000 : IF( ( error = ivas_masa_enc_config_fx( st_ivas ) ) != IVAS_ERR_OK )
379 : {
380 0 : return error;
381 : }
382 :
383 9000 : IF( NE_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
384 : {
385 : /* Configure oMASA analysis based on MASA config */
386 5858 : ivas_omasa_set_config_fx( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hEncoderConfig->input_Fs, st_ivas->ism_mode );
387 : }
388 :
389 9000 : return IVAS_ERR_OK;
390 : }
391 :
392 :
393 : /*--------------------------------------------------------------------------*
394 : * ivas_omasa_set_config()
395 : *
396 : * Frame-by-frame config for oMASA
397 : *--------------------------------------------------------------------------*/
398 5858 : void ivas_omasa_set_config_fx(
399 : OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */
400 : MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */
401 : const Word32 input_Fs, /* i : Input sample rate */
402 : const ISM_MODE ism_mode /* i : ISM mode */
403 : )
404 : {
405 : UWord8 i, maxBin;
406 :
407 : /* Determine the number of bands */
408 5858 : test();
409 5858 : IF( EQ_16( ism_mode, ISM_MODE_NONE ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
410 : {
411 : /* use full resolution for the ISM+MASA merge and reduce later */
412 3996 : hOMasa->nbands = 24;
413 : }
414 : ELSE
415 : {
416 1862 : hOMasa->nbands = hMasa->config.numCodingBands;
417 : }
418 5858 : move16();
419 :
420 5858 : hOMasa->nCodingBands = hMasa->config.numCodingBands;
421 5858 : move16();
422 :
423 : /* Determine the number of subframes */
424 5858 : IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) )
425 1426 : hOMasa->nSubframes = 1;
426 : ELSE
427 4432 : hOMasa->nSubframes = MAX_PARAM_SPATIAL_SUBFRAMES;
428 5858 : move16();
429 :
430 : /* Determine band grouping */
431 5858 : IF( EQ_16( hOMasa->nbands, 24 ) )
432 : {
433 3996 : Copy( MASA_band_grouping_24, hOMasa->band_grouping, 24 + 1 );
434 : }
435 : ELSE
436 : {
437 15680 : FOR( i = 0; i < hOMasa->nbands + 1; i++ )
438 : {
439 13818 : hOMasa->band_grouping[i] = MASA_band_grouping_24[hMasa->data.band_mapping[i]];
440 13818 : move16();
441 : }
442 : }
443 :
444 5858 : maxBin = (UWord8) L_shr( L_add( Mpy_32_32( L_shl( input_Fs, 1 ), INV_CLDFB_BANDWIDTH_Q31 ), 1 ), 1 ); /*(uint8_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f )*/
445 5858 : move16();
446 :
447 106960 : FOR( i = 1; i < hOMasa->nbands + 1; i++ )
448 : {
449 106960 : IF( GE_16( hOMasa->band_grouping[i], maxBin ) )
450 : {
451 5858 : hOMasa->band_grouping[i] = maxBin;
452 5858 : hOMasa->nbands = i;
453 5858 : move16();
454 5858 : move16();
455 5858 : BREAK;
456 : }
457 : }
458 :
459 5858 : Copy( DirAC_block_grouping, hOMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); // Q0
460 5858 : IF( EQ_16( hOMasa->nSubframes, 1 ) )
461 : {
462 1426 : hOMasa->block_grouping[1] = hOMasa->block_grouping[MAX_PARAM_SPATIAL_SUBFRAMES];
463 1426 : move16();
464 : }
465 :
466 5858 : return;
467 : }
468 :
469 :
470 : /*--------------------------------------------------------------------------*
471 : * ivas_omasa_enc()
472 : *
473 : * Main OMASA encoding function
474 : *--------------------------------------------------------------------------*/
475 5858 : void ivas_omasa_enc_fx(
476 : OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */
477 : MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */
478 : ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */
479 : Word32 *data_in[], /* i/o: Input / transport audio signals q_data*/
480 : Word16 q_data, /* i : Q0 Stores the q for data_in */
481 : const Word16 input_frame, /* i : Input frame size */
482 : const Word16 nchan_transport, /* i : Number of transport channels */
483 : const Word16 nchan_ism, /* i : Number of objects for parameter analysis */
484 : const ISM_MODE ism_mode, /* i : ISM mode */
485 : Word32 *data_separated_object_fx, /* o : Separated object audio signal */
486 : Word16 *idx_separated_object /* o : Index of the separated object */
487 : )
488 : {
489 : Word16 i, j;
490 : Word32 data_out[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k];
491 :
492 : /* Determine separated object (when applicable) */
493 5858 : test();
494 5858 : IF( EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
495 : {
496 : Word32 broadband_energy_fx[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS];
497 : Word16 broadband_energy_e[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS];
498 3916 : Word16 max_broadband_energy_e = MIN_16;
499 3916 : move16();
500 : Word16 loudest_object;
501 : Word16 selected_object;
502 : Word16 nchan_all_inp;
503 : UWord8 fade_out_separate_object;
504 : UWord8 fade_in_separate_object;
505 : Word32 temp32; /*temp32_e*/
506 : /* Estimate broadband energies */
507 3916 : nchan_all_inp = add( nchan_ism, nchan_transport );
508 3916 : set_zero_fx( broadband_energy_fx, nchan_all_inp );
509 3916 : set16_fx( broadband_energy_e, 0, nchan_all_inp );
510 :
511 25272 : FOR( i = 0; i < nchan_all_inp; i++ )
512 : {
513 19569516 : FOR( j = 0; j < input_frame; j++ )
514 : {
515 19548160 : temp32 = L_shl( data_in[i][j], 6 ); /* scaling data_in to prevent zeroes values in Mpy_32_32 due to precision loss*/
516 19548160 : broadband_energy_fx[i] = BASOP_Util_Add_Mant32Exp( broadband_energy_fx[i], broadband_energy_e[i], Mpy_32_32( temp32, temp32 ), sub( 50, shl( q_data, 1 ) ) /*exponent=62-2*(q+6)*/, &broadband_energy_e[i] );
517 19548160 : move32();
518 : }
519 21356 : max_broadband_energy_e = s_max( max_broadband_energy_e, broadband_energy_e[i] ); /*calculating maximum exponent for all values in broadband_energy_e*/
520 : }
521 :
522 : /*scaling all the values in broadband_energy_fx to max_broadband_energy_e*/
523 25272 : FOR( i = 0; i < nchan_all_inp; i++ )
524 : {
525 21356 : broadband_energy_fx[i] = L_shr( broadband_energy_fx[i], sub( max_broadband_energy_e, broadband_energy_e[i] ) );
526 21356 : move32();
527 : }
528 : /*making exponent for hOMasa->broadband_energy_sm_fx and broadband_energy_fx equal as they are used in addition later*/
529 3916 : IF( GT_16( max_broadband_energy_e, hOMasa->broadband_energy_sm_e ) )
530 : {
531 680 : Scale_sig32( hOMasa->broadband_energy_sm_fx, nchan_all_inp, sub( hOMasa->broadband_energy_sm_e, max_broadband_energy_e ) );
532 680 : hOMasa->broadband_energy_sm_e = max_broadband_energy_e;
533 680 : move16();
534 : }
535 : ELSE
536 : {
537 3236 : Scale_sig32( broadband_energy_fx, nchan_all_inp, sub( max_broadband_energy_e, hOMasa->broadband_energy_sm_e ) );
538 3236 : max_broadband_energy_e = hOMasa->broadband_energy_sm_e;
539 3236 : move16();
540 : }
541 :
542 : /* Temporal averaging */
543 : // alpha = 26214;/*0.8 Q15*/
544 25272 : FOR( i = 0; i < nchan_all_inp; i++ )
545 : {
546 21356 : hOMasa->broadband_energy_sm_fx[i] = L_add( Mpy_32_16_1( broadband_energy_fx[i], 6554 /*0.2 Q15*/ ), Mpy_32_16_1( hOMasa->broadband_energy_sm_fx[i], 26214 /*0.8 Q15*/ ) );
547 21356 : move32();
548 : }
549 :
550 : /* Determine loudest object */
551 3916 : loudest_object = 0;
552 3916 : move16();
553 13524 : FOR( i = 1; i < nchan_ism; i++ )
554 : {
555 9608 : if ( GT_32( hOMasa->broadband_energy_sm_fx[i], hOMasa->broadband_energy_sm_fx[loudest_object] ) )
556 : {
557 1998 : loudest_object = i;
558 1998 : move16();
559 : }
560 : }
561 :
562 : /* Determine object to separate */
563 3916 : selected_object = hOMasa->prev_selected_object;
564 3916 : fade_out_separate_object = 0;
565 3916 : fade_in_separate_object = 0;
566 3916 : move16();
567 3916 : move16();
568 3916 : move16();
569 3916 : IF( hOMasa->changing_object )
570 : {
571 125 : hOMasa->changing_object = 0;
572 125 : selected_object = loudest_object;
573 125 : fade_in_separate_object = 1;
574 125 : move16();
575 125 : move16();
576 125 : move16();
577 : }
578 : ELSE
579 : {
580 3791 : IF( NE_16( loudest_object, hOMasa->prev_selected_object ) )
581 : {
582 : Word32 selected_ene_fx; /*selected_ene_e*/
583 : Word16 selected_ene_e;
584 : Word32 total_ene_fx; /*total_ene_e*/
585 : Word16 total_ene_e;
586 : Word32 selected_ratio_fx; /*selected_ratio_e*/
587 : Word16 selected_ratio_e;
588 : Word32 adaptive_threshold_dB_fx;
589 : Word32 ratio_objects_dB_fx;
590 : Word32 hardswitch_threshold_fx; /*(0.25 q30) as selected_ratio_fx is in q30(both are compared later)*/
591 : Word16 temp32_e;
592 763 : selected_ene_e = 0;
593 763 : temp32_e = 0;
594 763 : hardswitch_threshold_fx = 268435456; /*(0.25 q30)*/
595 763 : selected_ratio_e = 0;
596 763 : total_ene_e = 0;
597 763 : move16();
598 763 : move16();
599 763 : move16();
600 763 : move16();
601 763 : move32();
602 :
603 : /* Compute the energy of the current and the previous selected object in the current and the previous frame */
604 : /*scaling broadband_energy_fx and broadband_energy_prev_fx by 1 (guard bit for addition operation)*/
605 763 : selected_ene_fx = BASOP_Util_Add_Mant32Exp( L_add( L_shr( broadband_energy_fx[loudest_object], 1 ), L_shr( broadband_energy_fx[hOMasa->prev_selected_object], 1 ) ), add( max_broadband_energy_e, 1 ), L_add( L_shr( hOMasa->broadband_energy_prev_fx[loudest_object], 1 ), L_shr( hOMasa->broadband_energy_prev_fx[hOMasa->prev_selected_object], 1 ) ), add( hOMasa->broadband_energy_prev_e, 1 ), &selected_ene_e );
606 :
607 : /* Compute the energy of all objects and MASA channels in the current and the previous frame */
608 763 : total_ene_fx = 0;
609 763 : move32();
610 4917 : FOR( i = 0; i < nchan_all_inp; i++ )
611 : {
612 4154 : total_ene_fx = BASOP_Util_Add_Mant32Exp( total_ene_fx, total_ene_e, broadband_energy_fx[i], max_broadband_energy_e, &total_ene_e );
613 4154 : total_ene_fx = BASOP_Util_Add_Mant32Exp( total_ene_fx, total_ene_e, hOMasa->broadband_energy_prev_fx[i], hOMasa->broadband_energy_prev_e, &total_ene_e );
614 : }
615 :
616 : /* Compute the ratio */
617 763 : selected_ratio_fx = BASOP_Util_Divide3232_Scale( selected_ene_fx, L_add_sat( total_ene_fx, EPSILON_FX ), &selected_ratio_e );
618 763 : selected_ratio_e = add( selected_ratio_e, sub( selected_ene_e, total_ene_e ) );
619 763 : selected_ratio_fx = L_shl( selected_ratio_fx, add( selected_ratio_e, 15 ) ); /*scaling to q30 as the value will always be <=1*/
620 763 : adaptive_threshold_dB_fx = L_add( Mpy_32_16_1( selected_ratio_fx /*q30*/, 576 /*9 in q6*/ ), ONE_IN_Q21 ); /* selected ratio = 0 -> 1 dB, selected ratio = 1 -> 10 dB */ /*q21*/
621 763 : temp32 = BASOP_Util_Divide3232_Scale( hOMasa->broadband_energy_sm_fx[loudest_object], L_add_sat( hOMasa->broadband_energy_sm_fx[hOMasa->prev_selected_object], EPSILON_FX ), &temp32_e );
622 763 : ratio_objects_dB_fx = Mult_32_16( BASOP_Util_Log10( temp32, add( 16, temp32_e ) ) /*q25*/, 20480 /*10 in q11*/ ); /*q21 as the maximum value can go up to 320*/
623 :
624 : /* Adaptively determine whether to change the separated object. If they are quiet compared to the total energy, change easier, as other signals mask the change. */
625 763 : IF( GT_32( ratio_objects_dB_fx, adaptive_threshold_dB_fx ) )
626 : {
627 184 : IF( LT_32( selected_ratio_fx, hardswitch_threshold_fx ) ) /* If low level compared to all audio channels, perform hardswitch */
628 : {
629 53 : selected_object = loudest_object;
630 53 : move16();
631 : }
632 : ELSE /* If high level compared to all audio channels, perform switch via fade out fade in */
633 : {
634 131 : hOMasa->changing_object = 1;
635 131 : fade_out_separate_object = 1;
636 131 : move16();
637 131 : move16();
638 : }
639 : }
640 : }
641 : }
642 :
643 : /* Set values for next frame */
644 25272 : FOR( i = 0; i < nchan_all_inp; i++ )
645 : {
646 21356 : hOMasa->broadband_energy_prev_fx[i] = broadband_energy_fx[i];
647 21356 : hOMasa->broadband_energy_prev_e = max_broadband_energy_e;
648 21356 : move32();
649 21356 : move16();
650 : }
651 3916 : hOMasa->prev_selected_object = selected_object;
652 3916 : move16();
653 :
654 : /* Separate the selected object */
655 3916 : *idx_separated_object = selected_object;
656 3916 : move16();
657 3916 : Copy32( data_in[selected_object], data_separated_object_fx, input_frame );
658 3916 : IF( fade_out_separate_object )
659 : {
660 131 : v_L_mult_3216( data_separated_object_fx, hOMasa->fade_out_gain_fx, data_separated_object_fx, input_frame ); /*q_data + q15 -q15*/
661 131 : v_L_mult_3216( data_in[selected_object], hOMasa->fade_in_gain_fx, data_in[selected_object], input_frame ); /*q_data + q15 -q15*/
662 : }
663 3785 : ELSE IF( fade_in_separate_object )
664 : {
665 125 : v_L_mult_3216( data_separated_object_fx, hOMasa->fade_in_gain_fx, data_separated_object_fx, input_frame ); /*q_data + q15 -q15*/
666 125 : v_L_mult_3216( data_in[selected_object], hOMasa->fade_out_gain_fx, data_in[selected_object], input_frame ); /*q_data + q15 -q15*/
667 : }
668 : ELSE
669 : {
670 3660 : set_zero_fx( data_in[selected_object], input_frame );
671 : }
672 : }
673 :
674 : /* Analysis */
675 5858 : test();
676 5858 : IF( EQ_16( ism_mode, ISM_MODE_NONE ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
677 3996 : {
678 : OMASA_SPATIAL_META OMasaMeta; /* working memory for the ISM-object MASA-parameters */
679 : OMASA_SPATIAL_META_HANDLE hOMasaMeta;
680 : UWord8 n_bands_orig, n_subframes_orig;
681 : UWord8 numCodingBands_orig, joinedSubframes_orig;
682 :
683 3996 : hOMasaMeta = &OMasaMeta;
684 3996 : hOMasaMeta->num_dirs = 1;
685 3996 : move16();
686 :
687 : /* merge MASA directions before adding ISM to the mixture */
688 3996 : IF( EQ_16( hMasa->config.numberOfDirections, 2 ) )
689 : {
690 2198 : n_bands_orig = hMasa->config.numCodingBands;
691 2198 : move16();
692 2198 : hMasa->config.numCodingBands = MASA_FREQUENCY_BANDS;
693 2198 : move16();
694 : /* Estimate the importance of having two directions instead of one */
695 :
696 2198 : ivas_masa_combine_directions_fx( hMasa );
697 :
698 2198 : hMasa->config.numCodingBands = (Word8) n_bands_orig;
699 2198 : move16();
700 : }
701 :
702 : /* force computation into high resolution */
703 :
704 3996 : n_subframes_orig = hOMasa->nSubframes;
705 3996 : hOMasa->nSubframes = MAX_PARAM_SPATIAL_SUBFRAMES;
706 3996 : move16();
707 3996 : move16();
708 :
709 : /* Estimate MASA parameters from the objects */
710 : /* NB: only first direction is populated */
711 : /* NB2: in energy_ratios and surround_coherence only first sub-frame contains valid data */
712 3996 : ivas_omasa_param_est_enc_fx( hOMasa, hMasa->data.hOmasaData, hIsmMeta, data_in, hOMasaMeta->directional_meta[0].elevation_fx, hOMasaMeta->directional_meta[0].azimuth_fx, hOMasaMeta->directional_meta[0].energy_ratio_fx[0], hOMasaMeta->directional_meta[0].spread_coherence_fx, hOMasaMeta->common_meta.surround_coherence_fx[0],
713 3996 : hOMasaMeta->common_meta.diffuse_to_total_ratio_fx[0], input_frame, nchan_ism, q_data );
714 :
715 : /* copy energy_ratios and surrCoh from first sub-frame to the remaining ones */
716 15984 : FOR( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
717 : {
718 11988 : Copy32( hOMasaMeta->directional_meta[0].energy_ratio_fx[0], hOMasaMeta->directional_meta[0].energy_ratio_fx[i], MASA_FREQUENCY_BANDS ); /*q30*/
719 11988 : Copy( hOMasaMeta->common_meta.surround_coherence_fx[0], hOMasaMeta->common_meta.surround_coherence_fx[i], MASA_FREQUENCY_BANDS ); /*q14*/
720 11988 : Copy32( hOMasaMeta->common_meta.diffuse_to_total_ratio_fx[0], hOMasaMeta->common_meta.diffuse_to_total_ratio_fx[i], MASA_FREQUENCY_BANDS ); /*q30*/
721 : }
722 :
723 : /* restore resolution parameters */
724 3996 : hOMasa->nSubframes = n_subframes_orig;
725 3996 : move16();
726 :
727 : /* perform MASA+ISM merge in full resolution */
728 3996 : numCodingBands_orig = hMasa->config.numCodingBands;
729 3996 : joinedSubframes_orig = hMasa->config.joinedSubframes;
730 3996 : move16();
731 3996 : move16();
732 :
733 3996 : hMasa->config.numCodingBands = hOMasa->nbands;
734 3996 : hMasa->config.joinedSubframes = 0;
735 3996 : move16();
736 3996 : move16();
737 :
738 3996 : ivas_merge_masa_metadata_fx( hMasa, hOMasaMeta ); /* => merge result in hMasa->masaMetadata */
739 :
740 3996 : hMasa->config.numCodingBands = numCodingBands_orig;
741 3996 : hMasa->config.joinedSubframes = joinedSubframes_orig;
742 3996 : move16();
743 3996 : move16();
744 : }
745 1862 : ELSE IF( EQ_16( ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
746 : {
747 : /* Estimate energies and ratios */
748 1862 : ivas_omasa_energy_and_ratio_est_fx( hOMasa, hMasa->data.hOmasaData, data_in, input_frame, nchan_ism, q_data );
749 : }
750 :
751 : /* Downmix */
752 :
753 5858 : ivas_omasa_dmx_fx( data_in, data_out, input_frame, nchan_transport, nchan_ism, hIsmMeta, hOMasa->prev_object_dm_gains_fx, hOMasa->interpolator_fx );
754 : /* Move the ISM metadata to the first entry for encoding in the MASA_ONE_OBJ mode */
755 5858 : IF( EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
756 : {
757 2054 : hIsmMeta[0]->azimuth_fx = hIsmMeta[*idx_separated_object]->azimuth_fx; // Q22
758 2054 : hIsmMeta[0]->elevation_fx = hIsmMeta[*idx_separated_object]->elevation_fx; // Q22
759 2054 : move32();
760 2054 : move32();
761 : }
762 :
763 : /* Merge transport signals */
764 5858 : ivas_merge_masa_transports_fx( data_out, &( data_in[nchan_ism] ), data_in, input_frame, nchan_transport );
765 :
766 5858 : return;
767 : }
768 :
769 :
770 : /*-------------------------------------------------------------------------*
771 : * ivas_set_ism_importance_interformat()
772 : *
773 : * Set the importance of particular ISM streams in combined-format coding
774 : *-------------------------------------------------------------------------*/
775 :
776 7058 : void ivas_set_ism_importance_interformat_fx(
777 : const Word32 ism_total_brate, /* i/o: ISms total bitrate */
778 : const Word16 nchan_transport, /* i : number of transported channels */
779 : ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */
780 : SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */
781 : const Word16 lp_noise_CPE_fx, /* i : LP filtered total noise estimation Q8 */
782 : Word16 ism_imp[] /* o : ISM importance flags */
783 : )
784 : {
785 : Encoder_State *st;
786 : Word16 ch, ctype, active_flag;
787 :
788 19434 : FOR( ch = 0; ch < nchan_transport; ch++ )
789 : {
790 12376 : st = hSCE[ch]->hCoreCoder[0];
791 :
792 12376 : active_flag = st->vad_flag;
793 12376 : move16();
794 :
795 12376 : IF( active_flag == 0 )
796 : {
797 272 : test();
798 272 : if ( GT_16( st->lp_noise_fx, 3840 /* 15 in Q8 */ ) || LT_16( sub( lp_noise_CPE_fx, st->lp_noise_fx ), 7680 /* 30 in Q8 */ ) )
799 : {
800 272 : active_flag = 1;
801 272 : move16();
802 : }
803 : }
804 :
805 : Word32 quo, rem;
806 12376 : iDiv_and_mod_32( ism_total_brate, nchan_transport, &quo, &rem, 0 );
807 :
808 : /* do not use the low-rate core-coder mode at highest bit-rates */
809 12376 : if ( GT_32( quo, IVAS_48k ) )
810 : {
811 1428 : active_flag = 1;
812 1428 : move16();
813 : }
814 :
815 12376 : ctype = hSCE[ch]->hCoreCoder[0]->coder_type_raw;
816 12376 : move16();
817 :
818 12376 : st->low_rate_mode = 0;
819 12376 : move16();
820 12376 : test();
821 12376 : IF( active_flag == 0 )
822 : {
823 0 : ism_imp[ch] = ISM_INACTIVE_IMP;
824 0 : move16();
825 0 : st->low_rate_mode = 1;
826 0 : move16();
827 : }
828 12376 : ELSE IF( EQ_16( ctype, INACTIVE ) || EQ_16( ctype, UNVOICED ) )
829 : {
830 449 : ism_imp[ch] = ISM_LOW_IMP;
831 449 : move16();
832 : }
833 11927 : ELSE IF( EQ_16( ctype, VOICED ) )
834 : {
835 3105 : ism_imp[ch] = ISM_MEDIUM_IMP;
836 3105 : move16();
837 : }
838 : ELSE /* GENERIC */
839 : {
840 8822 : ism_imp[ch] = ISM_HIGH_IMP;
841 8822 : move16();
842 : }
843 :
844 12376 : hIsmMeta[ch]->ism_metadata_flag = active_flag; /* flag is needed for the MD coding */
845 12376 : move16();
846 : }
847 :
848 7058 : return;
849 : }
850 :
851 : /*--------------------------------------------------------------------------*
852 : * ivas_set_surplus_brate_enc()
853 : *
854 : * set bit-rate surplus in combined format coding
855 : *--------------------------------------------------------------------------*/
856 :
857 9000 : void ivas_set_surplus_brate_enc(
858 : Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */
859 : #ifdef DEBUG_MODE_INFO
860 : ,
861 : const int16_t *nb_bits_metadata /* i : number of metadata bits */
862 : #endif
863 : )
864 : {
865 9000 : test();
866 9000 : IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) )
867 : {
868 1862 : st_ivas->hCPE[0]->brate_surplus = L_sub( st_ivas->hSCE[0]->element_brate, ivas_interformat_brate_fx( ISM_MASA_MODE_PARAM_ONE_OBJ, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ) );
869 1862 : move32();
870 : /* note: ISM st->total_brate is iset in ivas_sce_enc() */
871 : }
872 7138 : ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
873 : {
874 : /* it is already set in ivas_ism_enc() */
875 : }
876 : ELSE
877 : {
878 1942 : st_ivas->hCPE[0]->brate_surplus = 0;
879 1942 : move32();
880 : }
881 :
882 : #ifdef DEBUG_MODE_INFO
883 : if ( st_ivas->hSCE[0] != NULL )
884 : {
885 : int16_t input_frame = (int16_t) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC );
886 : float tmpF = 0;
887 :
888 : if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ )
889 : {
890 : tmpF += st_ivas->hSCE[0]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[1] * 50 );
891 : }
892 : else
893 : {
894 : for ( int16_t i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ )
895 : {
896 : tmpF += st_ivas->hSCE[i]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[i + 1] * 50 );
897 : }
898 : }
899 : tmpF /= 1000.f;
900 : dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_ISM" ); /* == ism_total_brate incl. ISM MD */
901 : tmpF = st_ivas->hEncoderConfig->ivas_total_brate / 1000.0f - tmpF;
902 : dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA" ); /* == masa_total_brate incl. MASA MD */
903 : tmpF = nb_bits_metadata[0] * FRAMES_PER_SEC / 1000.0f;
904 : dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA_MD" ); /* == MASA MD bitrate */
905 : }
906 : #endif
907 :
908 9000 : return;
909 : }
910 :
911 :
912 : /*--------------------------------------------------------------------------*
913 : * ivas_omasa_ener_brate()
914 : *
915 : *
916 : *--------------------------------------------------------------------------*/
917 :
918 : /*! r: OMASA energy bitrate flag */
919 3142 : Word16 ivas_omasa_ener_brate_fx(
920 : const Word16 nchan_ism, /* i : number of ISMs */
921 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
922 : Word32 *data_f[], /* i : Input / transport audio signals data_e*/
923 : const Word16 input_frame, /* i : Input frame size */
924 : Word16 data_e /*i:exponent for data_f */
925 : )
926 : {
927 : Word16 i, flag_omasa_ener_brate;
928 : Word32 energy_ism, energy_masa;
929 : Word16 energy_ism_e, energy_masa_e;
930 : Word32 temp_32;
931 : Word16 temp, temp_e;
932 3142 : flag_omasa_ener_brate = 0;
933 3142 : energy_ism_e = 0;
934 3142 : energy_masa_e = 0;
935 3142 : move16();
936 3142 : move16();
937 3142 : move16();
938 :
939 3142 : test();
940 3142 : IF( GE_16( nchan_ism, 3 ) && EQ_32( ivas_total_brate, IVAS_128k ) )
941 : {
942 126 : energy_ism = 0;
943 126 : move32();
944 570 : FOR( i = 0; i < nchan_ism; i++ )
945 : {
946 444 : temp_e = data_e;
947 444 : move16();
948 444 : temp_32 = sum2_32_fx( data_f[i], input_frame, &temp_e );
949 444 : energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, temp_32, temp_e, &energy_ism_e );
950 : }
951 :
952 126 : energy_masa = 0;
953 126 : move32();
954 378 : FOR( i = nchan_ism; i < nchan_ism + MASA_MAXIMUM_DIRECTIONS; i++ )
955 : {
956 252 : temp_e = data_e;
957 252 : move16();
958 252 : temp_32 = sum2_32_fx( data_f[i], input_frame, &temp_e );
959 252 : energy_masa = BASOP_Util_Add_Mant32Exp( energy_masa, energy_masa_e, temp_32, temp_e, &energy_masa_e );
960 : }
961 126 : IF( energy_masa_e < 0 )
962 : {
963 0 : energy_masa = L_shl( energy_masa, energy_masa_e );
964 0 : energy_masa_e = 0;
965 0 : move16();
966 : }
967 126 : energy_masa = L_shr( energy_masa, 1 );
968 126 : energy_masa_e = add( energy_masa_e, 1 );
969 126 : temp = divide1616( 2, nchan_ism ); /*q15*/
970 126 : energy_ism = BASOP_Util_Divide3232_Scale( energy_ism, L_add( energy_masa, L_shr( ONE_IN_Q31, energy_masa_e ) ), &temp_e );
971 126 : energy_ism_e = add( temp_e, sub( energy_ism_e, energy_masa_e ) );
972 126 : energy_ism = Mpy_32_16_1( energy_ism, temp );
973 126 : IF( energy_ism_e < 0 )
974 : {
975 15 : energy_ism = L_shl( energy_ism, energy_ism_e ); // Q31
976 15 : energy_ism_e = 0;
977 15 : move16();
978 : }
979 :
980 126 : IF( LT_32( energy_ism, L_shr( ONE_IN_Q31, energy_ism_e ) ) )
981 : {
982 126 : flag_omasa_ener_brate = 1;
983 126 : move16();
984 : }
985 : }
986 :
987 3142 : return flag_omasa_ener_brate;
988 : }
989 :
990 : /*--------------------------------------------------------------------------*
991 : * Local functions
992 : *--------------------------------------------------------------------------*/
993 :
994 : /* Estimate MASA parameters from the objects */
995 3996 : static void ivas_omasa_param_est_enc_fx(
996 : OMASA_ENC_HANDLE hOMasa,
997 : OMASA_ENCODER_DATA_HANDLE hOmasaData,
998 : ISM_METADATA_HANDLE hIsmMeta[],
999 : Word32 *data[], /*i:q_data*/
1000 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:q22*/
1001 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:q22*/
1002 : Word32 energyRatio_fx[MASA_FREQUENCY_BANDS], /*o:Q30*/
1003 : Word16 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /*o:Q15*/
1004 : Word16 surroundingCoherence_fx[MASA_FREQUENCY_BANDS], /*o:Q15*/
1005 : Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS], /*o:q30*/
1006 : const Word16 input_frame,
1007 : const Word16 nchan_ism,
1008 : Word16 q_data /*i: Qfactor for data*/
1009 : )
1010 : {
1011 : Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; // Q(31-ref_exp)
1012 : Word16 ref_exp;
1013 : Word16 ts, i, j, d, k;
1014 : Word16 num_freq_bins, num_freq_bands, index;
1015 : Word32 dir_v_fx[DIRAC_NUM_DIMS];
1016 : Word16 dir_v_e;
1017 : Word16 l_ts;
1018 : Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
1019 : Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
1020 : Word16 norm_buff;
1021 : Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1022 : Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1023 : Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
1024 : Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
1025 : Word16 intensity_real_e; /*exponent for intensity_real_fx*/
1026 : Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
1027 : Word16 q_diffuseness_vector;
1028 : Word32 norm_tmp_fx;
1029 : Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
1030 : Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
1031 : Word16 band_m_idx, block_m_idx;
1032 : Word16 mrange[2], brange[2];
1033 : Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
1034 : Word16 azimuth_16, elevation_16;
1035 : Word16 band_grouping_diff[MASA_FREQUENCY_BANDS], guard_bits, max_band_grouping_diff;
1036 : Word16 q; /*stores q for cldfb buffers*/
1037 : Word32 temp;
1038 : Word16 temp_e;
1039 :
1040 3996 : ref_exp = 0;
1041 3996 : norm_buff = MAX16B;
1042 3996 : dir_v_e = MIN_16;
1043 3996 : num_freq_bins = hOMasa->cldfbAnaEnc[0]->no_channels;
1044 3996 : num_freq_bands = hOMasa->nbands;
1045 3996 : l_ts = idiv1616( input_frame, CLDFB_NO_COL_MAX );
1046 3996 : move16();
1047 3996 : move16();
1048 3996 : move16();
1049 3996 : move16();
1050 3996 : move16();
1051 :
1052 : /* Need to initialize renormalization_factors, and variables to be normalized */
1053 3996 : set_zero_fx( &Foa_RealBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX );
1054 3996 : set_zero_fx( &Foa_ImagBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX );
1055 :
1056 3996 : set_zero_fx( renormalization_factor_diff_fx, hOMasa->nbands );
1057 3996 : set_zero_fx( diffuseness_m_fx, hOMasa->nbands );
1058 3996 : set16_fx( renormalization_factor_diff_e, 0, hOMasa->nbands );
1059 3996 : set16_fx( diffuseness_e, 0, hOMasa->nbands );
1060 17156 : FOR( i = 0; i < nchan_ism; i++ )
1061 : {
1062 13160 : set_zero_fx( Chnl_RealBuffer_fx[i], 60 );
1063 13160 : set_zero_fx( Chnl_ImagBuffer_fx[i], 60 );
1064 : }
1065 : /* Compute ISM to FOA matrices */
1066 17156 : FOR( i = 0; i < nchan_ism; i++ )
1067 : {
1068 13160 : azimuth_16 = extract_l( Mpy_32_32( hIsmMeta[i]->azimuth_fx, 46603 /*1<<24/360*/ ) ); /*q15*/
1069 13160 : elevation_16 = extract_l( Mpy_32_32( hIsmMeta[i]->elevation_fx, 46603 /*1<<24/360*/ ) ); /*q15*/
1070 13160 : hOMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; /*q31*/
1071 13160 : hOMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( azimuth_16 ), getCosWord16R2( elevation_16 ) ); /*q31*/
1072 13160 : hOMasa->chnlToFoaMtx_fx[2][i] = L_deposit_h( getSineWord16R2( elevation_16 ) ); /*q31*/
1073 13160 : hOMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( azimuth_16 ), getCosWord16R2( elevation_16 ) ); /*q31*/
1074 13160 : move32();
1075 13160 : move32();
1076 13160 : move32();
1077 13160 : move32();
1078 : }
1079 :
1080 3996 : q = q_data;
1081 3996 : move16();
1082 : /* do processing over all CLDFB time slots */
1083 19980 : FOR( block_m_idx = 0; block_m_idx < hOMasa->nSubframes; block_m_idx++ )
1084 : {
1085 15984 : mrange[0] = hOMasa->block_grouping[block_m_idx];
1086 15984 : mrange[1] = hOMasa->block_grouping[block_m_idx + 1];
1087 15984 : move16();
1088 15984 : move16();
1089 :
1090 396000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
1091 : {
1092 380016 : hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
1093 380016 : hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
1094 380016 : hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
1095 380016 : hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
1096 380016 : hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
1097 380016 : hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
1098 380016 : move32();
1099 380016 : move32();
1100 380016 : move32();
1101 380016 : move16();
1102 380016 : move16();
1103 380016 : move16();
1104 : }
1105 15984 : set_zero_fx( hOmasaData->energy_ism_fx[block_m_idx], num_freq_bands );
1106 15984 : set16_fx( hOmasaData->energy_ism_fx_e[block_m_idx], 0, num_freq_bands );
1107 88304 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
1108 : {
1109 72320 : norm_buff = MAX16B;
1110 72320 : move16();
1111 311616 : FOR( i = 0; i < nchan_ism; i++ )
1112 : {
1113 239296 : q = q_data;
1114 239296 : move16();
1115 239296 : cldfbAnalysis_ts_fx_var_q( &( data[i][l_ts * ts] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &q ); /*q_data-5*/
1116 239296 : norm_buff = s_min( norm_buff, L_norm_arr( Chnl_RealBuffer_fx[i], 60 ) );
1117 239296 : norm_buff = s_min( norm_buff, L_norm_arr( Chnl_ImagBuffer_fx[i], 60 ) );
1118 : }
1119 : /* Compute energy */
1120 1792416 : FOR( i = 0; i < num_freq_bands; i++ )
1121 : {
1122 1720096 : band_grouping_diff[i] = sub( hOMasa->band_grouping[i + 1], hOMasa->band_grouping[i] );
1123 1720096 : move16();
1124 : }
1125 72320 : maximum_abs_16_fx( band_grouping_diff, num_freq_bands, &max_band_grouping_diff );
1126 72320 : guard_bits = find_guarded_bits_fx( num_freq_bins );
1127 72320 : norm_buff = sub( norm_buff, guard_bits );
1128 311616 : FOR( i = 0; i < nchan_ism; i++ )
1129 : {
1130 239296 : scale_sig32( Chnl_RealBuffer_fx[i], 60, norm_buff );
1131 239296 : scale_sig32( Chnl_ImagBuffer_fx[i], 60, norm_buff );
1132 : }
1133 72320 : q = add( q, norm_buff );
1134 1792416 : FOR( i = 0; i < num_freq_bands; i++ )
1135 : {
1136 1720096 : brange[0] = hOMasa->band_grouping[i];
1137 1720096 : brange[1] = hOMasa->band_grouping[i + 1];
1138 1720096 : move16();
1139 1720096 : move16();
1140 7426048 : FOR( k = 0; k < nchan_ism; k++ )
1141 : {
1142 19512672 : FOR( j = brange[0]; j < brange[1]; j++ )
1143 : {
1144 13806720 : temp = L_add( Mpy_32_32( Chnl_RealBuffer_fx[k][j], Chnl_RealBuffer_fx[k][j] ), Mpy_32_32( Chnl_ImagBuffer_fx[k][j], Chnl_ImagBuffer_fx[k][j] ) );
1145 13806720 : temp_e = sub( 62, shl( q, 1 ) );
1146 13806720 : hOmasaData->energy_ism_fx[block_m_idx][i] = BASOP_Util_Add_Mant32Exp( hOmasaData->energy_ism_fx[block_m_idx][i], hOmasaData->energy_ism_fx_e[block_m_idx][i], temp, temp_e, &hOmasaData->energy_ism_fx_e[block_m_idx][i] ); /*2q-31*/
1147 13806720 : move32();
1148 : }
1149 : }
1150 : }
1151 :
1152 : /* Compute FOA */
1153 : /* W */
1154 72320 : Copy32( Chnl_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*q*/
1155 72320 : Copy32( Chnl_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*q*/
1156 239296 : FOR( i = 1; i < nchan_ism; i++ )
1157 : {
1158 166976 : v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins );
1159 166976 : v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins );
1160 : }
1161 :
1162 : /* Y */
1163 72320 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*q*/
1164 72320 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*q*/
1165 239296 : FOR( i = 1; i < nchan_ism; i++ )
1166 : {
1167 166976 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*q*/
1168 166976 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*q*/
1169 : }
1170 :
1171 : /* Z */
1172 72320 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*q*/
1173 72320 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*q*/
1174 239296 : FOR( i = 1; i < nchan_ism; i++ )
1175 : {
1176 166976 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*q*/
1177 166976 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*q*/
1178 : }
1179 :
1180 :
1181 : /* X */
1182 72320 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*q*/
1183 72320 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); /*q*/
1184 239296 : FOR( i = 1; i < nchan_ism; i++ )
1185 : {
1186 166976 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*q*/
1187 166976 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*q*/
1188 : }
1189 : /* Direction estimation */
1190 72320 : norm_buff = L_norm_arr( &Foa_RealBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX );
1191 72320 : norm_buff = s_min( norm_buff, L_norm_arr( &Foa_ImagBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ) );
1192 72320 : guard_bits = find_guarded_bits_fx( max_band_grouping_diff );
1193 72320 : guard_bits = add( guard_bits, sub( 1, norm_buff ) );
1194 72320 : computeIntensityVector_enc_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx, guard_bits );
1195 72320 : intensity_real_e = sub( add( 62, guard_bits ), shl( q, 1 ) );
1196 :
1197 72320 : computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], intensity_real_e,
1198 : NULL );
1199 :
1200 : /* Power estimation for diffuseness */
1201 :
1202 72320 : computeReferencePower_omasa_ivas_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], 0, num_freq_bands, q, &ref_exp );
1203 :
1204 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
1205 72320 : hOMasa->index_buffer_intensity = add( ( hOMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
1206 72320 : index = hOMasa->index_buffer_intensity;
1207 72320 : move16();
1208 72320 : move16();
1209 289280 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
1210 : {
1211 : /* only real part needed */
1212 216960 : Copy32( intensity_real_fx[i], &( hOMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands );
1213 : }
1214 72320 : hOMasa->buffer_intensity_real_q[index - 1] = sub( 31, intensity_real_e );
1215 72320 : move16();
1216 72320 : Copy32( reference_power_fx[ts], &( hOMasa->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands );
1217 72320 : hOMasa->buffer_energy_q[( index - 1 )] = sub( 31, ref_exp );
1218 72320 : move16();
1219 72320 : computeDiffuseness_fixed( hOMasa->buffer_intensity_real_fx, hOMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hOMasa->buffer_intensity_real_q, hOMasa->buffer_energy_q, &q_diffuseness_vector );
1220 :
1221 1792416 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
1222 : {
1223 1720096 : temp_e = norm_l( reference_power_fx[ts][band_m_idx] );
1224 1720096 : reference_power_fx[ts][band_m_idx] = L_shl( reference_power_fx[ts][band_m_idx], temp_e );
1225 1720096 : move32();
1226 1720096 : norm_tmp_fx = Mpy_32_32( reference_power_fx[ts][band_m_idx], L_sub( L_shl( 1, q_diffuseness_vector ), diffuseness_vector_fx[band_m_idx] ) ); /*30+(31-(ref_exp-temp_e))-31*/
1227 :
1228 1720096 : hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hOMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mpy_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), sub( add( ref_exp, 2 ), temp_e ), &hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] ); /*hOMasa->direction_vector_e[0][block_m_idx][band_m_idx]*/
1229 1720096 : hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hOMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mpy_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), sub( add( ref_exp, 2 ), temp_e ), &hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] ); /*hOMasa->direction_vector_e[1][block_m_idx][band_m_idx]*/
1230 1720096 : hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hOMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mpy_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), sub( add( ref_exp, 2 ), temp_e ), &hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] ); /*hOMasa->direction_vector_e[2][block_m_idx][band_m_idx]*/
1231 1720096 : move32();
1232 1720096 : move32();
1233 1720096 : move32();
1234 :
1235 1720096 : diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], W_extract_l( W_shr( W_mult0_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), 30 ) ), sub( ref_exp, temp_e ), &diffuseness_e[band_m_idx] ); /*diffuseness_e[band_m_idx]*/
1236 1720096 : renormalization_factor_diff_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], reference_power_fx[ts][band_m_idx], sub( ref_exp, temp_e ), &renormalization_factor_diff_e[band_m_idx] ); /*renormalization_factor_diff_e[band_m_idx]*/
1237 1720096 : move32();
1238 1720096 : move32();
1239 : }
1240 : }
1241 :
1242 396000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
1243 : {
1244 380016 : dir_v_e = MIN_16;
1245 380016 : move16();
1246 1520064 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
1247 : {
1248 1140048 : dir_v_fx[d] = hOMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx];
1249 1140048 : move32();
1250 1140048 : dir_v_e = s_max( dir_v_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) + 1;
1251 : }
1252 1520064 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
1253 : {
1254 1140048 : dir_v_fx[d] = L_shr( hOMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( dir_v_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) );
1255 1140048 : move32();
1256 : }
1257 :
1258 380016 : ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, sub( 31, dir_v_e ), &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] );
1259 : }
1260 :
1261 : /* Set coherences to zero, as this mode is used at lowest bit rates where the coherences are not transmitted */
1262 396000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
1263 : {
1264 380016 : spreadCoherence_fx[block_m_idx][band_m_idx] = 0;
1265 380016 : surroundingCoherence_fx[band_m_idx] = 0;
1266 380016 : move16();
1267 380016 : move16();
1268 : }
1269 : }
1270 :
1271 : /* Determine energy ratios */
1272 99000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
1273 : {
1274 95004 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], 1 /*EPSILON Q50*/, -19 ), 1 ) )
1275 : {
1276 95004 : diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], L_add( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ), &temp_e ); // Q=15-temp_e
1277 95004 : temp_e = add( temp_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
1278 : }
1279 : ELSE
1280 : {
1281 0 : diffuseness_m_fx[band_m_idx] = 0;
1282 0 : temp_e = 0;
1283 0 : move16();
1284 : }
1285 95004 : move32();
1286 95004 : diffuseness_m_fx[band_m_idx] = L_shl( diffuseness_m_fx[band_m_idx], add( 15, temp_e ) ); // Scaling to Q30
1287 95004 : energyRatio_fx[band_m_idx] = L_sub( ONE_IN_Q30, diffuseness_m_fx[band_m_idx] ); // Q30
1288 95004 : move32();
1289 95004 : move32();
1290 : }
1291 3996 : return;
1292 : }
1293 :
1294 :
1295 : /* Estimate energies and ratios */
1296 1862 : static void ivas_omasa_energy_and_ratio_est_fx(
1297 : OMASA_ENC_HANDLE hOMasa,
1298 : OMASA_ENCODER_DATA_HANDLE hOmasaData,
1299 : Word32 *data_fx[], /*i: q_data*/
1300 : const Word16 input_frame,
1301 : const Word16 nchan_ism,
1302 : const Word16 q_data /*i: stoes the q for data_fx*/
1303 : )
1304 : {
1305 : Word16 ts, i, j, k;
1306 : Word16 num_freq_bands;
1307 : Word16 l_ts;
1308 : Word32 Chnl_RealBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
1309 : Word32 Chnl_ImagBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
1310 : Word16 block_m_idx;
1311 : Word16 mrange[2], brange[2];
1312 : Word32 tftile_energy_fx;
1313 : Word16 tftile_energy_e;
1314 : Word64 ism_ratio_sum_fx;
1315 : Word16 q_cldfb;
1316 : Word16 norm_Chnl;
1317 : Word16 temp_e; /* to store temporary exp*/
1318 : Word16 energy_ratio_ism_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; /*q30*/
1319 1862 : num_freq_bands = hOMasa->nbands;
1320 1862 : l_ts = shr( input_frame, 4 ); /*input_frame / CLDFB_NO_COL_MAX*/
1321 1862 : q_cldfb = q_data;
1322 1862 : move16(); /*num_freq_bands*/
1323 1862 : move16(); /*q_cldfb*/
1324 1862 : set_zero_fx( &Chnl_RealBuffer_fx[0][0], MAX_NUM_OBJECTS * CLDFB_NO_CHANNELS_MAX );
1325 1862 : set_zero_fx( &Chnl_ImagBuffer_fx[0][0], MAX_NUM_OBJECTS * CLDFB_NO_CHANNELS_MAX );
1326 : /* do processing over all CLDFB time slots */
1327 8176 : FOR( block_m_idx = 0; block_m_idx < hOMasa->nSubframes; block_m_idx++ )
1328 : {
1329 6314 : mrange[0] = hOMasa->block_grouping[block_m_idx];
1330 6314 : mrange[1] = hOMasa->block_grouping[block_m_idx + 1];
1331 6314 : move16();
1332 6314 : move16();
1333 :
1334 : /* Reset variable */
1335 40530 : FOR( i = 0; i < hOMasa->nbands; i++ )
1336 : {
1337 34216 : set_zero_fx( hOmasaData->energy_ratio_ism_fx[block_m_idx][i], nchan_ism );
1338 34216 : set16_fx( energy_ratio_ism_e[block_m_idx][i], 0, nchan_ism );
1339 : }
1340 6314 : set_zero_fx( hOmasaData->energy_ism_fx[block_m_idx], num_freq_bands );
1341 6314 : set16_fx( hOmasaData->energy_ism_fx_e[block_m_idx], 0, num_freq_bands );
1342 : /* Compute CLDFB */
1343 36106 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
1344 : {
1345 29792 : norm_Chnl = MAX_16;
1346 29792 : move16();
1347 130272 : FOR( i = 0; i < nchan_ism; i++ )
1348 : {
1349 100480 : q_cldfb = q_data;
1350 100480 : move16();
1351 100480 : scale_sig32( hOMasa->cldfbAnaEnc[i]->cldfb_state_fx, hOMasa->cldfbAnaEnc[i]->cldfb_state_length, sub( q_cldfb, hOMasa->cldfbAnaEnc[i]->Q_cldfb_state ) );
1352 100480 : hOMasa->cldfbAnaEnc[i]->Q_cldfb_state = q_cldfb;
1353 100480 : move16();
1354 100480 : cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][l_ts * ts] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &q_cldfb );
1355 100480 : norm_Chnl = s_min( norm_Chnl, L_norm_arr( Chnl_ImagBuffer_fx[i], 60 ) );
1356 100480 : norm_Chnl = s_min( norm_Chnl, L_norm_arr( Chnl_RealBuffer_fx[i], 60 ) );
1357 : }
1358 29792 : norm_Chnl = sub( norm_Chnl, 1 );
1359 : /*scaling cldfb buffers to avoid loss of values in Mpy_32_32*/
1360 130272 : FOR( i = 0; i < nchan_ism; i++ )
1361 : {
1362 100480 : scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, norm_Chnl );
1363 100480 : scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, norm_Chnl );
1364 : }
1365 29792 : q_cldfb = add( q_cldfb, norm_Chnl );
1366 : /* Compute energy */
1367 221088 : FOR( i = 0; i < num_freq_bands; i++ )
1368 : {
1369 191296 : brange[0] = hOMasa->band_grouping[i];
1370 191296 : brange[1] = hOMasa->band_grouping[i + 1];
1371 191296 : move16();
1372 191296 : move16();
1373 1835456 : FOR( j = brange[0]; j < brange[1]; j++ )
1374 : {
1375 7242880 : FOR( k = 0; k < nchan_ism; k++ )
1376 : {
1377 : Word64 tmp64;
1378 : Word16 tmpNorm;
1379 5598720 : tmp64 = W_add( W_mult0_32_32( Chnl_RealBuffer_fx[k][j], Chnl_RealBuffer_fx[k][j] ), W_mult0_32_32( Chnl_ImagBuffer_fx[k][j], Chnl_ImagBuffer_fx[k][j] ) ); // exp: 2 * (31 - q_cldfb) + 1
1380 5598720 : tftile_energy_e = sub( 63, shl( q_cldfb, 1 ) );
1381 5598720 : tmpNorm = W_norm( tmp64 );
1382 5598720 : tmp64 = W_shl( tmp64, tmpNorm );
1383 5598720 : tftile_energy_fx = W_extract_h( tmp64 );
1384 5598720 : tftile_energy_e = sub( tftile_energy_e, tmpNorm );
1385 5598720 : hOmasaData->energy_ism_fx[block_m_idx][i] = BASOP_Util_Add_Mant32Exp( hOmasaData->energy_ism_fx[block_m_idx][i], hOmasaData->energy_ism_fx_e[block_m_idx][i], tftile_energy_fx, tftile_energy_e, &hOmasaData->energy_ism_fx_e[block_m_idx][i] );
1386 5598720 : hOmasaData->energy_ratio_ism_fx[block_m_idx][i][k] = BASOP_Util_Add_Mant32Exp( hOmasaData->energy_ratio_ism_fx[block_m_idx][i][k], energy_ratio_ism_e[block_m_idx][i][k], tftile_energy_fx, tftile_energy_e, &energy_ratio_ism_e[block_m_idx][i][k] );
1387 5598720 : move32();
1388 5598720 : move32();
1389 : }
1390 : }
1391 : }
1392 : }
1393 :
1394 : /* Compute ISM energy ratios */
1395 40530 : FOR( i = 0; i < num_freq_bands; i++ )
1396 : {
1397 34216 : ism_ratio_sum_fx = 0;
1398 34216 : move64();
1399 148936 : FOR( j = 0; j < nchan_ism; j++ )
1400 : {
1401 114720 : hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j] = L_deposit_h( BASOP_Util_Divide3232_Scale( hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j], L_add( hOmasaData->energy_ism_fx[block_m_idx][i], EPSILON_FX ), &temp_e ) );
1402 114720 : move32();
1403 114720 : temp_e = add( temp_e, sub( energy_ratio_ism_e[block_m_idx][i][j], hOmasaData->energy_ism_fx_e[block_m_idx][i] ) );
1404 :
1405 114720 : hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j] = L_shl( hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j], sub( temp_e, 1 ) ); /* scaling to q30 */
1406 114720 : move32();
1407 114720 : ism_ratio_sum_fx = W_add( ism_ratio_sum_fx, hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j] );
1408 : }
1409 34216 : IF( ism_ratio_sum_fx == 0 )
1410 : {
1411 0 : Word16 temp_ism_ratio = BASOP_Util_Divide1616_Scale( 1, nchan_ism, &temp_e );
1412 0 : FOR( j = 0; j < nchan_ism; j++ )
1413 : {
1414 0 : hOmasaData->energy_ratio_ism_fx[block_m_idx][i][j] = L_shl( temp_ism_ratio, add( temp_e, 15 ) ); /*scaling to q30*/
1415 0 : move32();
1416 : }
1417 : }
1418 : }
1419 : }
1420 :
1421 1862 : return;
1422 : }
1423 :
1424 :
1425 : /* Compute downmix */
1426 5858 : static void ivas_omasa_dmx_fx(
1427 : Word32 *data_in[], /*i:Qx*/
1428 : Word32 data_out[][L_FRAME48k], /*i:Qx*/
1429 : const Word16 input_frame, /*i:q0*/
1430 : const Word16 nchan_transport, /*i:q0*/
1431 : const Word16 nchan_ism, /*i:q0*/
1432 : ISM_METADATA_HANDLE hIsmMeta[], /*i*/
1433 : Word16 prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], /*o:q15*/
1434 : const Word16 interpolator[L_FRAME48k] /*i:q15*/
1435 : )
1436 : {
1437 : Word16 i, j, k;
1438 : Word16 azimuth, elevation;
1439 : Word16 gains[MASA_MAX_TRANSPORT_CHANNELS];
1440 : Word16 g1, g2;
1441 :
1442 17574 : FOR( i = 0; i < nchan_transport; i++ )
1443 : {
1444 11716 : set_zero_fx( data_out[i], input_frame );
1445 : }
1446 :
1447 25298 : FOR( i = 0; i < nchan_ism; i++ )
1448 : {
1449 19440 : azimuth = extract_l( L_shr( L_add( hIsmMeta[i]->azimuth_fx, ONE_IN_Q21 ), 22 ) ); /* scaling from q22 to q0 for ivas_get_stereo_panning_gains_fx*/
1450 19440 : elevation = extract_l( L_shr( L_add( hIsmMeta[i]->elevation_fx, ONE_IN_Q21 ), 22 ) ); /* scaling from q22 to q0 for ivas_get_stereo_panning_gains_fx*/
1451 :
1452 : /*gains is q15*/
1453 : /*azimuth is q0*/
1454 : /*elevation is q0*/
1455 19440 : ivas_get_stereo_panning_gains_fx( azimuth, elevation, gains );
1456 :
1457 : /* Downmix using the panning gains */
1458 58320 : FOR( j = 0; j < nchan_transport; j++ )
1459 : {
1460 38880 : test();
1461 38880 : IF( abs_s( gains[j] ) > 0 || abs_s( prev_gains[i][j] ) > 0 )
1462 : {
1463 32614184 : FOR( k = 0; k < input_frame; k++ )
1464 : {
1465 32578560 : g1 = interpolator[k];
1466 32578560 : move16();
1467 32578560 : g2 = sub( MAX_WORD16, g1 ); /*q15*/
1468 32578560 : data_out[j][k] = L_add( data_out[j][k], Mpy_32_32( L_add( L_mult( g1, gains[j] ), L_mult( g2, prev_gains[i][j] ) ) /*q31*/, data_in[i][k] ) ); /*Qx*/
1469 32578560 : move32();
1470 : }
1471 : }
1472 38880 : prev_gains[i][j] = gains[j]; /*q15*/
1473 38880 : move16();
1474 : }
1475 : }
1476 :
1477 5858 : return;
1478 : }
1479 :
1480 72320 : void computeIntensityVector_enc_fx(
1481 : const Word16 *band_grouping, /* i : Band grouping for estimation */
1482 : Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */
1483 : Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal */
1484 : const Word16 num_frequency_bands, /* i : Number of frequency bands */
1485 : Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS], /* o : Intensity vector */
1486 : Word16 guard_bits )
1487 : {
1488 : /* Reminder
1489 : * X = a + ib; Y = c + id
1490 : * X*Y = ac - bd + i(ad +bc)
1491 : */
1492 : Word16 i, j;
1493 : Word32 real, img;
1494 : Word16 brange[2];
1495 :
1496 1792416 : FOR( i = 0; i < num_frequency_bands; i++ )
1497 : {
1498 1720096 : brange[0] = band_grouping[i];
1499 1720096 : move16();
1500 1720096 : brange[1] = band_grouping[i + 1];
1501 1720096 : move16();
1502 :
1503 1720096 : intensity_real[0][i] = 0;
1504 1720096 : move32();
1505 1720096 : intensity_real[1][i] = 0;
1506 1720096 : move32();
1507 1720096 : intensity_real[2][i] = 0;
1508 1720096 : move32();
1509 :
1510 5843616 : FOR( j = brange[0]; j < brange[1]; j++ )
1511 : {
1512 4123520 : real = Cldfb_RealBuffer[0][j];
1513 4123520 : img = Cldfb_ImagBuffer[0][j];
1514 : /* Intensity is XYZ order, audio is WYZX order. */
1515 4123520 : intensity_real[0][i] = L_add( intensity_real[0][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[3][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[3][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits
1516 4123520 : move32();
1517 4123520 : intensity_real[1][i] = L_add( intensity_real[1][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[1][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[1][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits
1518 4123520 : move32();
1519 4123520 : intensity_real[2][i] = L_add( intensity_real[2][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[2][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[2][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits
1520 4123520 : move32();
1521 : }
1522 : }
1523 :
1524 72320 : return;
1525 : }
1526 :
1527 :
1528 72320 : static void computeReferencePower_omasa_ivas_fx(
1529 : const Word16 *band_grouping, /* i : Band grouping for estimation */
1530 : Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal Q6*/
1531 : Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal Q6*/
1532 : Word32 *reference_power, /* o : Estimated power Q(31-ref_exp)*/
1533 : const Word16 enc_param_start_band, /* i : first band to process */
1534 : const Word16 num_freq_bands, /* i : Number of frequency bands */
1535 : Word16 q_Cldfb,
1536 : Word16 *ref_exp )
1537 : {
1538 : Word16 brange[2];
1539 : Word16 ch_idx, i, j;
1540 : Word64 reference_power_tmp[CLDFB_NO_CHANNELS_MAX];
1541 72320 : Word16 ref_Q = 63;
1542 72320 : move16();
1543 :
1544 1792416 : FOR( i = 0; i < num_freq_bands; i++ )
1545 : {
1546 1720096 : brange[0] = band_grouping[i + enc_param_start_band];
1547 1720096 : move16();
1548 1720096 : brange[1] = band_grouping[i + enc_param_start_band + 1];
1549 1720096 : move16();
1550 1720096 : reference_power[i] = 0;
1551 1720096 : move32();
1552 1720096 : reference_power_tmp[i] = 0;
1553 1720096 : move64();
1554 :
1555 8600480 : FOR( ch_idx = 0; ch_idx < FOA_CHANNELS; ch_idx++ )
1556 : {
1557 : /* abs()^2 */
1558 23374464 : FOR( j = brange[0]; j < brange[1]; j++ )
1559 : {
1560 16494080 : reference_power_tmp[i] = W_add( reference_power_tmp[i], W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[ch_idx][j], Cldfb_RealBuffer[ch_idx][j] ), Cldfb_ImagBuffer[ch_idx][j], Cldfb_ImagBuffer[ch_idx][j] ) ); // Q13 (Q6+Q6+1)
1561 16494080 : move64();
1562 : }
1563 : }
1564 : }
1565 : // v_multc( reference_power, 0.5f, reference_power, num_freq_bands );
1566 1792416 : FOR( i = 0; i < num_freq_bands; i++ )
1567 : {
1568 1720096 : reference_power_tmp[i] = W_shr( reference_power_tmp[i], 1 );
1569 1720096 : move64();
1570 1720096 : ref_Q = s_min( ref_Q, W_norm( reference_power_tmp[i] ) );
1571 : }
1572 :
1573 1792416 : FOR( i = 0; i < num_freq_bands; i++ )
1574 : {
1575 1720096 : reference_power_tmp[i] = W_shl( reference_power_tmp[i], ref_Q ); // Q13 + ref_Q
1576 1720096 : move64();
1577 1720096 : reference_power[i] = W_extract_h( reference_power_tmp[i] ); // Q13 + ref_Q -32
1578 1720096 : move32();
1579 : }
1580 :
1581 : // ref_exp = 31- ((13+ref_Q) -32)
1582 72320 : *ref_exp = sub( 31, ( sub( add( ref_Q, 2 * q_Cldfb + 1 ), 32 ) ) );
1583 72320 : move16();
1584 72320 : return;
1585 : }
|