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 <math.h>
34 : #include <stdlib.h>
35 : #include <stdio.h>
36 : #include "ivas_cnst.h"
37 : #include "options.h"
38 : #include "ivas_prot_rend_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 : #include "ivas_prot_fx.h"
44 : #include "ivas_rom_com_fx.h"
45 :
46 : /*-------------------------------------------------------------------------
47 : * Local constants
48 : *------------------------------------------------------------------------*/
49 :
50 : #define NEAR_HORIZONTAL_PLANE_ELEVATION 17.5f
51 : #define NEAR_HORIZONTAL_PLANE_ELEVATION_FX 73400320 /*Q22*/
52 : #define VERTICAL_ENERGY_RATIO_OFFSET 0.15f
53 : #define VERTICAL_ENERGY_RATIO_OFFSET_FX 4915 /*Q15*/
54 :
55 :
56 : /*-------------------------------------------------------------------------
57 : * Local function prototypes
58 : *------------------------------------------------------------------------*/
59 :
60 : /* Structure for covariance matrix */
61 : typedef struct
62 : {
63 : float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
64 : float xi[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
65 : Word32 xr_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
66 : Word32 xi_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
67 : Word16 xr_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xr_fx*/
68 : Word16 xi_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xi_fx*/
69 : } CovarianceMatrix;
70 : void ivas_mcmasa_param_est_ana_fx(
71 : MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */
72 : Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */
73 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation Q22 */
74 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth Q22 */
75 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio Q31 */
76 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence Q31 */
77 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence Q31 */
78 : Word16 q_data,
79 : const Word16 input_frame, /* i : Input frame size */
80 : const Word16 nchan_inp /* i : Number of input channels */
81 : );
82 :
83 :
84 : static void computeVerticalDiffuseness_fx(
85 : Word32 **buffer_intensity, /* i : Intensity vectors */
86 : const Word32 *buffer_energy, /* i : Energy */
87 : const Word16 num_freq_bands, /* i : Number of frequency bands */
88 : Word32 *diffuseness, /* o : Estimated diffuseness Q31 */
89 : Word16 *buffer_intensity_q,
90 : Word16 *buffer_energy_q );
91 : static void compute_cov_mtx_fx(
92 : Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */
93 : Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */
94 : const Word16 freq, /* i : Freq to process */
95 : const Word16 N, /* i : Number of channels */
96 : CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */
97 : Word16 inp_exp /* i : Stores exponent for sr and si */
98 : );
99 : static void computeEvenLayout_fx(
100 : const Word32 *ls_azimuth, /* i: Q22 */
101 : Word32 *ls_azimuth_even, /* o: Q22 */
102 : const Word16 numChannels );
103 :
104 : static void ivas_mcmasa_dmx_fx(
105 : MCMASA_ANA_HANDLE hMcMasa,
106 : Word32 data_f_fx[][L_FRAME48k],
107 : Word16 data_e,
108 : const Word16 input_frame,
109 : const Word16 nchan_transport,
110 : const Word16 nchan_inp );
111 :
112 :
113 : /*--------------------------------------------------------------------------*
114 : * ivas_mcmasa_ana_open()
115 : *
116 : *
117 : *--------------------------------------------------------------------------*/
118 :
119 1 : ivas_error ivas_mcmasa_ana_open(
120 : MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */
121 : const AUDIO_CONFIG inConfig, /* i : Input config */
122 : Word32 input_Fs /* i : Sampling frequency */
123 : )
124 : {
125 : Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS];
126 : Word32 ls_elevation_fx[MCMASA_MAX_ANA_CHANS];
127 : Word32 ls_azimuth_even_fx[MCMASA_MAX_ANA_CHANS];
128 : Word32 left_min_fx, right_min_fx, azi_diff_fx;
129 : Word16 i, j;
130 : MCMASA_ANA_HANDLE hMcMasa;
131 : Word16 nchan_inp;
132 : Word16 numAnalysisChannels;
133 : Word16 maxBin, input_frame;
134 : ivas_error error;
135 :
136 1 : error = IVAS_ERR_OK;
137 :
138 1 : IF( ( hMcMasa = (MCMASA_ANA_HANDLE) malloc( sizeof( MCMASA_ANA_DATA ) ) ) == NULL )
139 : {
140 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
141 : }
142 :
143 1 : IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1 ) )
144 : {
145 0 : nchan_inp = 6;
146 0 : move16();
147 0 : Copy32( ls_azimuth_CICP6_fx, ls_azimuth_fx, 5 ); /* nchan_inp - 1 */
148 0 : Copy32( ls_elevation_CICP6_fx, ls_elevation_fx, 5 ); /* nchan_inp - 1 */
149 0 : hMcMasa->numHorizontalChannels = 5;
150 0 : move16();
151 0 : hMcMasa->isHorizontalSetup = 1;
152 0 : move16();
153 : }
154 1 : ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
155 : {
156 0 : nchan_inp = 8;
157 0 : move16();
158 0 : Copy32( ls_azimuth_CICP12_fx, ls_azimuth_fx, 7 ); /* nchan_inp - 1 */
159 0 : Copy32( ls_elevation_CICP12_fx, ls_elevation_fx, 7 ); /* nchan_inp - 1 */
160 0 : hMcMasa->numHorizontalChannels = 7;
161 0 : move16();
162 0 : hMcMasa->isHorizontalSetup = 1;
163 0 : move16();
164 : }
165 1 : ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1_2 ) )
166 : {
167 0 : nchan_inp = 8;
168 0 : move16();
169 0 : Copy32( ls_azimuth_CICP14_fx, ls_azimuth_fx, 7 ); /* nchan_inp - 1 */
170 0 : Copy32( ls_elevation_CICP14_fx, ls_elevation_fx, 7 ); /* nchan_inp - 1 */
171 0 : hMcMasa->numHorizontalChannels = 5;
172 0 : move16();
173 0 : hMcMasa->isHorizontalSetup = 0;
174 0 : move16();
175 : }
176 1 : ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1_4 ) )
177 : {
178 0 : nchan_inp = 10;
179 0 : Copy32( ls_azimuth_CICP16_fx, ls_azimuth_fx, 9 ); /* nchan_inp - 1 */
180 0 : Copy32( ls_elevation_CICP16_fx, ls_elevation_fx, 9 ); /* nchan_inp - 1 */
181 0 : hMcMasa->numHorizontalChannels = 5;
182 0 : move16();
183 0 : hMcMasa->isHorizontalSetup = 0;
184 0 : move16();
185 : }
186 : ELSE
187 : {
188 1 : nchan_inp = 12;
189 1 : move16();
190 1 : Copy32( ls_azimuth_CICP19_fx, ls_azimuth_fx, 11 ); /* nchan_inp - 1 */
191 1 : Copy32( ls_elevation_CICP19_fx, ls_elevation_fx, 11 ); /* nchan_inp - 1 */
192 1 : hMcMasa->numHorizontalChannels = 7;
193 1 : move16();
194 1 : hMcMasa->isHorizontalSetup = 0;
195 1 : move16();
196 : }
197 :
198 1 : numAnalysisChannels = sub( nchan_inp, 1 );
199 :
200 : /* Determine the number of bands */
201 1 : hMcMasa->nbands = MASA_FREQUENCY_BANDS;
202 1 : move16();
203 : /* Determine band grouping */
204 1 : Copy( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
205 :
206 1 : maxBin = extract_l( W_extract_h( W_add( W_mult_32_32( input_Fs, INV_CLDFB_BANDWIDTH_Q31 ), ONE_IN_Q31 /*0.5f in Q32*/ ) ) ); // Q0
207 24 : FOR( i = 1; i < add( hMcMasa->nbands, 1 ); i++ )
208 : {
209 24 : IF( GE_16( hMcMasa->band_grouping[i], maxBin ) )
210 : {
211 1 : hMcMasa->band_grouping[i] = maxBin;
212 1 : move16();
213 1 : hMcMasa->nbands = i;
214 1 : move16();
215 1 : break;
216 : }
217 : }
218 :
219 : /* Determine block grouping */
220 1 : Copy( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
221 :
222 : /* open/initialize CLDFB */
223 1 : hMcMasa->num_Cldfb_instances = numAnalysisChannels;
224 1 : move16();
225 12 : FOR( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
226 : {
227 11 : IF( NE_32( ( error = openCldfb_ivas_fx( &( hMcMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
228 : {
229 0 : return error;
230 : }
231 : }
232 :
233 : /* intensity 3-dim */
234 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
235 : {
236 3 : IF( ( hMcMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL )
237 : {
238 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
239 : }
240 :
241 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
242 : {
243 12 : IF( ( hMcMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
244 : {
245 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
246 : }
247 12 : set_zero_fx( hMcMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS );
248 : }
249 3 : IF( ( hMcMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL )
250 : {
251 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
252 : }
253 :
254 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
255 : {
256 12 : IF( ( hMcMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL )
257 : {
258 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
259 : }
260 12 : set16_fx( hMcMasa->direction_vector_e[i][j], 0, MASA_FREQUENCY_BANDS );
261 : }
262 : }
263 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
264 : {
265 99 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
266 : {
267 96 : IF( ( hMcMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
268 : {
269 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
270 : }
271 96 : set_zero_fx( hMcMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS );
272 : }
273 : }
274 1 : set16_fx( hMcMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF );
275 :
276 33 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
277 : {
278 32 : IF( ( hMcMasa->buffer_intensity_real_vert_fx[j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
279 : {
280 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
281 : }
282 32 : set_zero_fx( hMcMasa->buffer_intensity_real_vert_fx[j], MASA_FREQUENCY_BANDS );
283 : }
284 :
285 1 : set16_fx( hMcMasa->buffer_intensity_real_vert_q, 31, DIRAC_NO_COL_AVG_DIFF );
286 1 : set_zero_fx( hMcMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
287 1 : set16_fx( hMcMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF );
288 :
289 1 : computeEvenLayout_fx( ls_azimuth_fx, ls_azimuth_even_fx, hMcMasa->numHorizontalChannels );
290 :
291 1 : IF( !hMcMasa->isHorizontalSetup )
292 : {
293 1 : computeEvenLayout_fx( &ls_azimuth_fx[hMcMasa->numHorizontalChannels], &ls_azimuth_even_fx[hMcMasa->numHorizontalChannels], sub( numAnalysisChannels, hMcMasa->numHorizontalChannels ) );
294 : }
295 :
296 12 : FOR( i = 0; i < numAnalysisChannels; i++ )
297 : {
298 11 : hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; // Q31
299 11 : move32();
300 11 : hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31
301 11 : move32();
302 11 : hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
303 11 : move32();
304 11 : hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31
305 11 : move32();
306 :
307 11 : hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; // Q31
308 11 : move32();
309 11 : hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
310 11 : move32();
311 11 : hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; // Q31
312 11 : move32();
313 11 : hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
314 11 : move32();
315 : }
316 :
317 1 : Copy32( ls_azimuth_fx, hMcMasa->ls_azimuth_fx, numAnalysisChannels );
318 :
319 8 : FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
320 : {
321 7 : left_min_fx = 360 << 22; // Q22
322 7 : move32();
323 7 : right_min_fx = -( 360 << 22 ); // Q22
324 7 : move32();
325 :
326 56 : FOR( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
327 : {
328 49 : azi_diff_fx = L_sub( ls_azimuth_fx[j], ls_azimuth_fx[i] ); // Q22
329 :
330 49 : IF( GT_32( azi_diff_fx, ( 180 << 22 ) ) )
331 : {
332 3 : azi_diff_fx = L_sub( azi_diff_fx, 360 << 22 ); // Q22
333 : }
334 46 : ELSE IF( LT_32( azi_diff_fx, -( 180 << 22 ) ) )
335 : {
336 3 : azi_diff_fx = L_add( azi_diff_fx, 360 << 22 ); // Q22
337 : }
338 49 : test();
339 49 : IF( LT_32( azi_diff_fx, left_min_fx ) && GT_32( azi_diff_fx, 0 ) )
340 : {
341 12 : hMcMasa->leftNearest[i] = j;
342 12 : move16();
343 12 : left_min_fx = azi_diff_fx; // Q22
344 12 : move32();
345 : }
346 49 : test();
347 49 : IF( GT_32( azi_diff_fx, right_min_fx ) && LT_32( azi_diff_fx, 0 ) )
348 : {
349 11 : hMcMasa->rightNearest[i] = j;
350 11 : move16();
351 11 : right_min_fx = azi_diff_fx; // Q22
352 11 : move32();
353 : }
354 : }
355 : }
356 :
357 1 : hMcMasa->prevMultiChEne_fx = 0;
358 1 : move32();
359 1 : hMcMasa->prevDownmixEne_fx = 0;
360 1 : move32();
361 1 : hMcMasa->prevMultiChEne_e = 0;
362 1 : move16();
363 1 : hMcMasa->prevDownmixEne_e = 0;
364 1 : move16();
365 1 : hMcMasa->prevEQ_e = 1;
366 1 : move16();
367 1 : hMcMasa->prevEQ_fx = 1073741824;
368 1 : move32();
369 1 : input_frame = (Word16) Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 );
370 1 : move16();
371 961 : FOR( i = 0; i < input_frame; i++ )
372 : {
373 960 : hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); // Q15
374 960 : move16();
375 : }
376 :
377 1 : hMcMasa->index_buffer_intensity = 0;
378 1 : move16();
379 :
380 1 : IF( ( hMcMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
381 : {
382 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
383 : }
384 :
385 1 : IF( ( hMcMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
386 : {
387 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
388 : }
389 1 : generate_gridEq_fx( hMcMasa->sph_grid16 );
390 :
391 1 : ( *hMcMasaPtr ) = hMcMasa;
392 :
393 1 : return error;
394 : }
395 :
396 :
397 : /*--------------------------------------------------------------------------*
398 : * ivas_mcmasa_ana_close()
399 : *
400 : *
401 : *--------------------------------------------------------------------------*/
402 :
403 666 : void ivas_mcmasa_ana_close(
404 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
405 : )
406 : {
407 : Word16 i, j;
408 :
409 666 : test();
410 666 : IF( hMcMasa == NULL || *hMcMasa == NULL )
411 : {
412 665 : return;
413 : }
414 :
415 12 : FOR( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
416 : {
417 11 : deleteCldfb_ivas_fx( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
418 : }
419 :
420 : /* intensity 3-dim */
421 4 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
422 : {
423 15 : FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
424 : {
425 12 : free( ( *hMcMasa )->direction_vector_m_fx[i][j] );
426 12 : ( *hMcMasa )->direction_vector_m_fx[i][j] = NULL;
427 : }
428 :
429 99 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
430 : {
431 96 : free( ( *hMcMasa )->buffer_intensity_real_fx[i][j] );
432 96 : ( *hMcMasa )->buffer_intensity_real_fx[i][j] = NULL;
433 : }
434 :
435 3 : free( ( *hMcMasa )->direction_vector_m_fx[i] );
436 3 : ( *hMcMasa )->direction_vector_m_fx[i] = NULL;
437 : }
438 :
439 33 : FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
440 : {
441 32 : free( ( *hMcMasa )->buffer_intensity_real_vert_fx[j] );
442 32 : ( *hMcMasa )->buffer_intensity_real_vert_fx[j] = NULL;
443 : }
444 :
445 1 : free( ( *hMcMasa )->hMasaOut );
446 1 : ( *hMcMasa )->hMasaOut = NULL;
447 1 : free( ( *hMcMasa )->sph_grid16 );
448 1 : ( *hMcMasa )->sph_grid16 = NULL;
449 :
450 1 : free( ( *hMcMasa ) );
451 1 : ( *hMcMasa ) = NULL;
452 :
453 1 : return;
454 : }
455 :
456 :
457 : /*--------------------------------------------------------------------------*
458 : * ivas_mcmasa_ana()
459 : *
460 : * Multichannel MASA analysis
461 : *--------------------------------------------------------------------------*/
462 :
463 150 : void ivas_mcmasa_ana_fx(
464 : MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */
465 : Word32 data[][L_FRAME48k], /* i/o: Input / transport audio signals */
466 : Word16 q_data,
467 : const Word16 input_frame, /* i : Input frame size */
468 : const Word16 nchan_transport, /* i : Number of transport channels */
469 : const Word16 nchan_inp /* i : Number of input channels */
470 : )
471 : {
472 : Word16 i;
473 :
474 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
475 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
476 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
477 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
478 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
479 : /* Sum center and LFE, move surround channels */
480 150 : v_add_32( data[2], data[3], data[2], input_frame );
481 1350 : FOR( i = 4; i < nchan_inp; i++ )
482 : {
483 1200 : Copy32( data[i], data[i - 1], input_frame );
484 : }
485 :
486 : /* Analysis */
487 150 : ivas_mcmasa_param_est_ana_fx( hMcMasa, data, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, q_data, input_frame, nchan_inp );
488 :
489 : /* Create MASA metadata buffer from the estimated values */
490 150 : ivas_create_masa_out_meta_fx( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, Q31, Q31, Q31 );
491 :
492 : /* Downmix */
493 :
494 150 : ivas_mcmasa_dmx_fx( hMcMasa, data, sub( 31, q_data ), input_frame, nchan_transport, nchan_inp );
495 :
496 :
497 150 : return;
498 : }
499 :
500 :
501 : /*--------------------------------------------------------------------------*
502 : * Local functions
503 : *--------------------------------------------------------------------------*/
504 :
505 : /* Estimate metadata parameters for McMASA */
506 150 : void ivas_mcmasa_param_est_ana_fx(
507 : MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */
508 : Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */
509 : Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation Q22 */
510 : Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth Q22 */
511 : Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio Q31 */
512 : Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence Q31 */
513 : Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence Q31 */
514 : Word16 q_data,
515 : const Word16 input_frame, /* i : Input frame size */
516 : const Word16 nchan_inp /* i : Number of input channels */
517 : )
518 : {
519 : Word16 cohPanCoh_e;
520 : Word16 tempLsEnergyRelation_e;
521 : Word16 q_vdv[MASA_FREQUENCY_BANDS];
522 : Word16 out_exp[MASA_FREQUENCY_BANDS];
523 : Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
524 : Word16 reference_power_q;
525 : Word32 dir_v_fx[DIRAC_NUM_DIMS];
526 : Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
527 : Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
528 : Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
529 : Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
530 : Word32 FoaEven_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
531 : Word32 FoaEven_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
532 : Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
533 : Word16 intensity_real_q[MASA_FREQUENCY_BANDS];
534 : Word32 intensity_even_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
535 : Word16 intensity_even_real_q[MASA_FREQUENCY_BANDS];
536 : Word16 intensity_q, intensity_even_q;
537 : Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
538 : Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
539 : Word32 vertical_diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
540 : Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS];
541 : Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
542 : Word32 coherentEnergyRatio_fx[MASA_FREQUENCY_BANDS];
543 : Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
544 : Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
545 : Word32 norm_tmp_fx;
546 : Word32 absCOVls_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
547 : Word16 absCOVls_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
548 : Word32 lsEnergy_fx[MCMASA_MAX_ANA_CHANS];
549 : Word16 lsEnergy_e[MCMASA_MAX_ANA_CHANS];
550 : Word32 lsEnergySum_fx, maxEne_fx;
551 150 : Word16 lsEnergySum_e = 0;
552 150 : move16();
553 : Word16 maxEne_e;
554 : Word32 angleDist_fx, minAngleDist_fx;
555 : Word32 currentAzi_fx;
556 : Word32 lsEnergyRelation_fx;
557 : Word16 lsEnergyRelation_e;
558 : Word32 tempLsEnergyRelation_fx;
559 : Word32 stereoness_fx, cohwideness_fx, spreadCoh_fx;
560 : Word32 stereoRatio_fx, cohPanRatio_fx;
561 : Word16 stereoness_e;
562 : Word32 stereoCoh_fx, cohPanCoh_fx, cohRatio_fx;
563 : Word32 surrCoh_fx, tempCoh_fx, tempCoh2_fx;
564 : Word16 surrCoh_e;
565 : Word16 stereoCoh_e;
566 : Word16 tempCoh_e;
567 : Word16 tempCoh2_e;
568 : Word16 ts, i, j, d;
569 : Word16 num_freq_bins, num_freq_bands, index;
570 : Word16 l_ts;
571 : Word16 band_m_idx, block_m_idx;
572 : Word16 mrange[2], brange[2];
573 : CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
574 : Word16 loudestCh;
575 : Word16 i1, i2, i3;
576 : Word16 numAnalysisChannels;
577 : Word16 spreadCoh_e;
578 : Word64 W_temp;
579 : Word32 temp;
580 : Word16 temp_e;
581 150 : Word16 sf, scaled_data_q, s, shift = 31;
582 150 : move16();
583 150 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
584 150 : move16();
585 150 : num_freq_bands = hMcMasa->nbands;
586 150 : move16();
587 150 : l_ts = shr( input_frame, CLDFB_NO_COL_MAX_LOG2 );
588 150 : numAnalysisChannels = sub( nchan_inp, 1 );
589 :
590 150 : set16_fx( q_vdv, 31, MASA_FREQUENCY_BANDS );
591 150 : set16_fx( out_exp, 30, MASA_FREQUENCY_BANDS );
592 :
593 1800 : FOR( i = 0; i < numAnalysisChannels; i++ )
594 : {
595 1650 : shift = s_min( shift, L_norm_arr( data_fx[i], input_frame ) );
596 : }
597 150 : shift = sub( shift, find_guarded_bits_fx( l_ts ) );
598 1800 : FOR( i = 0; i < numAnalysisChannels; i++ )
599 : {
600 1650 : scale_sig32( data_fx[i], input_frame, shift );
601 : }
602 150 : scaled_data_q = add( q_data, shift );
603 :
604 : /* do processing over all CLDFB time slots */
605 750 : FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
606 : {
607 600 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
608 600 : move16();
609 600 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
610 600 : move16();
611 :
612 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
613 : {
614 14400 : hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
615 14400 : move16();
616 14400 : hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
617 14400 : move16();
618 14400 : hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
619 14400 : move16();
620 14400 : hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
621 14400 : move16();
622 14400 : hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
623 14400 : move16();
624 14400 : hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
625 14400 : move16();
626 : }
627 :
628 : /* Need to initialize renormalization_factors, and variables to be normalized */
629 600 : set_zero_fx( renormalization_factor_diff_fx, hMcMasa->nbands );
630 600 : set16_fx( renormalization_factor_diff_e, 0, hMcMasa->nbands );
631 600 : set_zero_fx( diffuseness_m_fx, hMcMasa->nbands );
632 600 : set16_fx( diffuseness_e, 0, hMcMasa->nbands );
633 600 : set_zero_fx( hMcMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
634 600 : set16_fx( hMcMasa->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
635 : /* Reset variable */
636 15000 : FOR( i = 0; i < hMcMasa->nbands; i++ )
637 : {
638 172800 : FOR( j = 0; j < numAnalysisChannels; j++ )
639 : {
640 158400 : set_zero_fx( COVls[i].xr_fx[j], numAnalysisChannels );
641 158400 : set_zero_fx( COVls[i].xi_fx[j], numAnalysisChannels );
642 158400 : set16_fx( COVls[i].xr_e[j], 0, numAnalysisChannels );
643 158400 : set16_fx( COVls[i].xi_e[j], 0, numAnalysisChannels );
644 : }
645 : }
646 :
647 3000 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
648 : {
649 2400 : Word16 cr_q = MAX_16, ci_q = MAX_16, c_e;
650 2400 : move16();
651 2400 : move16();
652 2400 : Word16 inp_q = scaled_data_q;
653 2400 : move16();
654 28800 : FOR( i = 0; i < numAnalysisChannels; i++ )
655 : {
656 26400 : inp_q = scaled_data_q;
657 26400 : move16();
658 26400 : cldfbAnalysis_ts_fx_var_q( &( data_fx[i][i_mult( l_ts, ts )] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hMcMasa->cldfbAnaEnc[i], &inp_q );
659 26400 : cr_q = s_min( cr_q, getScaleFactor32( Chnl_ImagBuffer_fx[i], l_ts ) );
660 26400 : ci_q = s_min( ci_q, getScaleFactor32( Chnl_RealBuffer_fx[i], l_ts ) );
661 : }
662 2400 : sf = sub( s_min( cr_q, ci_q ), 4 );
663 28800 : FOR( i = 0; i < numAnalysisChannels; i++ )
664 : {
665 26400 : scale_sig32( Chnl_RealBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
666 26400 : scale_sig32( Chnl_ImagBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
667 : }
668 2400 : inp_q = add( inp_q, sf );
669 2400 : c_e = sub( 31, inp_q );
670 2400 : hMcMasa->chnlToFoaMtx_e = c_e;
671 2400 : move16();
672 : /* Compute channel-based energy for metadata processing */
673 60000 : FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
674 : {
675 57600 : brange[0] = hMcMasa->band_grouping[band_m_idx];
676 57600 : move16();
677 57600 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
678 57600 : move16();
679 201600 : FOR( j = brange[0]; j < brange[1]; j++ )
680 : {
681 1728000 : FOR( i = 0; i < numAnalysisChannels; i++ )
682 : {
683 1584000 : W_temp = W_mac_32_32( W_mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ); // Q-> 2*inp_q + 1
684 1584000 : sf = W_norm( W_temp );
685 1584000 : temp = W_extract_h( W_shl( W_temp, sf ) ); // 2 * inp_q + 1 + sf - 32
686 1584000 : temp_e = sub( 31 + 31, add( shl( inp_q, 1 ), sf ) ); // e = 31 - (2 * inp_q + 1 + sf - 32)
687 :
688 1584000 : hMcMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->energy_fx[block_m_idx][band_m_idx], hMcMasa->energy_e[block_m_idx][band_m_idx], temp, temp_e, &hMcMasa->energy_e[block_m_idx][band_m_idx] );
689 1584000 : move32();
690 : }
691 : }
692 : }
693 :
694 : /* Compute covariance matrix */
695 60000 : FOR( i = 0; i < num_freq_bands; i++ )
696 : {
697 57600 : brange[0] = hMcMasa->band_grouping[i];
698 57600 : move16();
699 57600 : brange[1] = hMcMasa->band_grouping[i + 1];
700 57600 : move16();
701 201600 : FOR( j = brange[0]; j < brange[1]; j++ )
702 : {
703 144000 : compute_cov_mtx_fx( Chnl_RealBuffer_fx, Chnl_ImagBuffer_fx, j, numAnalysisChannels, &( COVls[i] ), c_e );
704 : }
705 : }
706 :
707 : /* Compute standard FOA */
708 : /* W */
709 2400 : v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
710 2400 : v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
711 24000 : FOR( i = 2; i < numAnalysisChannels; i++ )
712 : {
713 21600 : v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
714 21600 : v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
715 : }
716 :
717 : /* Y */
718 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
719 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
720 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
721 : {
722 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
723 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
724 : }
725 : /* Z */
726 2400 : IF( hMcMasa->isHorizontalSetup )
727 : {
728 : /* Set zero for horizontal setups */
729 0 : set_zero_fx( Foa_RealBuffer_fx[2], num_freq_bins );
730 0 : set_zero_fx( Foa_ImagBuffer_fx[2], num_freq_bins );
731 : }
732 : ELSE
733 : {
734 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
735 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
736 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
737 : {
738 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
739 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
740 : }
741 : }
742 : /* X */
743 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
744 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
745 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
746 : {
747 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
748 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
749 : }
750 :
751 : /* Compute even FOA */
752 : /* W */
753 2400 : Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
754 2400 : Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
755 :
756 : /* Y */
757 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
758 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
759 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
760 : {
761 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
762 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
763 : }
764 :
765 : /* Z (even setups are handled as horizontal) */
766 2400 : set_zero_fx( FoaEven_RealBuffer_fx[2], num_freq_bins );
767 2400 : set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins );
768 :
769 : /* X */
770 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
771 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
772 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
773 : {
774 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
775 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
776 : }
777 :
778 : /* Direction estimation */
779 2400 : computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx, intensity_real_q, inp_q );
780 :
781 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,
782 : intensity_real_q ); /* Q direction_vector_fx = Q30*/
783 :
784 : /* Power and intensity estimation for diffuseness */
785 2400 : computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx, intensity_even_real_q, inp_q );
786 :
787 2400 : computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands, inp_q, &reference_power_q );
788 :
789 : /* Aligning intensity_real and intensity_even_real to a common Q-factor */
790 2400 : minimum_fx( intensity_real_q, num_freq_bands, &intensity_q );
791 2400 : minimum_fx( intensity_even_real_q, num_freq_bands, &intensity_even_q );
792 :
793 : Word16 tmp;
794 60000 : FOR( i = 0; i < num_freq_bands; i++ )
795 : {
796 57600 : tmp = sub( intensity_q, intensity_real_q[i] );
797 57600 : intensity_real_fx[0][i] = L_shl( intensity_real_fx[0][i], tmp );
798 57600 : move32();
799 57600 : intensity_real_fx[1][i] = L_shl( intensity_real_fx[1][i], tmp );
800 57600 : move32();
801 57600 : intensity_real_fx[2][i] = L_shl( intensity_real_fx[2][i], tmp );
802 57600 : move32();
803 :
804 57600 : tmp = sub( intensity_even_q, intensity_even_real_q[i] );
805 57600 : intensity_even_real_fx[0][i] = L_shl( intensity_even_real_fx[0][i], tmp );
806 57600 : move32();
807 57600 : intensity_even_real_fx[1][i] = L_shl( intensity_even_real_fx[1][i], tmp );
808 57600 : move32();
809 57600 : intensity_even_real_fx[2][i] = L_shl( intensity_even_real_fx[2][i], tmp );
810 57600 : move32();
811 : }
812 :
813 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
814 2400 : hMcMasa->index_buffer_intensity = add( ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
815 2400 : index = hMcMasa->index_buffer_intensity;
816 2400 : move16();
817 9600 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
818 : {
819 : /* only real part needed */
820 7200 : Copy32( intensity_even_real_fx[i], &( hMcMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands );
821 : }
822 2400 : hMcMasa->buffer_intensity_real_q[index - 1] = intensity_even_q;
823 2400 : move16();
824 2400 : Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[i_mult( index - 1, num_freq_bands )] ), num_freq_bands );
825 2400 : hMcMasa->buffer_energy_q[index - 1] = reference_power_q;
826 2400 : move16();
827 2400 : computeDiffuseness_fixed( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q, out_exp ); // out_exp = Q30
828 : /* Compute vertical diffuseness, and tune original diffuseness if needed */
829 2400 : IF( !hMcMasa->isHorizontalSetup )
830 : {
831 2400 : Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands );
832 2400 : hMcMasa->buffer_intensity_real_vert_q[index - 1] = intensity_q;
833 2400 : move16();
834 2400 : computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, num_freq_bands, vertical_diffuseness_vector_fx, hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q ); // Q vertical_diffuseness_vector_fx = 31
835 2400 : v_min_fx( diffuseness_vector_fx, out_exp, vertical_diffuseness_vector_fx, q_vdv, diffuseness_vector_fx, out_exp, num_freq_bands );
836 : }
837 60000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
838 : {
839 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*/
840 57600 : hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hMcMasa->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 ), &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] );
841 57600 : hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hMcMasa->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 ), &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] );
842 57600 : hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hMcMasa->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 ), &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] );
843 :
844 57600 : W_temp = W_mult0_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] );
845 57600 : s = W_norm( W_temp );
846 57600 : temp = W_extract_h( W_shl( W_temp, s ) );
847 57600 : temp_e = sub( 63, add( Q30, add( reference_power_q, s ) ) ); // 31 - ( reference_power_q + diffuseness_q + s - 32 )
848 :
849 57600 : diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], temp, temp_e, &diffuseness_e[band_m_idx] );
850 :
851 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] );
852 57600 : move32();
853 57600 : move32();
854 57600 : move32();
855 57600 : move32();
856 57600 : move32();
857 : }
858 : }
859 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
860 : {
861 14400 : Word16 max_e = MIN_16;
862 14400 : move16();
863 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
864 : {
865 43200 : max_e = s_max( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] );
866 : }
867 14400 : max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/
868 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
869 : {
870 43200 : dir_v_fx[d] = L_shr( hMcMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) );
871 43200 : move32();
872 : }
873 14400 : Word16 div_q = sub( 31, max_e );
874 14400 : ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, div_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] );
875 14400 : elevation_m_values_fx[block_m_idx][band_m_idx] = L_add( elevation_m_values_fx[block_m_idx][band_m_idx], L_shr( elevation_m_values_fx[block_m_idx][band_m_idx], 5 ) );
876 14400 : move32();
877 : }
878 :
879 : /* Coherence processing */
880 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
881 : {
882 : /* Compute absolute values */
883 172800 : FOR( i = 0; i < numAnalysisChannels; i++ )
884 : {
885 1108800 : FOR( j = i; j < numAnalysisChannels; j++ )
886 : {
887 950400 : temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( COVls[band_m_idx].xr_fx[i][j], COVls[band_m_idx].xr_fx[i][j] ), shl( COVls[band_m_idx].xr_e[i][j], 1 ), Mult_32_32( COVls[band_m_idx].xi_fx[i][j], COVls[band_m_idx].xi_fx[i][j] ), shl( COVls[band_m_idx].xi_e[i][j], 1 ), &absCOVls_e[i][j] );
888 950400 : absCOVls_fx[i][j] = Sqrt32( temp, &absCOVls_e[i][j] );
889 950400 : move32();
890 : }
891 158400 : lsEnergy_fx[i] = absCOVls_fx[i][i];
892 158400 : move32();
893 158400 : lsEnergy_e[i] = absCOVls_e[i][i];
894 158400 : move16();
895 : }
896 :
897 : /* Find loudest channel */
898 14400 : maxEne_fx = lsEnergy_fx[0];
899 14400 : move32();
900 14400 : maxEne_e = lsEnergy_e[0];
901 14400 : move16();
902 14400 : loudestCh = 0;
903 158400 : FOR( i = 1; i < numAnalysisChannels; i++ )
904 : {
905 144000 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], maxEne_fx, maxEne_e ), 1 ) )
906 : {
907 27488 : maxEne_fx = lsEnergy_fx[i];
908 27488 : move32();
909 27488 : maxEne_e = lsEnergy_e[i];
910 27488 : move16();
911 27488 : loudestCh = i;
912 27488 : move16();
913 : }
914 : }
915 :
916 : /* Compute surrounding coherence */
917 14400 : surrCoh_fx = ONE_IN_Q31;
918 14400 : move32();
919 14400 : surrCoh_e = 0;
920 14400 : move16();
921 172800 : FOR( i = 0; i < numAnalysisChannels; i++ )
922 : {
923 158400 : IF( NE_16( i, loudestCh ) )
924 : {
925 144000 : IF( LT_16( i, loudestCh ) )
926 : {
927 87885 : i1 = i;
928 87885 : move16();
929 87885 : i2 = loudestCh;
930 87885 : move16();
931 : }
932 : ELSE
933 : {
934 56115 : i1 = loudestCh;
935 56115 : move16();
936 56115 : i2 = i;
937 56115 : move16();
938 : }
939 144000 : Word16 temp_exp = add( lsEnergy_e[i1], lsEnergy_e[i2] );
940 144000 : temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_exp );
941 144000 : tempCoh_e = 0;
942 144000 : move16();
943 144000 : tempCoh_fx = L_shl( BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], temp, &tempCoh_e ), 16 );
944 144000 : tempCoh_e = add( sub( absCOVls_e[i1][i2], temp_exp ), tempCoh_e );
945 144000 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( surrCoh_fx, surrCoh_e, tempCoh_fx, tempCoh_e ), -1 ) )
946 : {
947 39801 : surrCoh_fx = tempCoh_fx;
948 39801 : move32();
949 39801 : surrCoh_e = tempCoh_e;
950 39801 : move16();
951 : }
952 : }
953 : }
954 14400 : surrCoh_fx = L_shl( surrCoh_fx, surrCoh_e );
955 14400 : surrCoh_e = 0;
956 14400 : move16();
957 14400 : surrCoh_fx = Mult_32_32( surrCoh_fx, surrCoh_fx );
958 14400 : IF( GE_32( surrCoh_fx, ONE_IN_Q31 ) )
959 : {
960 0 : surrCoh_fx = ONE_IN_Q31;
961 0 : move32();
962 : }
963 14400 : surrCoh_fx = L_max( surrCoh_fx, 0 );
964 : /* Compute spread coherence */
965 14400 : IF( LT_32( elevation_m_values_fx[block_m_idx][band_m_idx], NEAR_HORIZONTAL_PLANE_ELEVATION_FX ) ) /* Computed only near horizontal plane */
966 : {
967 1231 : minAngleDist_fx = 754974720; /*Q22*/
968 1231 : move32();
969 1231 : i1 = 0;
970 1231 : move16();
971 1231 : currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; /*Q22*/
972 1231 : move32();
973 9848 : FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
974 : {
975 8617 : angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); /*Q22*/
976 8617 : IF( GT_32( angleDist_fx, 754974720 /*180.0f Q.22*/ ) )
977 : {
978 554 : angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); /*Q22*/
979 : }
980 8617 : IF( LT_32( angleDist_fx, minAngleDist_fx ) )
981 : {
982 2904 : minAngleDist_fx = angleDist_fx; /*Q22*/
983 2904 : move32();
984 2904 : i1 = i;
985 2904 : move16();
986 : }
987 : }
988 1231 : i2 = hMcMasa->leftNearest[i1];
989 1231 : move16();
990 1231 : i3 = hMcMasa->rightNearest[i1];
991 1231 : move16();
992 1231 : temp_e = add( lsEnergy_e[i2], lsEnergy_e[i3] );
993 1231 : temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i2], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e );
994 1231 : IF( LT_16( i2, i3 ) )
995 : {
996 900 : stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i3], temp, &stereoCoh_e );
997 900 : stereoCoh_e = add( sub( absCOVls_e[i2][i3], temp_e ), stereoCoh_e );
998 : }
999 : ELSE
1000 : {
1001 331 : stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i2], temp, &stereoCoh_e );
1002 331 : stereoCoh_e = add( sub( absCOVls_e[i3][i2], temp_e ), stereoCoh_e );
1003 : }
1004 1231 : stereoCoh_fx = L_shl( stereoCoh_fx, 16 );
1005 : Word32 temp1, temp2;
1006 : Word16 temp1_e, temp2_e;
1007 1231 : temp1 = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i2], lsEnergy_e[i2], lsEnergy_fx[i3], lsEnergy_e[i3], &temp1_e );
1008 1231 : temp2 = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, lsEnergy_fx[i1], lsEnergy_e[i1], &temp2_e );
1009 1231 : temp2 = L_add( temp2, EPSILON_FX );
1010 1231 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e );
1011 1231 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, temp2_e ) );
1012 1231 : lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
1013 1231 : stereoness_fx = Mult_32_32( stereoCoh_fx, lsEnergyRelation_fx );
1014 1231 : stereoness_e = stereoCoh_e;
1015 1231 : move16();
1016 1231 : IF( LT_16( i1, i2 ) )
1017 : {
1018 514 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
1019 514 : tempCoh_fx = BASOP_Util_Divide3232_Scale_newton( absCOVls_fx[i1][i2], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
1020 514 : tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i1][i2], temp_e ) );
1021 : }
1022 : ELSE
1023 : {
1024 717 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
1025 717 : tempCoh_fx = BASOP_Util_Divide3232_Scale_newton( absCOVls_fx[i2][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
1026 717 : tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i2][i1], temp_e ) );
1027 : }
1028 1231 : IF( LT_16( i1, i3 ) )
1029 : {
1030 400 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
1031 400 : tempCoh2_fx = BASOP_Util_Divide3232_Scale_newton( absCOVls_fx[i1][i3], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
1032 400 : tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i1][i3], temp_e ) );
1033 : }
1034 : ELSE
1035 : {
1036 831 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
1037 831 : tempCoh2_fx = BASOP_Util_Divide3232_Scale_newton( absCOVls_fx[i3][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
1038 831 : tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i3][i1], temp_e ) );
1039 : }
1040 1231 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tempCoh_fx, tempCoh_e, tempCoh2_fx, tempCoh2_e ), -1 ) )
1041 : {
1042 712 : cohPanCoh_fx = tempCoh_fx;
1043 712 : move32();
1044 712 : cohPanCoh_e = tempCoh_e;
1045 712 : move16();
1046 : }
1047 : ELSE
1048 : {
1049 519 : cohPanCoh_fx = tempCoh2_fx;
1050 519 : move32();
1051 519 : cohPanCoh_e = tempCoh2_e;
1052 519 : move16();
1053 : }
1054 1231 : cohPanCoh_fx = L_shl( cohPanCoh_fx, cohPanCoh_e ); /*Q31*/
1055 1231 : cohPanCoh_e = 0;
1056 1231 : move16();
1057 1231 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i2], L_add( lsEnergy_fx[i1], EPSILON_FX ), &lsEnergyRelation_e );
1058 1231 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( lsEnergy_e[i2], lsEnergy_e[i1] ) );
1059 1231 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i2], EPSILON_FX ), &tempLsEnergyRelation_e );
1060 1231 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i2] ) );
1061 1231 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1062 : {
1063 373 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1064 373 : move32();
1065 373 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1066 373 : move16();
1067 : }
1068 1231 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i3], L_add( lsEnergy_fx[i1], EPSILON_FX ), &tempLsEnergyRelation_e );
1069 1231 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i3], lsEnergy_e[i1] ) );
1070 1231 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1071 : {
1072 354 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1073 354 : move32();
1074 354 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1075 354 : move16();
1076 : }
1077 1231 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i3], EPSILON_FX ), &tempLsEnergyRelation_e );
1078 1231 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i3] ) );
1079 1231 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1080 : {
1081 207 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1082 207 : move32();
1083 207 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1084 207 : move16();
1085 : }
1086 1231 : lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); /*Q31*/
1087 1231 : cohwideness_fx = Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ); /*cohPanCoh_e*/
1088 :
1089 1231 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
1090 : {
1091 211 : spreadCoh_fx = cohwideness_fx;
1092 211 : move32();
1093 211 : spreadCoh_e = cohPanCoh_e;
1094 211 : move16();
1095 : }
1096 : ELSE
1097 : {
1098 1020 : spreadCoh_fx = stereoness_fx;
1099 1020 : move32();
1100 1020 : spreadCoh_e = stereoness_e;
1101 1020 : move16();
1102 : }
1103 1231 : IF( ( spreadCoh_e < 0 ) )
1104 : {
1105 100 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
1106 100 : spreadCoh_e = 0;
1107 100 : move16();
1108 : }
1109 1231 : IF( GT_32( spreadCoh_fx, L_shl_sat( 1, sub( 30, spreadCoh_e ) /*0.5f with exp=spreadCoh_e*/ ) ) )
1110 : {
1111 448 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
1112 : {
1113 :
1114 119 : tempCoh_fx = BASOP_Util_Add_Mant32Exp( stereoness_fx, stereoness_e, L_negate( L_sub( cohwideness_fx, L_shl( 1, sub( 30, cohPanCoh_e ) ) ) ), cohPanCoh_e, &tempCoh_e );
1115 119 : IF( ( tempCoh_e < 0 ) )
1116 : {
1117 119 : tempCoh_fx = L_shl( tempCoh_fx, tempCoh_e );
1118 119 : tempCoh_e = 0;
1119 119 : move16();
1120 : }
1121 119 : IF( GT_32( tempCoh_fx, L_shl_sat( 1, sub( 30, tempCoh_e ) ) ) )
1122 : {
1123 0 : spreadCoh_fx = tempCoh_fx;
1124 0 : move32();
1125 : }
1126 : ELSE
1127 : {
1128 119 : spreadCoh_fx = L_shl_sat( 1, sub( 30, tempCoh_e ) );
1129 : }
1130 119 : spreadCoh_e = tempCoh_e;
1131 119 : move16();
1132 : }
1133 : }
1134 1231 : IF( ( spreadCoh_e < 0 ) )
1135 : {
1136 0 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
1137 0 : spreadCoh_e = 0;
1138 0 : move16();
1139 : }
1140 :
1141 1231 : IF( GE_32( spreadCoh_fx, L_shl_sat( 1, sub( 31, spreadCoh_e ) ) ) )
1142 : {
1143 0 : spreadCoh_fx = L_shl_sat( 1, sub( 31, spreadCoh_e ) );
1144 : }
1145 1231 : IF( ( spreadCoh_fx <= 0 ) )
1146 : {
1147 0 : spreadCoh_fx = 0;
1148 0 : move32();
1149 : }
1150 1231 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); /*Q31*/
1151 : /* Compute energy ratio tuning parameter */
1152 1231 : lsEnergySum_fx = 0;
1153 1231 : move32();
1154 1231 : lsEnergySum_e = 0;
1155 1231 : move16();
1156 14772 : FOR( i = 0; i < numAnalysisChannels; i++ )
1157 : {
1158 13541 : lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
1159 : }
1160 1231 : lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
1161 1231 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, lsEnergySum_fx, &lsEnergyRelation_e );
1162 1231 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, lsEnergySum_e ) );
1163 1231 : lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
1164 1231 : stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); // Q31
1165 1231 : temp2 = L_sub( temp2, EPSILON_FX );
1166 1231 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e );
1167 1231 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp2_e, lsEnergySum_e ) );
1168 1231 : lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
1169 1231 : cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); // Q31
1170 :
1171 1231 : IF( GT_32( stereoRatio_fx, cohPanRatio_fx ) )
1172 : {
1173 51 : cohRatio_fx = stereoRatio_fx;
1174 51 : move32();
1175 : }
1176 : ELSE
1177 : {
1178 1180 : cohRatio_fx = cohPanRatio_fx;
1179 1180 : move32();
1180 : }
1181 :
1182 1231 : IF( GE_32( cohRatio_fx, ONE_IN_Q31 ) )
1183 : {
1184 0 : cohRatio_fx = ONE_IN_Q31;
1185 0 : move32();
1186 : }
1187 :
1188 1231 : IF( cohRatio_fx <= 0 )
1189 : {
1190 131 : cohRatio_fx = 0;
1191 131 : move32();
1192 : }
1193 : }
1194 : ELSE /* Otherwise, set spread coherence to zero */
1195 : {
1196 13169 : spreadCoh_fx = 0;
1197 13169 : move32();
1198 13169 : cohRatio_fx = 0;
1199 13169 : move32();
1200 13169 : lsEnergySum_fx = 0;
1201 13169 : move32();
1202 158028 : FOR( i = 0; i < numAnalysisChannels; i++ )
1203 : {
1204 144859 : lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
1205 : }
1206 13169 : lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
1207 : }
1208 :
1209 : /* Store values */
1210 14400 : spreadCoherence_fx[block_m_idx][band_m_idx] = spreadCoh_fx; /*Q31*/
1211 14400 : move32();
1212 14400 : surroundingCoherence_fx[block_m_idx][band_m_idx] = surrCoh_fx; /*Q31*/
1213 14400 : move32();
1214 14400 : coherentEnergyRatio_fx[band_m_idx] = cohRatio_fx; /*Q31*/
1215 14400 : move32();
1216 : }
1217 :
1218 : /* Determine energy ratios */
1219 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
1220 : {
1221 : Word16 diffuseness_m_e;
1222 14400 : IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) )
1223 : {
1224 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 );
1225 14400 : move32();
1226 14400 : diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
1227 14400 : diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31
1228 14400 : move32();
1229 : }
1230 : ELSE
1231 : {
1232 0 : diffuseness_m_fx[band_m_idx] = 0;
1233 0 : move32();
1234 : }
1235 :
1236 14400 : energyRatio_fx[block_m_idx][band_m_idx] = L_sub( ONE_IN_Q31, diffuseness_m_fx[band_m_idx] );
1237 14400 : move32();
1238 14400 : IF( GT_32( energyRatio_fx[block_m_idx][band_m_idx], coherentEnergyRatio_fx[band_m_idx] ) )
1239 : {
1240 13972 : energyRatio_fx[block_m_idx][band_m_idx] = energyRatio_fx[block_m_idx][band_m_idx];
1241 13972 : move32();
1242 : }
1243 : ELSE
1244 : {
1245 428 : energyRatio_fx[block_m_idx][band_m_idx] = coherentEnergyRatio_fx[band_m_idx];
1246 428 : move32();
1247 : }
1248 : }
1249 : }
1250 :
1251 1800 : FOR( i = 0; i < numAnalysisChannels; i++ )
1252 : {
1253 1650 : scale_sig32( data_fx[i], input_frame, negate( shift ) );
1254 : }
1255 :
1256 150 : return;
1257 : }
1258 :
1259 150 : static void ivas_mcmasa_dmx_fx(
1260 : MCMASA_ANA_HANDLE hMcMasa,
1261 : Word32 data_f_fx[][L_FRAME48k],
1262 : Word16 data_e,
1263 : const Word16 input_frame,
1264 : const Word16 nchan_transport,
1265 : const Word16 nchan_inp )
1266 : {
1267 : Word16 i, j;
1268 : Word16 numAnalysisChannels;
1269 :
1270 : Word32 dmx_c_fx;
1271 : Word32 multiChEne_fx, downmixEne_fx;
1272 : Word32 prevEQ_fx, currEQ_fx, instEQ_fx;
1273 : Word32 alpha_fx, L_tmp, L_tmp1;
1274 150 : Word16 multiChEne_e, scale, downmixEne_e = 0, prevEQ_e, tmp, currEQ_e, instEQ_e;
1275 150 : move16();
1276 :
1277 150 : numAnalysisChannels = sub( nchan_inp, 1 );
1278 :
1279 150 : multiChEne_fx = 0;
1280 150 : move32();
1281 150 : multiChEne_e = 0;
1282 150 : move16();
1283 :
1284 1800 : FOR( j = 0; j < numAnalysisChannels; j++ )
1285 : {
1286 1585650 : FOR( i = 0; i < input_frame; i++ )
1287 : {
1288 1584000 : L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
1289 1584000 : L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
1290 1584000 : multiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, multiChEne_fx, multiChEne_e, &scale );
1291 1584000 : multiChEne_e = scale;
1292 1584000 : move16();
1293 : }
1294 : }
1295 :
1296 150 : IF( EQ_16( nchan_transport, 2 ) )
1297 : {
1298 : Word16 numSideChannels; /* Channels other than left, right, center */
1299 : Word16 leftIndex, rightIndex;
1300 :
1301 150 : numSideChannels = sub( shr( numAnalysisChannels, 1 ), 1 );
1302 750 : FOR( j = 0; j < numSideChannels; j++ )
1303 : {
1304 600 : leftIndex = add( shl( j, 1 ), 3 );
1305 600 : rightIndex = add( shl( j, 1 ), 4 );
1306 :
1307 576600 : FOR( i = 0; i < input_frame; i++ )
1308 : {
1309 576000 : data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[leftIndex][i] );
1310 576000 : move32();
1311 576000 : data_f_fx[1][i] = L_add( data_f_fx[1][i], data_f_fx[rightIndex][i] );
1312 576000 : move32();
1313 : }
1314 : }
1315 :
1316 144150 : FOR( i = 0; i < input_frame; i++ )
1317 : {
1318 144000 : dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_f_fx[2][i] ) ); // data_e
1319 144000 : move32();
1320 144000 : data_f_fx[0][i] = L_add( dmx_c_fx, data_f_fx[0][i] );
1321 144000 : move32();
1322 144000 : data_f_fx[1][i] = L_add( dmx_c_fx, data_f_fx[1][i] );
1323 144000 : move32();
1324 : }
1325 : }
1326 0 : ELSE IF( EQ_16( nchan_transport, 1 ) )
1327 : {
1328 0 : FOR( i = 0; i < input_frame; i++ )
1329 : {
1330 0 : FOR( j = 1; j < numAnalysisChannels; j++ )
1331 : {
1332 0 : data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[j][i] );
1333 0 : move32();
1334 : }
1335 : }
1336 : }
1337 :
1338 150 : downmixEne_fx = 0;
1339 150 : move32();
1340 :
1341 450 : FOR( j = 0; j < nchan_transport; j++ )
1342 : {
1343 288300 : FOR( i = 0; i < input_frame; i++ )
1344 : {
1345 288000 : L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
1346 288000 : L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
1347 288000 : downmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, downmixEne_fx, downmixEne_e, &downmixEne_e );
1348 : }
1349 : }
1350 :
1351 150 : alpha_fx = 214748364; // 0.1 in Q31
1352 150 : move32();
1353 :
1354 150 : L_tmp = Mpy_32_32( alpha_fx, multiChEne_fx );
1355 150 : L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevMultiChEne_fx );
1356 150 : hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e );
1357 :
1358 :
1359 150 : L_tmp = Mpy_32_32( alpha_fx, downmixEne_fx );
1360 150 : L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevDownmixEne_fx );
1361 150 : hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e );
1362 :
1363 150 : prevEQ_fx = hMcMasa->prevEQ_fx;
1364 150 : move32();
1365 150 : prevEQ_e = hMcMasa->prevEQ_e;
1366 150 : move16();
1367 :
1368 150 : tmp = BASOP_Util_Divide3232_Scale( hMcMasa->prevMultiChEne_fx, L_add( hMcMasa->prevDownmixEne_fx, EPSILON_FX ), &scale );
1369 150 : currEQ_e = add( scale, sub( hMcMasa->prevMultiChEne_e, hMcMasa->prevDownmixEne_e ) );
1370 150 : currEQ_fx = Sqrt32( L_deposit_h( tmp ), &currEQ_e );
1371 :
1372 150 : hMcMasa->prevEQ_fx = currEQ_fx;
1373 150 : move32();
1374 150 : hMcMasa->prevEQ_e = currEQ_e;
1375 150 : move16();
1376 :
1377 144150 : FOR( i = 0; i < input_frame; i++ )
1378 : {
1379 144000 : L_tmp = Mpy_32_32( L_deposit_h( hMcMasa->interpolator_fx[i] ), currEQ_fx );
1380 144000 : L_tmp1 = L_sub( 1073741824 /* 1.0 in Q30*/, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); // Q30
1381 144000 : L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); // e = prevEQ_e + 1
1382 144000 : instEQ_fx = BASOP_Util_Add_Mant32Exp( L_tmp, currEQ_e, L_tmp1, add( prevEQ_e, 1 ), &instEQ_e );
1383 :
1384 432000 : FOR( j = 0; j < nchan_transport; j++ )
1385 : {
1386 288000 : data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); // e = data_e + instEQ_e
1387 288000 : move32();
1388 288000 : move32();
1389 288000 : data_f_fx[j][i] = L_shl( data_f_fx[j][i], instEQ_e ); // data_e
1390 : }
1391 : }
1392 :
1393 150 : return;
1394 : }
1395 :
1396 :
1397 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
1398 144000 : static void compute_cov_mtx_fx(
1399 : Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */
1400 : Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */
1401 : const Word16 freq, /* i : Freq to process */
1402 : const Word16 N, /* i : Number of channels */
1403 : CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */
1404 : Word16 inp_exp /* i : Stores exponent for sr and si */
1405 : )
1406 : {
1407 : Word16 i, j;
1408 : Word32 a, b, c, d;
1409 : Word32 temp;
1410 : Word16 norm_a, norm_b, norm_c, norm_d;
1411 : Word16 shift;
1412 1728000 : FOR( i = 0; i < N; i++ )
1413 : {
1414 1584000 : a = sr[i][freq];
1415 1584000 : b = si[i][freq];
1416 1584000 : norm_a = norm_l( a );
1417 1584000 : norm_b = norm_l( b );
1418 1584000 : a = L_shl( a, norm_a ); /*inp_exp-norm_a*/
1419 1584000 : b = L_shl( b, norm_b ); /*inp_exp-norm_b*/
1420 11088000 : FOR( j = i; j < N; j++ )
1421 : {
1422 9504000 : c = sr[j][freq];
1423 9504000 : d = si[j][freq];
1424 9504000 : norm_c = norm_l( c );
1425 9504000 : norm_d = norm_l( d );
1426 9504000 : c = L_shl( c, norm_c ); /*inp_exp-norm_c*/
1427 9504000 : d = L_shl( d, norm_d ); /*inp_exp-norm_d*/
1428 9504000 : temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), sub( shl( inp_exp, 1 ), add( norm_a, norm_c ) ), Mult_32_32( b, d ), sub( shl( inp_exp, 1 ), add( norm_b, norm_d ) ), &shift );
1429 9504000 : COVls->xr_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xr_fx[i][j], COVls->xr_e[i][j], temp, shift, &COVls->xr_e[i][j] );
1430 9504000 : move32();
1431 9504000 : temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( b, c ), sub( shl( inp_exp, 1 ), add( norm_b, norm_c ) ), L_negate( Mult_32_32( a, d ) ), sub( shl( inp_exp, 1 ), add( norm_a, norm_d ) ), &shift );
1432 9504000 : COVls->xi_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xi_fx[i][j], COVls->xi_e[i][j], temp, shift, &COVls->xi_e[i][j] );
1433 9504000 : move32();
1434 : }
1435 : }
1436 :
1437 144000 : return;
1438 : }
1439 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
1440 :
1441 : /*-------------------------------------------------------------------------
1442 : * computeVerticalDiffuseness()
1443 : *
1444 : *
1445 : *------------------------------------------------------------------------*/
1446 2400 : static void computeVerticalDiffuseness_fx(
1447 : Word32 **buffer_intensity, /* i : Intensity vectors */
1448 : const Word32 *buffer_energy, /* i : Energy */
1449 : const Word16 num_freq_bands, /* i : Number of frequency bands */
1450 : Word32 *diffuseness, /* o : Estimated diffuseness Q31 */
1451 : Word16 *buffer_intensity_q,
1452 : Word16 *buffer_energy_q )
1453 : {
1454 : Word32 intensity_slow[MASA_FREQUENCY_BANDS];
1455 : Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS];
1456 : Word32 energy_slow[MASA_FREQUENCY_BANDS];
1457 : Word16 i, k;
1458 2400 : Word32 tmp = 0;
1459 2400 : move32();
1460 : const Word32 *p_tmp_c;
1461 : Word16 intensity_slow_e[MASA_FREQUENCY_BANDS], energy_slow_e[MASA_FREQUENCY_BANDS];
1462 :
1463 : /* Set variables to zero */
1464 2400 : set32_fx( intensity_slow, 0, MASA_FREQUENCY_BANDS );
1465 2400 : set32_fx( energy_slow, 0, MASA_FREQUENCY_BANDS );
1466 2400 : set16_fx( intensity_slow_e, 0, MASA_FREQUENCY_BANDS );
1467 2400 : set16_fx( energy_slow_e, 0, MASA_FREQUENCY_BANDS );
1468 :
1469 79200 : FOR( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
1470 : {
1471 : /* Energy slow */
1472 76800 : p_tmp_c = buffer_energy + i_mult( i, num_freq_bands );
1473 1920000 : FOR( k = 0; k < num_freq_bands; k++ )
1474 : {
1475 1843200 : energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], *( p_tmp_c ), sub( 31, buffer_energy_q[i] ), &energy_slow_e[k] );
1476 1843200 : move32();
1477 1843200 : p_tmp_c++;
1478 : }
1479 :
1480 : /* Intensity slow */
1481 1920000 : FOR( k = 0; k < num_freq_bands; k++ )
1482 : {
1483 1843200 : intensity_slow[k] = BASOP_Util_Add_Mant32Exp( intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k], sub( 31, buffer_intensity_q[i] ), &intensity_slow_e[k] );
1484 1843200 : move32();
1485 : }
1486 : }
1487 :
1488 : /* Compute absolute value */
1489 60000 : FOR( k = 0; k < num_freq_bands; k++ )
1490 : {
1491 57600 : intensity_slow_abs[k] = L_abs( intensity_slow[k] );
1492 57600 : move32();
1493 : }
1494 :
1495 : /* Compute Diffuseness */
1496 60000 : FOR( i = 0; i < num_freq_bands; ++i )
1497 : {
1498 : Word16 tmp_e1, tmp_e2;
1499 57600 : tmp = BASOP_Util_Divide3232_Scale( intensity_slow_abs[i], L_add( energy_slow[i], EPSILON_FX_SMALL ), &tmp_e1 );
1500 57600 : IF( tmp != 0 )
1501 : {
1502 57600 : tmp_e1 = add( tmp_e1, sub( intensity_slow_e[i], energy_slow_e[i] ) );
1503 57600 : tmp = BASOP_Util_Divide3232_Scale( L_sub( tmp, L_shr( VERTICAL_ENERGY_RATIO_OFFSET_FX, tmp_e1 ) ), L_sub( ONE_IN_Q15, VERTICAL_ENERGY_RATIO_OFFSET_FX ), &tmp_e2 ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
1504 57600 : tmp_e2 = add( tmp_e2, tmp_e1 );
1505 57600 : tmp = L_sub( L_shl( 1, sub( 15, tmp_e2 ) ), tmp );
1506 57600 : IF( tmp < 0 )
1507 : {
1508 0 : tmp = 0;
1509 0 : move32();
1510 : }
1511 57600 : ELSE IF( GE_32( tmp, L_shl( 1, sub( 15, tmp_e2 ) ) ) )
1512 : {
1513 1405 : tmp = ONE_IN_Q31; // Q31
1514 1405 : move32();
1515 : }
1516 : ELSE
1517 : {
1518 56195 : tmp = L_shl( tmp, add( 16, tmp_e2 ) ); // Q31
1519 : }
1520 : }
1521 : ELSE
1522 : {
1523 0 : tmp = ONE_IN_Q31; // Q31
1524 0 : move32();
1525 : }
1526 :
1527 57600 : diffuseness[i] = tmp; // Q31
1528 57600 : move32();
1529 : }
1530 :
1531 2400 : return;
1532 : }
1533 :
1534 :
1535 2 : static void computeEvenLayout_fx(
1536 : const Word32 *ls_azimuth, /* i: Q22 */
1537 : Word32 *ls_azimuth_even, /* o: Q22 */
1538 : const Word16 numChannels )
1539 : {
1540 : Word16 i;
1541 : Word16 j;
1542 : Word32 ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
1543 : Word32 ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
1544 : Word16 ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
1545 : Word32 smallestAzimuth;
1546 : Word16 smallestAzimuthIndex;
1547 : Word32 lsSpacing;
1548 : UWord8 oddLayout;
1549 : Word32 startAzimuth;
1550 : Word16 numChannelsHalf;
1551 :
1552 2 : lsSpacing = L_shl( L_mult0( 360, div_s( 1, numChannels ) ), 6 ); /*Q.21*/
1553 2 : oddLayout = (UWord8) s_and( numChannels, 1 );
1554 2 : move16();
1555 2 : numChannelsHalf = shr( numChannels, 1 );
1556 :
1557 2 : Copy32( ls_azimuth, ls_azimuth_temp, numChannels );
1558 2 : Scale_sig32( ls_azimuth_temp, numChannels, -1 ); /*Q.21*/
1559 13 : FOR( i = 0; i < numChannels; i++ )
1560 : {
1561 11 : smallestAzimuth = 1000 << 21; /*Q21*/
1562 11 : move32();
1563 11 : smallestAzimuthIndex = 0;
1564 11 : move16();
1565 76 : FOR( j = 0; j < numChannels; j++ )
1566 : {
1567 65 : IF( LT_32( ls_azimuth_temp[j], smallestAzimuth ) )
1568 : {
1569 21 : smallestAzimuth = ls_azimuth_temp[j]; /*Q21*/
1570 21 : move32();
1571 21 : smallestAzimuthIndex = j;
1572 21 : move16();
1573 : }
1574 : }
1575 11 : ls_azimuth_order[i] = smallestAzimuthIndex;
1576 11 : move32();
1577 11 : ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); /*Q21*/
1578 11 : move32();
1579 : }
1580 :
1581 2 : IF( oddLayout )
1582 : {
1583 1 : startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, shl( numChannelsHalf, 1 ) ) ); /*Q.22*/
1584 : }
1585 : ELSE
1586 : {
1587 1 : startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, sub( shl( numChannelsHalf, 1 ), 1 ) ) ); /*Q.22*/
1588 : }
1589 :
1590 13 : FOR( i = 0; i < numChannels; i++ )
1591 : {
1592 11 : ls_azimuth_even_ordered[i] = W_extract_l( W_add( W_mult_32_16( lsSpacing, i ), startAzimuth ) ); /*Q.22*/
1593 11 : move32();
1594 : }
1595 :
1596 13 : FOR( i = 0; i < numChannels; i++ )
1597 : {
1598 11 : ls_azimuth_even[ls_azimuth_order[i]] = L_shl( L_shr( L_add( ls_azimuth_even_ordered[i], ONE_IN_Q21 /* 0.5 in Q22 */ ), 22 ), 22 ); /*Q22*/
1599 11 : move32();
1600 : }
1601 :
1602 2 : return;
1603 : }
1604 :
1605 :
1606 : /*-------------------------------------------------------------------------
1607 : * ivas_create_masa_out_meta()
1608 : *
1609 : *
1610 : *------------------------------------------------------------------------*/
1611 :
1612 450 : void ivas_create_masa_out_meta_fx(
1613 : MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */
1614 : SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */
1615 : const Word16 nchan_transport, /* i : Number of transport channels */
1616 : Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation Q22 */
1617 : Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth Q22 */
1618 : Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */
1619 : Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */
1620 : Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */
1621 : Word16 energyRatio_q,
1622 : Word16 spreadCoherence_q,
1623 : Word16 surroundingCoherence_q )
1624 : {
1625 : #ifndef FIX_1121_MASA_DESCRIPTOR
1626 : const UWord8 ivasmasaFormatDescriptor[8] = { 0x49, 0x56, 0x41, 0x53, 0x4D, 0x41, 0x53, 0x41 }; /* "IVASMASA" */
1627 : #endif
1628 : Word16 i, sf, band;
1629 : UWord8 numFrequencyBands;
1630 : UWord8 numDirections;
1631 : UWord16 spherical_index;
1632 :
1633 450 : numDirections = 1;
1634 450 : move16();
1635 450 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1636 450 : move16();
1637 :
1638 : /* Construct descriptive meta */
1639 4050 : FOR( i = 0; i < 8; i++ )
1640 : {
1641 3600 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1642 3600 : move16();
1643 : }
1644 450 : extOutMeta->descriptiveMeta.numberOfDirections = (UWord8) sub( numDirections, 1 );
1645 450 : move16();
1646 450 : extOutMeta->descriptiveMeta.numberOfChannels = (UWord8) sub( nchan_transport, 1 );
1647 450 : move16();
1648 : /* Following correspond to "unknown" values */
1649 450 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1650 450 : move16();
1651 450 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1652 450 : move16();
1653 450 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1654 450 : move16();
1655 450 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1656 450 : move16();
1657 450 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1658 450 : move16();
1659 :
1660 : /* Construct spatial metadata from estimated values */
1661 2250 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1662 : {
1663 : /* Spherical index */
1664 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1665 : {
1666 43200 : spherical_index = index_theta_phi_16_fx( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1667 43200 : move16();
1668 43200 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1669 43200 : move16();
1670 43200 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1671 43200 : move16();
1672 : }
1673 :
1674 : /* Direct-to-total ratio */
1675 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1676 : {
1677 43200 : extOutMeta->directToTotalRatio[0][sf][band] = (UWord8) L_shr( Mpy_32_16_1( energyRatio[sf][band], UINT8_MAX ), sub( energyRatio_q, 15 ) ); // Q0
1678 43200 : move16();
1679 43200 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1680 43200 : move16();
1681 : }
1682 :
1683 : /* Spread coherence */
1684 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1685 : {
1686 43200 : extOutMeta->spreadCoherence[0][sf][band] = (UWord8) L_shr( Mpy_32_16_1( spreadCoherence[sf][band], UINT8_MAX ), sub( spreadCoherence_q, 15 ) ); // Q0
1687 43200 : move16();
1688 43200 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1689 43200 : move16();
1690 : }
1691 :
1692 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1693 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1694 : {
1695 43200 : extOutMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( UINT8_MAX, (UWord8) L_shr( Mpy_32_16_1( energyRatio[sf][band], UINT8_MAX ), sub( energyRatio_q, 15 ) ) ); // Q0
1696 43200 : move16();
1697 : }
1698 :
1699 : /* Surround coherence */
1700 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1701 : {
1702 43200 : extOutMeta->surroundCoherence[sf][band] = (UWord8) L_shr( Mpy_32_16_1( surroundingCoherence[sf][band], UINT8_MAX ), sub( surroundingCoherence_q, 15 ) ); // Q0
1703 43200 : move16();
1704 : }
1705 : }
1706 :
1707 450 : return;
1708 : }
|