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 <math.h>
36 : #include "ivas_cnst.h"
37 : #include "ivas_prot_rend_fx.h"
38 : #include "ivas_prot_fx.h"
39 : #include "prot_fx.h"
40 : #include "ivas_stat_rend.h"
41 : #include "ivas_rom_com.h"
42 : #include "wmc_auto.h"
43 :
44 : /*-------------------------------------------------------------------------
45 : * Local function prototypes
46 : *------------------------------------------------------------------------*/
47 :
48 :
49 : static void ivas_omasa_dmx_fx(
50 : Word32 data_in_f_fx[][L_FRAME48k],
51 : Word16 *data_in_q,
52 : const Word16 input_frame,
53 : const Word16 nchan_transport,
54 : const Word16 nchan_ism,
55 : const Word32 ism_azimuth_fx[MAX_NUM_OBJECTS],
56 : const Word32 ism_elevation_fx[MAX_NUM_OBJECTS],
57 : Word32 prev_gains_fx[][MASA_MAX_TRANSPORT_CHANNELS],
58 : const Word16 interpolator_fx[L_FRAME48k] );
59 :
60 :
61 : static void ivas_omasa_param_est_ana_fx(
62 : OMASA_ANA_HANDLE hOMasa,
63 : Word32 data_f_fx[][L_FRAME48k],
64 : Word16 data_f_q,
65 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
66 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
67 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
68 : Word16 *energyRatio_q,
69 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
70 : Word16 *spreadCoherence_q,
71 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
72 : Word16 *surroundingCoherence_q,
73 : const Word16 input_frame,
74 : const Word16 nchan_ism );
75 :
76 : /*--------------------------------------------------------------------------*
77 : * ivas_omasa_ana_open()
78 : *
79 : * Allocate and initialize OMASA handle
80 : *--------------------------------------------------------------------------*/
81 :
82 1 : ivas_error ivas_omasa_ana_open(
83 : OMASA_ANA_HANDLE *hOMasaPtr, /* i/o: OMASA data handle pointer */
84 : Word32 input_Fs, /* i : Sampling frequency */
85 : UWord16 total_num_objects /* i : Number of objects */
86 : )
87 : {
88 : Word16 i, j;
89 : OMASA_ANA_HANDLE hOMasa;
90 : Word16 numAnalysisChannels;
91 : Word16 maxBin, input_frame;
92 : ivas_error error;
93 : Word16 scale;
94 :
95 1 : error = IVAS_ERR_OK;
96 1 : move32();
97 :
98 1 : IF( ( hOMasa = (OMASA_ANA_HANDLE) malloc( sizeof( OMASA_ANA_DATA ) ) ) == NULL )
99 : {
100 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA\n" ) );
101 : }
102 :
103 1 : numAnalysisChannels = (Word16) total_num_objects;
104 1 : move16();
105 :
106 : /* Determine the number of bands */
107 1 : hOMasa->nbands = MASA_FREQUENCY_BANDS;
108 1 : move16();
109 :
110 : /* Determine band grouping */
111 1 : Copy( MASA_band_grouping_24, hOMasa->band_grouping, 24 + 1 );
112 :
113 : /* maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); */
114 1 : maxBin = extract_l( Mpy_32_32( input_Fs, 2684355 /* INV_CLDFB_BANDWIDTH in Q31 */ ) ); // Q: ( ( Q0 + Q31 ) - Q31 ) -> Q0
115 :
116 24 : FOR( i = 1; i < hOMasa->nbands + 1; i++ )
117 : {
118 24 : IF( GE_16( hOMasa->band_grouping[i], maxBin ) )
119 : {
120 1 : hOMasa->band_grouping[i] = maxBin;
121 1 : move16();
122 1 : hOMasa->nbands = i;
123 1 : move16();
124 1 : BREAK;
125 : }
126 : }
127 :
128 : /* Determine block grouping */
129 1 : Copy( DirAC_block_grouping, hOMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
130 :
131 : /* open/initialize CLDFB */
132 1 : hOMasa->num_Cldfb_instances = numAnalysisChannels;
133 5 : FOR( i = 0; i < hOMasa->num_Cldfb_instances; i++ )
134 : {
135 4 : IF( NE_32( ( error = openCldfb_ivas_fx( &( hOMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
136 : {
137 0 : return error;
138 : }
139 : }
140 :
141 1 : FOR( ; i < MAX_NUM_OBJECTS; i++ )
142 : {
143 0 : hOMasa->cldfbAnaEnc[i] = NULL;
144 : }
145 :
146 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
147 : {
148 3 : IF( ( hOMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL )
149 : {
150 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
151 : }
152 :
153 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
154 : {
155 12 : IF( ( hOMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
156 : {
157 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
158 : }
159 12 : set_zero_fx( hOMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS );
160 : }
161 3 : IF( ( hOMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL )
162 : {
163 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
164 : }
165 :
166 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
167 : {
168 12 : IF( ( hOMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL )
169 : {
170 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
171 : }
172 12 : set16_fx( hOMasa->direction_vector_e[i][j], 0, MASA_FREQUENCY_BANDS );
173 : }
174 : }
175 :
176 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
177 : {
178 99 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
179 : {
180 96 : IF( ( hOMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
181 : {
182 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
183 : }
184 96 : set_zero_fx( hOMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS );
185 : }
186 : }
187 1 : set16_fx( hOMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF );
188 1 : set16_fx( hOMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF );
189 1 : set_zero_fx( hOMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
190 :
191 5 : FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
192 : {
193 4 : set32_fx( hOMasa->prev_object_dm_gains_fx[i], INV_SQRT_2_Q31, MASA_MAX_TRANSPORT_CHANNELS );
194 : }
195 :
196 : /* input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); */
197 1 : input_frame = extract_l( Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) );
198 961 : FOR( i = 0; i < input_frame; i++ )
199 : {
200 960 : hOMasa->interpolator_fx[i] = BASOP_Util_Divide1616_Scale( i, input_frame, &scale );
201 960 : move16();
202 960 : hOMasa->interpolator_fx[i] = shl( hOMasa->interpolator_fx[i], scale ); // Q15
203 960 : move16();
204 : }
205 :
206 1 : hOMasa->index_buffer_intensity = 0;
207 1 : move16();
208 :
209 1 : IF( ( hOMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
210 : {
211 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
212 : }
213 :
214 1 : IF( ( hOMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
215 : {
216 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
217 : }
218 :
219 1 : generate_gridEq_fx( hOMasa->sph_grid16 );
220 :
221 5 : FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
222 : {
223 4 : set_zero_fx( hOMasa->energy_fx[i], MASA_FREQUENCY_BANDS );
224 : }
225 :
226 1 : set_zero_fx( hOMasa->ism_azimuth_fx, MAX_NUM_OBJECTS );
227 1 : set_zero_fx( hOMasa->ism_elevation_fx, MAX_NUM_OBJECTS );
228 :
229 1 : ( *hOMasaPtr ) = hOMasa;
230 :
231 1 : return error;
232 : }
233 :
234 : /*--------------------------------------------------------------------------*
235 : * ivas_omasa_ana_close()
236 : *
237 : * Close OMASA handle
238 : *--------------------------------------------------------------------------*/
239 :
240 2664 : void ivas_omasa_ana_close(
241 : OMASA_ANA_HANDLE *hOMasa /* i/o: analysis OMASA handle */
242 : )
243 : {
244 : Word16 i, j;
245 :
246 2664 : test();
247 2664 : IF( hOMasa == NULL || *hOMasa == NULL )
248 : {
249 2663 : return;
250 : }
251 :
252 5 : FOR( i = 0; i < ( *hOMasa )->num_Cldfb_instances; i++ )
253 : {
254 4 : deleteCldfb_ivas_fx( &( ( *hOMasa )->cldfbAnaEnc[i] ) );
255 : }
256 :
257 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
258 : {
259 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
260 : {
261 12 : free( ( *hOMasa )->direction_vector_m_fx[i][j] );
262 12 : ( *hOMasa )->direction_vector_m_fx[i][j] = NULL;
263 : }
264 :
265 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
266 : {
267 12 : free( ( *hOMasa )->direction_vector_e[i][j] );
268 12 : ( *hOMasa )->direction_vector_e[i][j] = NULL;
269 : }
270 :
271 99 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
272 : {
273 96 : free( ( *hOMasa )->buffer_intensity_real_fx[i][j] );
274 96 : ( *hOMasa )->buffer_intensity_real_fx[i][j] = NULL;
275 : }
276 :
277 3 : free( ( *hOMasa )->direction_vector_m_fx[i] );
278 3 : ( *hOMasa )->direction_vector_m_fx[i] = NULL;
279 :
280 3 : free( ( *hOMasa )->direction_vector_e[i] );
281 3 : ( *hOMasa )->direction_vector_e[i] = NULL;
282 : }
283 :
284 1 : free( ( *hOMasa )->hMasaOut );
285 1 : ( *hOMasa )->hMasaOut = NULL;
286 1 : free( ( *hOMasa )->sph_grid16 );
287 1 : ( *hOMasa )->sph_grid16 = NULL;
288 :
289 1 : free( ( *hOMasa ) );
290 1 : ( *hOMasa ) = NULL;
291 :
292 1 : return;
293 : }
294 :
295 : /*--------------------------------------------------------------------------*
296 : * ivas_omasa_ana()
297 : *
298 : * OMASA analysis function
299 : *--------------------------------------------------------------------------*/
300 :
301 :
302 150 : void ivas_omasa_ana_fx(
303 : OMASA_ANA_HANDLE hOMasa, /* i/o: OMASA analysis handle */
304 : Word32 data_in_f_fx[][L_FRAME48k], /* i/o: Input / transport audio signals */
305 : Word16 *data_in_q,
306 : const Word16 input_frame, /* i : Input frame size */
307 : const Word16 nchan_transport, /* i : Number of transport channels */
308 : const Word16 nchan_ism /* i : Number of objects for parameter analysis */
309 : )
310 : {
311 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
312 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
313 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
314 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
315 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
316 : Word16 spreadCoherence_q, sorroundingCoherence_q, energyRatio_q;
317 :
318 : /* Estimate MASA parameters from the objects */
319 150 : ivas_omasa_param_est_ana_fx( hOMasa, data_in_f_fx, *data_in_q, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, &energyRatio_q, spreadCoherence_fx, &spreadCoherence_q, surroundingCoherence_fx, &sorroundingCoherence_q, input_frame, nchan_ism );
320 :
321 : /* Create MASA metadata buffer from the estimated values */
322 150 : ivas_create_masa_out_meta_fx( hOMasa->hMasaOut, hOMasa->sph_grid16, nchan_transport, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, Q31, Q31, Q31 );
323 :
324 : /* Downmix */
325 150 : ivas_omasa_dmx_fx( data_in_f_fx, data_in_q, input_frame, nchan_transport, nchan_ism, hOMasa->ism_azimuth_fx, hOMasa->ism_elevation_fx, hOMasa->prev_object_dm_gains_fx, hOMasa->interpolator_fx );
326 :
327 150 : return;
328 : }
329 :
330 :
331 : /*--------------------------------------------------------------------------*
332 : * Local functions
333 : *--------------------------------------------------------------------------*/
334 :
335 : /* Estimate MASA parameters from the objects */
336 :
337 :
338 150 : static void ivas_omasa_param_est_ana_fx(
339 : OMASA_ANA_HANDLE hOMasa,
340 : Word32 data_f_fx[][L_FRAME48k],
341 : Word16 data_f_q,
342 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
343 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
344 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
345 : Word16 *energyRatio_q,
346 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
347 : Word16 *spreadCoherence_q,
348 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
349 : Word16 *surroundingCoherence_q,
350 : const Word16 input_frame,
351 : const Word16 nchan_ism )
352 : {
353 : Word16 ts, i, d, j;
354 : Word16 num_freq_bins, num_freq_bands, index;
355 : Word16 l_ts;
356 :
357 : Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
358 : Word32 Chnl_RealBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
359 : Word16 Chnl_RealBuffer_q[MAX_NUM_OBJECTS];
360 : Word16 Chnl_ImagBuffer_q[MAX_NUM_OBJECTS];
361 : Word32 Chnl_ImagBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
362 : Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
363 : Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
364 : Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
365 : Word16 intensity_real_q[MASA_FREQUENCY_BANDS];
366 : Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
367 : Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
368 150 : Word16 diffuseness_q = 0;
369 150 : move16();
370 : Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
371 : Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS];
372 :
373 : Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
374 : Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
375 : Word32 norm_tmp_fx;
376 :
377 : Word32 dir_v_fx[DIRAC_NUM_DIMS] /*, L_tmp1, L_tmp2*/;
378 : Word16 dir_v_q /*, norm_tmp_q*/;
379 : Word16 band_m_idx, block_m_idx;
380 :
381 : Word16 mrange[2];
382 : Word16 brange[2];
383 :
384 150 : num_freq_bins = hOMasa->cldfbAnaEnc[0]->no_channels;
385 150 : move16();
386 150 : num_freq_bands = hOMasa->nbands;
387 150 : move16();
388 150 : l_ts = shr( input_frame, 4 );
389 :
390 : Word16 intensity_q;
391 : Word16 reference_power_q;
392 :
393 150 : set16_zero_fx( Chnl_RealBuffer_q, MAX_NUM_OBJECTS );
394 150 : set16_zero_fx( Chnl_ImagBuffer_q, MAX_NUM_OBJECTS );
395 :
396 : /* Compute ISM to FOA matrices */
397 750 : FOR( i = 0; i < nchan_ism; i++ )
398 : {
399 600 : hOMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31;
400 600 : move32();
401 600 : hOMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( Mpy_32_32( hOMasa->ism_azimuth_fx[i], 46603 /*32767/360*/ ) /*Q22+Q24-31=>Q15*/ ) ), getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ) ); // Q31
402 600 : move32();
403 600 : hOMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ), 16 ); // Q31
404 600 : move32();
405 600 : hOMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_azimuth_fx[i], 46603 /*2^24/360*/ ) ) ), getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ) ); // Q31
406 600 : move32();
407 : }
408 :
409 : /* do processing over all CLDFB time slots */
410 750 : FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
411 : {
412 600 : mrange[0] = hOMasa->block_grouping[block_m_idx];
413 600 : move16();
414 600 : mrange[1] = hOMasa->block_grouping[block_m_idx + 1];
415 600 : move16();
416 :
417 15000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
418 : {
419 14400 : hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
420 14400 : move32();
421 14400 : hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
422 14400 : move32();
423 14400 : hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
424 14400 : move32();
425 :
426 14400 : hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
427 14400 : move16();
428 14400 : hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
429 14400 : move16();
430 14400 : hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
431 14400 : move16();
432 : }
433 :
434 : /* Need to initialize renormalization_factors, and variables to be normalized */
435 :
436 600 : set_zero_fx( renormalization_factor_diff_fx, hOMasa->nbands );
437 600 : set16_fx( renormalization_factor_diff_e, 0, hOMasa->nbands );
438 600 : set_zero_fx( diffuseness_m_fx, hOMasa->nbands );
439 600 : set16_fx( diffuseness_e, 0, hOMasa->nbands );
440 600 : set_zero_fx( hOMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
441 600 : set16_fx( hOMasa->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
442 :
443 3000 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
444 : {
445 2400 : Word16 cr_q = MAX_16, ci_q = MAX_16, sf, c_e;
446 2400 : move16();
447 2400 : move16();
448 2400 : Word16 inp_q = data_f_q;
449 2400 : move16();
450 12000 : FOR( i = 0; i < nchan_ism; i++ )
451 : {
452 9600 : inp_q = data_f_q;
453 9600 : cldfbAnalysis_ts_fx_var_q( &( data_f_fx[i][i_mult( l_ts, ts )] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &inp_q );
454 :
455 9600 : cr_q = s_min( cr_q, L_norm_arr( Chnl_ImagBuffer_fx[i], l_ts ) );
456 9600 : ci_q = s_min( ci_q, L_norm_arr( Chnl_RealBuffer_fx[i], l_ts ) );
457 : }
458 2400 : sf = sub( s_min( cr_q, ci_q ), 4 );
459 12000 : FOR( i = 0; i < nchan_ism; i++ )
460 : {
461 9600 : scale_sig32( Chnl_RealBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
462 9600 : scale_sig32( Chnl_ImagBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
463 : }
464 2400 : inp_q = add( inp_q, sf );
465 2400 : c_e = sub( 31, inp_q );
466 :
467 : /* Compute channel-based energy for metadata processing */
468 60000 : FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
469 : {
470 57600 : brange[0] = hOMasa->band_grouping[band_m_idx];
471 57600 : move16();
472 57600 : brange[1] = hOMasa->band_grouping[band_m_idx + 1];
473 57600 : move16();
474 201600 : FOR( j = brange[0]; j < brange[1]; j++ )
475 : {
476 720000 : FOR( i = 0; i < nchan_ism; i++ )
477 : {
478 576000 : Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); // Q-> 2*inp_q - 31, e = 31 - (2*inp_q - 31) = 62 - 2*inp_q = 2*(31 - inp_q) = 2*c_e
479 576000 : hOMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->energy_fx[block_m_idx][band_m_idx], hOMasa->energy_e[block_m_idx][band_m_idx], temp, shl( c_e, 1 ), &hOMasa->energy_e[block_m_idx][band_m_idx] );
480 576000 : move32();
481 : }
482 : }
483 : }
484 :
485 : /* Compute FOA */
486 : /* W */
487 :
488 2400 : Copy32( Chnl_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); // inp_q
489 2400 : Copy32( Chnl_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); // inp_q
490 :
491 9600 : FOR( i = 1; i < nchan_ism; i++ )
492 : {
493 7200 : v_add_fixed_no_hdrm( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); // Q: Chnl_RealBuffer_q
494 7200 : v_add_fixed_no_hdrm( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); // Q: Chnl_ImagBuffer_q
495 : }
496 :
497 : /* Y */
498 :
499 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); // Q: Chnl_RealBuffer_q
500 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); // Q: Chnl_ImagBuffer_q
501 :
502 9600 : FOR( i = 1; i < nchan_ism; i++ )
503 : {
504 7200 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); // Q: Chnl_RealBuffer_q
505 7200 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); // Q: Chnl_ImagBuffer_q
506 : }
507 :
508 : /* Z */
509 :
510 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); // Q: Chnl_RealBuffer_q
511 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); // Q: Chnl_ImagBuffer_q
512 :
513 9600 : FOR( i = 1; i < nchan_ism; i++ )
514 : {
515 7200 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); // Q: Chnl_RealBuffer_q
516 7200 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); // Q: Chnl_ImagBuffer_q
517 : }
518 :
519 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); // Q: Chnl_RealBuffer_q
520 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); // Q: Chnl_ImagBuffer_q
521 :
522 9600 : FOR( i = 1; i < nchan_ism; i++ )
523 : {
524 7200 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); // Q: Chnl_RealBuffer_q
525 7200 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); // Q: Chnl_ImagBuffer_q
526 : }
527 2400 : computeIntensityVector_ana_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx, intensity_real_q, inp_q );
528 :
529 2400 : 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], 0, intensity_real_q ); /* Q direction_vector_fx = Q30*/
530 : /* Power estimation for diffuseness */
531 :
532 2400 : computeReferencePower_ana_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands, inp_q, &reference_power_q );
533 :
534 : /* Aligning intensity_real to a common Q-factor */
535 2400 : minimum_fx( intensity_real_q, num_freq_bands, &intensity_q );
536 :
537 : Word16 tmp;
538 60000 : FOR( i = 0; i < num_freq_bands; i++ )
539 : {
540 57600 : tmp = sub( intensity_q, intensity_real_q[i] );
541 57600 : intensity_real_fx[0][i] = L_shl( intensity_real_fx[0][i], tmp );
542 57600 : move32();
543 57600 : intensity_real_fx[1][i] = L_shl( intensity_real_fx[1][i], tmp );
544 57600 : move32();
545 57600 : intensity_real_fx[2][i] = L_shl( intensity_real_fx[2][i], tmp );
546 57600 : move32();
547 : }
548 :
549 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
550 2400 : hOMasa->index_buffer_intensity = add( ( hOMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
551 2400 : move16();
552 2400 : index = hOMasa->index_buffer_intensity;
553 2400 : move16();
554 :
555 9600 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
556 : {
557 : /* only real part needed */
558 7200 : Copy32( intensity_real_fx[i], &( hOMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); // intensity_q
559 : }
560 2400 : hOMasa->buffer_intensity_real_q[index - 1] = intensity_q;
561 2400 : move16();
562 2400 : Copy32( reference_power_fx[ts], &( hOMasa->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands );
563 2400 : hOMasa->buffer_energy_q[index - 1] = reference_power_q;
564 2400 : move16();
565 :
566 2400 : 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, &diffuseness_q ); // diffuseness_q=Q30
567 :
568 60000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
569 : {
570 57600 : norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*reference_power_q*/
571 57600 : 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], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] );
572 57600 : move32();
573 57600 : 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], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] );
574 57600 : move32();
575 57600 : 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], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] );
576 57600 : move32();
577 :
578 57600 : diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), 1 ), sub( 31, reference_power_q ), &diffuseness_e[band_m_idx] );
579 57600 : move32();
580 57600 : 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( 31, reference_power_q ), &renormalization_factor_diff_e[band_m_idx] );
581 57600 : move32();
582 : }
583 : }
584 :
585 15000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
586 : {
587 14400 : Word16 max_e = MIN_16;
588 14400 : move16();
589 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
590 : {
591 43200 : max_e = s_max( max_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] );
592 : }
593 14400 : max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/
594 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
595 : {
596 43200 : dir_v_fx[d] = L_shr( hOMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( max_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) );
597 43200 : move32();
598 : }
599 14400 : dir_v_q = sub( 31, max_e );
600 :
601 14400 : ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, dir_v_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] );
602 : }
603 :
604 : /* Determine energy ratios */
605 15000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
606 : {
607 : Word16 diffuseness_m_e;
608 14400 : IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) )
609 : {
610 14400 : diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e );
611 14400 : move32();
612 14400 : diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
613 14400 : diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31
614 14400 : move32();
615 : }
616 : ELSE
617 : {
618 0 : diffuseness_m_fx[band_m_idx] = 0;
619 0 : move32();
620 : }
621 14400 : energyRatio_fx[block_m_idx][band_m_idx] = L_sub( ONE_IN_Q31, diffuseness_m_fx[band_m_idx] );
622 14400 : move32();
623 : }
624 :
625 : /* Set coherences to zero, as this mode is used at lowest bit rates where the coherences are not transmitted */
626 15000 : FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
627 : {
628 14400 : spreadCoherence_fx[block_m_idx][band_m_idx] = 0;
629 14400 : move32();
630 14400 : surroundingCoherence_fx[block_m_idx][band_m_idx] = 0;
631 14400 : move32();
632 : }
633 : }
634 150 : *energyRatio_q = Q31;
635 150 : *spreadCoherence_q = Q31;
636 150 : *surroundingCoherence_q = Q31;
637 150 : move16();
638 150 : move16();
639 150 : move16();
640 150 : return;
641 : }
642 :
643 :
644 : /* Compute downmix */
645 150 : static void ivas_omasa_dmx_fx(
646 : Word32 data_in_f_fx[][L_FRAME48k],
647 : Word16 *data_in_q,
648 : const Word16 input_frame,
649 : const Word16 nchan_transport,
650 : const Word16 nchan_ism,
651 : const Word32 ism_azimuth_fx[MAX_NUM_OBJECTS],
652 : const Word32 ism_elevation_fx[MAX_NUM_OBJECTS],
653 : Word32 prev_gains_fx[][MASA_MAX_TRANSPORT_CHANNELS],
654 : const Word16 interpolator_fx[L_FRAME48k] )
655 : {
656 : Word16 i, j, k, l, tmp1, tmp2;
657 :
658 : Word16 azimuth_fx, elevation_fx;
659 : Word16 gains_fx[MASA_MAX_TRANSPORT_CHANNELS];
660 : Word16 g1_fx, g2_fx, scale;
661 : Word32 data_out_f_fx[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k], L_tmp;
662 : Word16 max_e, tmp_e;
663 : Word16 in_e[960];
664 : Word16 data_e[4];
665 :
666 450 : FOR( i = 0; i < nchan_transport; i++ )
667 : {
668 300 : set_zero_fx( data_out_f_fx[i], input_frame );
669 : }
670 150 : set16_fx( data_e, 0, 4 );
671 150 : set16_fx( in_e, 0, 960 );
672 :
673 750 : FOR( i = 0; i < nchan_ism; i++ )
674 : {
675 :
676 600 : azimuth_fx = extract_l( L_shr( ism_azimuth_fx[i], Q22 ) ); // Q0
677 600 : elevation_fx = extract_l( L_shr( ism_elevation_fx[i], Q22 ) ); // Q0
678 :
679 600 : ivas_ism_get_stereo_gains_fx( azimuth_fx, elevation_fx, &gains_fx[0], &gains_fx[1] );
680 :
681 : /* Downmix using the panning gains */
682 1800 : FOR( j = 0; j < nchan_transport; j++ )
683 : {
684 1200 : test();
685 1200 : IF( abs_s( gains_fx[j] ) > 0 || L_abs( prev_gains_fx[i][j] ) > 0 )
686 : {
687 1060944 : FOR( k = 0; k < input_frame; k++ )
688 : {
689 :
690 1059840 : g1_fx = interpolator_fx[k]; // Q15
691 1059840 : move16();
692 1059840 : scale = BASOP_Util_Add_MantExp( 16384, 1, negate( g1_fx ), 0, &g2_fx );
693 :
694 1059840 : tmp1 = mult( g1_fx, gains_fx[j] );
695 1059840 : tmp2 = mult( g2_fx, (Word16) L_shr( prev_gains_fx[i][j], 16 ) ); // Q: ( ( ( 15 - scale ) + ( Q31 - Q16 ) ) - Q15 ) -> ( 15 - scale )
696 1059840 : scale = BASOP_Util_Add_MantExp( tmp1, 0, tmp2, scale, &tmp1 );
697 :
698 1059840 : L_tmp = data_in_f_fx[i][k]; // data_in_q
699 1059840 : move32();
700 1059840 : tmp_e = sub( 31, *data_in_q );
701 1059840 : move16();
702 :
703 1059840 : L_tmp = Mpy_32_16_1( L_tmp, tmp1 );
704 1059840 : scale = add( scale, tmp_e );
705 :
706 1059840 : data_out_f_fx[j][k] = BASOP_Util_Add_Mant32Exp( data_out_f_fx[j][k], data_e[j], L_tmp, scale, &in_e[k] );
707 1059840 : move32();
708 : }
709 1104 : max_e = in_e[0];
710 1104 : move16();
711 1059840 : FOR( l = 1; l < L_FRAME48k; l++ )
712 : {
713 1058736 : IF( LT_16( max_e, in_e[l] ) )
714 : {
715 2363 : max_e = in_e[l];
716 2363 : move16();
717 : }
718 : }
719 :
720 1060944 : FOR( l = 0; l < L_FRAME48k; l++ )
721 : {
722 1059840 : data_out_f_fx[j][l] = L_shr( data_out_f_fx[j][l], sub( max_e, in_e[l] ) ); // exponent: max_e, Q: ( 15 - max_e )
723 1059840 : move32();
724 : }
725 1104 : data_e[j] = max_e;
726 1104 : move16();
727 : }
728 :
729 1200 : prev_gains_fx[i][j] = L_deposit_h( gains_fx[j] ); // Q31
730 1200 : move32();
731 : }
732 : }
733 :
734 150 : max_e = data_e[0];
735 150 : move16();
736 300 : FOR( i = 1; i < nchan_transport; i++ )
737 : {
738 150 : if ( LT_16( max_e, data_e[i] ) )
739 : {
740 50 : max_e = data_e[i];
741 50 : move16();
742 : }
743 : }
744 :
745 450 : FOR( i = 0; i < nchan_transport; i++ )
746 : {
747 288300 : FOR( j = 0; j < input_frame; j++ )
748 : {
749 288000 : data_out_f_fx[i][j] = L_shr( data_out_f_fx[i][j], sub( max_e, data_e[i] ) ); // exponent: max_e, Q: ( 15 - max_e )
750 288000 : move32();
751 : }
752 : }
753 :
754 450 : FOR( i = 0; i < nchan_transport; i++ )
755 : {
756 300 : Copy32( data_out_f_fx[i], data_in_f_fx[i], input_frame );
757 300 : *data_in_q = sub( 31, max_e );
758 300 : move16();
759 : }
760 :
761 150 : return;
762 : }
763 :
764 : /* Compute downmix */
765 :
766 :
767 : /*--------------------------------------------------------------------------*
768 : * computeIntensityVector_ana()
769 : *
770 : *
771 : *--------------------------------------------------------------------------*/
772 :
773 9600 : void computeIntensityVector_ana_fx(
774 : const Word16 *band_grouping, /* i : Band grouping for estimation */
775 : Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal Qx */
776 : Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input sig Qx */
777 : const Word16 num_frequency_bands, /* i : Number of frequency bands */
778 : Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS], /* o : Intensity */
779 : Word16 q_intensity_real[MASA_FREQUENCY_BANDS],
780 : Word16 inp_q )
781 : {
782 : /* Reminder
783 : * X = a + ib; Y = c + id
784 : * X*Y = ac - bd + i(ad +bc)
785 : */
786 : Word16 i, j;
787 : Word32 real, img;
788 : Word16 brange[2];
789 9600 : Word16 shift_value = add( shl( inp_q, 1 ), 1 );
790 : Word16 tmp_norm;
791 240000 : FOR( i = 0; i < num_frequency_bands; i++ )
792 : {
793 230400 : brange[0] = band_grouping[i];
794 230400 : move16();
795 230400 : brange[1] = band_grouping[i + 1];
796 230400 : move16();
797 230400 : Word16 num_bins = sub( brange[1], brange[0] );
798 230400 : Word16 gb = find_guarded_bits_fx( num_bins );
799 : Word16 norm;
800 :
801 230400 : Word64 tmp_1 = 0, tmp_2 = 0, tmp_3 = 0;
802 230400 : move64();
803 230400 : move64();
804 230400 : move64();
805 :
806 806400 : FOR( j = brange[0]; j < brange[1]; j++ )
807 : {
808 576000 : real = Cldfb_RealBuffer[0][j];
809 576000 : move32();
810 576000 : img = Cldfb_ImagBuffer[0][j];
811 576000 : move32();
812 : Word64 t1, t2, t3;
813 576000 : t1 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[3][j], real ), Cldfb_ImagBuffer[3][j], img ); /* 2 * q_cldfb + 1 */
814 576000 : t2 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[1][j], real ), Cldfb_ImagBuffer[1][j], img ); /* 2 * q_cldfb + 1 */
815 576000 : t3 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[2][j], real ), Cldfb_ImagBuffer[2][j], img ); /* 2 * q_cldfb + 1 */
816 576000 : t1 = W_shr( t1, gb );
817 576000 : t2 = W_shr( t2, gb );
818 576000 : t3 = W_shr( t3, gb );
819 : /* Intensity is XYZ order, audio is WYZX order. */
820 576000 : tmp_1 = W_add( tmp_1, t1 ); /* 2 * q_cldfb + 1 */
821 576000 : tmp_2 = W_add( tmp_2, t2 ); /* 2 * q_cldfb + 1 */
822 576000 : tmp_3 = W_add( tmp_3, t3 ); /* 2 * q_cldfb + 1 */
823 : }
824 230400 : norm = 63;
825 230400 : move16();
826 230400 : IF( tmp_1 != 0 )
827 : {
828 230400 : tmp_norm = W_norm( tmp_1 );
829 230400 : norm = s_min( norm, tmp_norm );
830 : }
831 230400 : IF( tmp_2 != 0 )
832 : {
833 229632 : tmp_norm = W_norm( tmp_2 );
834 229632 : norm = s_min( norm, tmp_norm );
835 : }
836 230400 : IF( tmp_3 != 0 )
837 : {
838 172416 : tmp_norm = W_norm( tmp_3 );
839 172416 : norm = s_min( norm, tmp_norm );
840 : }
841 230400 : norm = sub( norm, 32 );
842 230400 : intensity_real[0][i] = W_shl_sat_l( tmp_1, norm ); // shift_value - (gb - norm)
843 230400 : move32();
844 230400 : intensity_real[1][i] = W_shl_sat_l( tmp_2, norm ); // shift_value - (gb - norm)
845 230400 : move32();
846 230400 : intensity_real[2][i] = W_shl_sat_l( tmp_3, norm ); // shift_value - (gb - norm)
847 230400 : q_intensity_real[i] = sub( shift_value, sub( gb, norm ) );
848 230400 : move16();
849 : }
850 :
851 9600 : return;
852 : }
853 : /*--------------------------------------------------------------------------*
854 : * computeIntensityVector_ana()
855 : *
856 : *
857 : *--------------------------------------------------------------------------*/
858 :
859 :
860 : /*--------------------------------------------------------------------------*
861 : * computeReferencePower_ana()
862 : *
863 : *
864 : *--------------------------------------------------------------------------*/
865 :
866 7200 : void computeReferencePower_ana_fx(
867 : const Word16 *band_grouping, /* i : Band grouping for estimation */
868 : Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal input_q */
869 : Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal input_q */
870 : Word32 *reference_power, /* o : Estimated power */
871 : const Word16 num_freq_bands, /* i : Number of frequency bands */
872 : const Word16 input_q, /* i : Q-factor Real and Imag part of input signal */
873 : Word16 *reference_power_q /* o : Q-factor of the estimated power */
874 : )
875 : {
876 : Word16 brange[2];
877 : Word16 ch_idx, i, j, s;
878 : Word64 reference_power64[MASA_FREQUENCY_BANDS];
879 180000 : FOR( i = 0; i < num_freq_bands; i++ )
880 : {
881 172800 : brange[0] = band_grouping[i];
882 172800 : move16();
883 172800 : brange[1] = band_grouping[i + 1];
884 172800 : move16();
885 172800 : reference_power64[i] = 0;
886 172800 : move64();
887 :
888 864000 : FOR( ch_idx = 0; ch_idx < FOA_CHANNELS; ch_idx++ )
889 : {
890 : /* abs()^2 */
891 2419200 : FOR( j = brange[0]; j < brange[1]; j++ )
892 : {
893 1728000 : reference_power64[i] = W_add( 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] ), reference_power64[i] ); // 2 * input_q + 1
894 1728000 : move64();
895 : }
896 : }
897 : }
898 :
899 7200 : s = sub( W_norm_arr( reference_power64, num_freq_bands ), 1 );
900 180000 : FOR( i = 0; i < num_freq_bands; i++ )
901 : {
902 172800 : reference_power[i] = W_extract_h( W_shl( reference_power64[i], s ) ); // 2 * input_q + 1 + s - 32
903 172800 : move32();
904 : }
905 7200 : *reference_power_q = sub( add( shl( input_q, 1 ), s ), 30 ); /* Bypassing the v_multc ,so output q = 2 * input_q + s - 30 */
906 7200 : move16();
907 :
908 7200 : return;
909 : }
|