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 658 : void ivas_mcmasa_ana_close(
404 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
405 : )
406 : {
407 : Word16 i, j;
408 :
409 658 : test();
410 658 : IF( hMcMasa == NULL || *hMcMasa == NULL )
411 : {
412 657 : 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 : Word32 dir_v_fx[DIRAC_NUM_DIMS];
525 : Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
526 : Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
527 : Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
528 : Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
529 : Word32 FoaEven_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
530 : Word32 FoaEven_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
531 : Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
532 : Word32 intensity_even_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
533 : Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
534 : Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
535 : Word32 vertical_diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
536 : Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS];
537 : Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
538 : Word32 coherentEnergyRatio_fx[MASA_FREQUENCY_BANDS];
539 : Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
540 : Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
541 : Word32 norm_tmp_fx;
542 : Word32 absCOVls_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
543 : Word16 absCOVls_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
544 : Word32 lsEnergy_fx[MCMASA_MAX_ANA_CHANS];
545 : Word16 lsEnergy_e[MCMASA_MAX_ANA_CHANS];
546 : Word32 lsEnergySum_fx, maxEne_fx;
547 150 : Word16 lsEnergySum_e = 0;
548 150 : move16();
549 : Word16 maxEne_e;
550 : Word32 angleDist_fx, minAngleDist_fx;
551 : Word32 currentAzi_fx;
552 : Word32 lsEnergyRelation_fx;
553 : Word16 lsEnergyRelation_e;
554 : Word32 tempLsEnergyRelation_fx;
555 : Word32 stereoness_fx, cohwideness_fx, spreadCoh_fx;
556 : Word32 stereoRatio_fx, cohPanRatio_fx;
557 : Word16 stereoness_e;
558 : Word32 stereoCoh_fx, cohPanCoh_fx, cohRatio_fx;
559 : Word32 surrCoh_fx, tempCoh_fx, tempCoh2_fx;
560 : Word16 surrCoh_e;
561 : Word16 stereoCoh_e;
562 : Word16 tempCoh_e;
563 : Word16 tempCoh2_e;
564 : Word16 ts, i, j, d;
565 : Word16 num_freq_bins, num_freq_bands, index;
566 : Word16 l_ts;
567 : Word16 band_m_idx, block_m_idx;
568 : Word16 mrange[2], brange[2];
569 : CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
570 : Word16 loudestCh;
571 : Word16 i1, i2, i3;
572 : Word16 numAnalysisChannels;
573 : Word16 spreadCoh_e;
574 150 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
575 150 : move16();
576 150 : num_freq_bands = hMcMasa->nbands;
577 150 : move16();
578 150 : l_ts = idiv1616( input_frame, CLDFB_NO_COL_MAX );
579 150 : numAnalysisChannels = sub( nchan_inp, 1 );
580 :
581 150 : set16_fx( q_vdv, 31, MASA_FREQUENCY_BANDS );
582 150 : set16_fx( out_exp, 30, MASA_FREQUENCY_BANDS );
583 : /* do processing over all CLDFB time slots */
584 750 : FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
585 : {
586 600 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
587 600 : move16();
588 600 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
589 600 : move16();
590 :
591 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
592 : {
593 14400 : hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
594 14400 : move16();
595 14400 : hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
596 14400 : move16();
597 14400 : hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
598 14400 : move16();
599 14400 : hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
600 14400 : move16();
601 14400 : hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
602 14400 : move16();
603 14400 : hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
604 14400 : move16();
605 : }
606 :
607 : /* Need to initialize renormalization_factors, and variables to be normalized */
608 600 : set_zero_fx( renormalization_factor_diff_fx, hMcMasa->nbands );
609 600 : set16_fx( renormalization_factor_diff_e, 0, hMcMasa->nbands );
610 600 : set_zero_fx( diffuseness_m_fx, hMcMasa->nbands );
611 600 : set16_fx( diffuseness_e, 0, hMcMasa->nbands );
612 600 : set_zero_fx( hMcMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
613 600 : set16_fx( hMcMasa->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
614 : /* Reset variable */
615 15000 : FOR( i = 0; i < hMcMasa->nbands; i++ )
616 : {
617 172800 : FOR( j = 0; j < numAnalysisChannels; j++ )
618 : {
619 158400 : set_zero_fx( COVls[i].xr_fx[j], numAnalysisChannels );
620 158400 : set_zero_fx( COVls[i].xi_fx[j], numAnalysisChannels );
621 158400 : set16_fx( COVls[i].xr_e[j], 0, numAnalysisChannels );
622 158400 : set16_fx( COVls[i].xi_e[j], 0, numAnalysisChannels );
623 : }
624 : }
625 :
626 3000 : FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
627 : {
628 2400 : Word16 cr_q = MAX_16, ci_q = MAX_16, sf, c_e;
629 2400 : move16();
630 2400 : move16();
631 2400 : Word16 inp_q = q_data;
632 2400 : move16();
633 28800 : FOR( i = 0; i < numAnalysisChannels; i++ )
634 : {
635 26400 : inp_q = q_data;
636 26400 : move16();
637 26400 : cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][i_mult( l_ts, ts )] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hMcMasa->cldfbAnaEnc[i], &inp_q );
638 26400 : cr_q = s_min( cr_q, getScaleFactor32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) );
639 26400 : ci_q = s_min( ci_q, getScaleFactor32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) );
640 : }
641 2400 : sf = sub( s_min( cr_q, ci_q ), 4 );
642 28800 : FOR( i = 0; i < numAnalysisChannels; i++ )
643 : {
644 26400 : scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf
645 26400 : scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf
646 : }
647 2400 : inp_q = add( inp_q, sf );
648 2400 : c_e = sub( 31, inp_q );
649 2400 : hMcMasa->chnlToFoaMtx_e = c_e;
650 2400 : move16();
651 : /* Compute channel-based energy for metadata processing */
652 60000 : FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
653 : {
654 57600 : brange[0] = hMcMasa->band_grouping[band_m_idx];
655 57600 : move16();
656 57600 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
657 57600 : move16();
658 201600 : FOR( j = brange[0]; j < brange[1]; j++ )
659 : {
660 1728000 : FOR( i = 0; i < numAnalysisChannels; i++ )
661 : {
662 1584000 : 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
663 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, shl( c_e, 1 ), &hMcMasa->energy_e[block_m_idx][band_m_idx] );
664 1584000 : move32();
665 : }
666 : }
667 : }
668 :
669 : /* Compute covariance matrix */
670 60000 : FOR( i = 0; i < num_freq_bands; i++ )
671 : {
672 57600 : brange[0] = hMcMasa->band_grouping[i];
673 57600 : move16();
674 57600 : brange[1] = hMcMasa->band_grouping[i + 1];
675 57600 : move16();
676 201600 : FOR( j = brange[0]; j < brange[1]; j++ )
677 : {
678 144000 : compute_cov_mtx_fx( Chnl_RealBuffer_fx, Chnl_ImagBuffer_fx, j, numAnalysisChannels, &( COVls[i] ), c_e );
679 : }
680 : }
681 :
682 : /* Compute standard FOA */
683 : /* W */
684 2400 : v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
685 2400 : v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
686 24000 : FOR( i = 2; i < numAnalysisChannels; i++ )
687 : {
688 21600 : v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
689 21600 : v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
690 : }
691 :
692 : /* Y */
693 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
694 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
695 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
696 : {
697 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
698 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
699 : }
700 : /* Z */
701 2400 : IF( hMcMasa->isHorizontalSetup )
702 : {
703 : /* Set zero for horizontal setups */
704 0 : set_zero_fx( Foa_RealBuffer_fx[2], num_freq_bins );
705 0 : set_zero_fx( Foa_ImagBuffer_fx[2], num_freq_bins );
706 : }
707 : ELSE
708 : {
709 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
710 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
711 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
712 : {
713 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
714 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
715 : }
716 : }
717 : /* X */
718 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
719 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], 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[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
723 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
724 : }
725 :
726 : /* Compute even FOA */
727 : /* W */
728 2400 : Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
729 2400 : Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
730 :
731 : /* Y */
732 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
733 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
734 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
735 : {
736 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
737 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
738 : }
739 :
740 : /* Z (even setups are handled as horizontal) */
741 2400 : set_zero_fx( FoaEven_RealBuffer_fx[2], num_freq_bins );
742 2400 : set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins );
743 :
744 : /* X */
745 2400 : v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
746 2400 : v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
747 26400 : FOR( i = 1; i < numAnalysisChannels; i++ )
748 : {
749 24000 : v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
750 24000 : v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
751 : }
752 :
753 : /* Direction estimation */
754 2400 : computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); /* Q intensity_real_fx = 2*inp_q-31, e = 31 - 2*inp_q + 31 = 62 - 2*inp_q = 2*(31-inp_q)=2*c_e */
755 :
756 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], shl( c_e, 1 ),
757 : NULL ); /* Q direction_vector_fx = Q30*/
758 :
759 : /* Power and intensity estimation for diffuseness */
760 2400 : computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx ); /*2*inp_q-31*/
761 2400 : computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); /*2*inp_q-30*/
762 :
763 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
764 2400 : hMcMasa->index_buffer_intensity = add( ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
765 2400 : index = hMcMasa->index_buffer_intensity;
766 2400 : move16();
767 9600 : FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
768 : {
769 : /* only real part needed */
770 7200 : Copy32( intensity_even_real_fx[i], &( hMcMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands );
771 : }
772 2400 : hMcMasa->buffer_intensity_real_q[index - 1] = sub( shl( inp_q, 1 ), 31 );
773 2400 : move16();
774 2400 : Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[i_mult( index - 1, num_freq_bands )] ), num_freq_bands );
775 2400 : hMcMasa->buffer_energy_q[index - 1] = sub( shl( inp_q, 1 ), 30 );
776 2400 : move16();
777 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
778 : /* Compute vertical diffuseness, and tune original diffuseness if needed */
779 2400 : IF( !hMcMasa->isHorizontalSetup )
780 : {
781 2400 : Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands );
782 2400 : hMcMasa->buffer_intensity_real_vert_q[index - 1] = sub( shl( inp_q, 1 ), 31 );
783 2400 : move16();
784 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
785 2400 : v_min_fx( diffuseness_vector_fx, out_exp, vertical_diffuseness_vector_fx, q_vdv, diffuseness_vector_fx, out_exp, num_freq_bands );
786 : }
787 60000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
788 : {
789 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 ); /*2*inp_q-30*/
790 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] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] );
791 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] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] );
792 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] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] );
793 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( shl( c_e, 1 ), 1 ), &diffuseness_e[band_m_idx] );
794 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( shl( c_e, 1 ), 1 ), &renormalization_factor_diff_e[band_m_idx] );
795 57600 : move32();
796 57600 : move32();
797 57600 : move32();
798 57600 : move32();
799 57600 : move32();
800 : }
801 : }
802 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
803 : {
804 14400 : Word16 max_e = MIN_16;
805 14400 : move16();
806 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
807 : {
808 43200 : max_e = s_max( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] );
809 : }
810 14400 : max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/
811 57600 : FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
812 : {
813 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] ) );
814 43200 : move32();
815 : }
816 14400 : Word16 div_q = sub( 31, max_e );
817 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] );
818 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 ) );
819 14400 : move32();
820 : }
821 :
822 : /* Coherence processing */
823 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
824 : {
825 : /* Compute absolute values */
826 172800 : FOR( i = 0; i < numAnalysisChannels; i++ )
827 : {
828 1108800 : FOR( j = i; j < numAnalysisChannels; j++ )
829 : {
830 950400 : Word32 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] );
831 950400 : absCOVls_fx[i][j] = Sqrt32( temp, &absCOVls_e[i][j] );
832 950400 : move32();
833 : }
834 158400 : lsEnergy_fx[i] = absCOVls_fx[i][i];
835 158400 : move32();
836 158400 : lsEnergy_e[i] = absCOVls_e[i][i];
837 158400 : move16();
838 : }
839 :
840 : /* Find loudest channel */
841 14400 : maxEne_fx = lsEnergy_fx[0];
842 14400 : move32();
843 14400 : maxEne_e = lsEnergy_e[0];
844 14400 : move16();
845 14400 : loudestCh = 0;
846 158400 : FOR( i = 1; i < numAnalysisChannels; i++ )
847 : {
848 144000 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], maxEne_fx, maxEne_e ), 1 ) )
849 : {
850 27487 : maxEne_fx = lsEnergy_fx[i];
851 27487 : move32();
852 27487 : maxEne_e = lsEnergy_e[i];
853 27487 : move16();
854 27487 : loudestCh = i;
855 27487 : move16();
856 : }
857 : }
858 :
859 : /* Compute surrounding coherence */
860 14400 : surrCoh_fx = ONE_IN_Q31;
861 14400 : move32();
862 14400 : surrCoh_e = 0;
863 14400 : move16();
864 172800 : FOR( i = 0; i < numAnalysisChannels; i++ )
865 : {
866 158400 : IF( NE_16( i, loudestCh ) )
867 : {
868 144000 : IF( LT_16( i, loudestCh ) )
869 : {
870 87891 : i1 = i;
871 87891 : move16();
872 87891 : i2 = loudestCh;
873 87891 : move16();
874 : }
875 : ELSE
876 : {
877 56109 : i1 = loudestCh;
878 56109 : move16();
879 56109 : i2 = i;
880 56109 : move16();
881 : }
882 144000 : Word16 temp_exp = add( lsEnergy_e[i1], lsEnergy_e[i2] );
883 144000 : Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_exp );
884 144000 : tempCoh_e = 0;
885 144000 : move16();
886 144000 : tempCoh_fx = L_shl( BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], temp, &tempCoh_e ), 16 );
887 144000 : tempCoh_e = add( sub( absCOVls_e[i1][i2], temp_exp ), tempCoh_e );
888 144000 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( surrCoh_fx, surrCoh_e, tempCoh_fx, tempCoh_e ), -1 ) )
889 : {
890 39805 : surrCoh_fx = tempCoh_fx;
891 39805 : move32();
892 39805 : surrCoh_e = tempCoh_e;
893 39805 : move16();
894 : }
895 : }
896 : }
897 14400 : surrCoh_fx = L_shl( surrCoh_fx, surrCoh_e );
898 14400 : surrCoh_e = 0;
899 14400 : move16();
900 14400 : surrCoh_fx = Mult_32_32( surrCoh_fx, surrCoh_fx );
901 14400 : IF( GE_32( surrCoh_fx, ONE_IN_Q31 ) )
902 : {
903 0 : surrCoh_fx = ONE_IN_Q31;
904 0 : move32();
905 : }
906 14400 : surrCoh_fx = L_max( surrCoh_fx, 0 );
907 : /* Compute spread coherence */
908 14400 : IF( LT_32( elevation_m_values_fx[block_m_idx][band_m_idx], NEAR_HORIZONTAL_PLANE_ELEVATION_FX ) ) /* Computed only near horizontal plane */
909 : {
910 2042 : minAngleDist_fx = 754974720; /*Q22*/
911 2042 : move32();
912 2042 : i1 = 0;
913 2042 : move16();
914 2042 : currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; /*Q22*/
915 2042 : move32();
916 16336 : FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
917 : {
918 14294 : angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); /*Q22*/
919 14294 : IF( GT_32( angleDist_fx, 754974720 /*180.0f Q.22*/ ) )
920 : {
921 881 : angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); /*Q22*/
922 : }
923 14294 : IF( LT_32( angleDist_fx, minAngleDist_fx ) )
924 : {
925 4611 : minAngleDist_fx = angleDist_fx; /*Q22*/
926 4611 : move32();
927 4611 : i1 = i;
928 4611 : move16();
929 : }
930 : }
931 2042 : i2 = hMcMasa->leftNearest[i1];
932 2042 : move16();
933 2042 : i3 = hMcMasa->rightNearest[i1];
934 2042 : move16();
935 2042 : Word16 temp_e = add( lsEnergy_e[i2], lsEnergy_e[i3] );
936 2042 : Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i2], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e );
937 2042 : IF( LT_16( i2, i3 ) )
938 : {
939 1631 : stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i3], temp, &stereoCoh_e );
940 1631 : stereoCoh_e = add( sub( absCOVls_e[i2][i3], temp_e ), stereoCoh_e );
941 : }
942 : ELSE
943 : {
944 411 : stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i2], temp, &stereoCoh_e );
945 411 : stereoCoh_e = add( sub( absCOVls_e[i3][i2], temp_e ), stereoCoh_e );
946 : }
947 2042 : stereoCoh_fx = L_shl( stereoCoh_fx, 16 );
948 : Word32 temp1, temp2;
949 : Word16 temp1_e, temp2_e;
950 2042 : temp1 = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i2], lsEnergy_e[i2], lsEnergy_fx[i3], lsEnergy_e[i3], &temp1_e );
951 2042 : temp2 = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, lsEnergy_fx[i1], lsEnergy_e[i1], &temp2_e );
952 2042 : temp2 = L_add( temp2, EPSILON_FX );
953 2042 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e );
954 2042 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, temp2_e ) );
955 2042 : lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
956 2042 : stereoness_fx = Mult_32_32( stereoCoh_fx, lsEnergyRelation_fx );
957 2042 : stereoness_e = stereoCoh_e;
958 2042 : move16();
959 2042 : IF( LT_16( i1, i2 ) )
960 : {
961 638 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
962 638 : tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
963 638 : tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i1][i2], temp_e ) );
964 : }
965 : ELSE
966 : {
967 1404 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
968 1404 : tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
969 1404 : tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i2][i1], temp_e ) );
970 : }
971 2042 : tempCoh_fx = L_shl( tempCoh_fx, 16 );
972 2042 : IF( LT_16( i1, i3 ) )
973 : {
974 498 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
975 498 : tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i3], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
976 498 : tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i1][i3], temp_e ) );
977 : }
978 : ELSE
979 : {
980 1544 : temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
981 1544 : tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
982 1544 : tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i3][i1], temp_e ) );
983 : }
984 2042 : tempCoh2_fx = L_shl( tempCoh2_fx, 16 );
985 2042 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tempCoh_fx, tempCoh_e, tempCoh2_fx, tempCoh2_e ), -1 ) )
986 : {
987 1326 : cohPanCoh_fx = tempCoh_fx;
988 1326 : move32();
989 1326 : cohPanCoh_e = tempCoh_e;
990 1326 : move16();
991 : }
992 : ELSE
993 : {
994 716 : cohPanCoh_fx = tempCoh2_fx;
995 716 : move32();
996 716 : cohPanCoh_e = tempCoh2_e;
997 716 : move16();
998 : }
999 2042 : cohPanCoh_fx = L_shl( cohPanCoh_fx, cohPanCoh_e ); /*Q31*/
1000 2042 : cohPanCoh_e = 0;
1001 2042 : move16();
1002 2042 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i2], L_add( lsEnergy_fx[i1], EPSILON_FX ), &lsEnergyRelation_e );
1003 2042 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( lsEnergy_e[i2], lsEnergy_e[i1] ) );
1004 2042 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i2], EPSILON_FX ), &tempLsEnergyRelation_e );
1005 2042 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i2] ) );
1006 2042 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1007 : {
1008 597 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1009 597 : move32();
1010 597 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1011 597 : move16();
1012 : }
1013 2042 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i3], L_add( lsEnergy_fx[i1], EPSILON_FX ), &tempLsEnergyRelation_e );
1014 2042 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i3], lsEnergy_e[i1] ) );
1015 2042 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1016 : {
1017 459 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1018 459 : move32();
1019 459 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1020 459 : move16();
1021 : }
1022 2042 : tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i3], EPSILON_FX ), &tempLsEnergyRelation_e );
1023 2042 : tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i3] ) );
1024 2042 : IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
1025 : {
1026 304 : lsEnergyRelation_fx = tempLsEnergyRelation_fx;
1027 304 : move32();
1028 304 : lsEnergyRelation_e = tempLsEnergyRelation_e;
1029 304 : move16();
1030 : }
1031 2042 : lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); /*Q31*/
1032 2042 : cohwideness_fx = Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ); /*cohPanCoh_e*/
1033 :
1034 2042 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
1035 : {
1036 344 : spreadCoh_fx = cohwideness_fx;
1037 344 : move32();
1038 344 : spreadCoh_e = cohPanCoh_e;
1039 344 : move16();
1040 : }
1041 : ELSE
1042 : {
1043 1698 : spreadCoh_fx = stereoness_fx;
1044 1698 : move32();
1045 1698 : spreadCoh_e = stereoness_e;
1046 1698 : move16();
1047 : }
1048 2042 : IF( ( spreadCoh_e < 0 ) )
1049 : {
1050 161 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
1051 161 : spreadCoh_e = 0;
1052 161 : move16();
1053 : }
1054 2042 : IF( GT_32( spreadCoh_fx, L_shl_sat( 1, sub( 30, spreadCoh_e ) /*0.5f with exp=spreadCoh_e*/ ) ) )
1055 : {
1056 629 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
1057 : {
1058 :
1059 159 : 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 );
1060 159 : IF( ( tempCoh_e < 0 ) )
1061 : {
1062 159 : tempCoh_fx = L_shl( tempCoh_fx, tempCoh_e );
1063 159 : tempCoh_e = 0;
1064 159 : move16();
1065 : }
1066 159 : IF( GT_32( tempCoh_fx, L_shl_sat( 1, sub( 30, tempCoh_e ) ) ) )
1067 : {
1068 0 : spreadCoh_fx = tempCoh_fx;
1069 0 : move32();
1070 : }
1071 : ELSE
1072 : {
1073 159 : spreadCoh_fx = L_shl_sat( 1, sub( 30, tempCoh_e ) );
1074 : }
1075 159 : spreadCoh_e = tempCoh_e;
1076 159 : move16();
1077 : }
1078 : }
1079 2042 : IF( ( spreadCoh_e < 0 ) )
1080 : {
1081 0 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
1082 0 : spreadCoh_e = 0;
1083 0 : move16();
1084 : }
1085 :
1086 2042 : IF( GE_32( spreadCoh_fx, L_shl_sat( 1, sub( 31, spreadCoh_e ) ) ) )
1087 : {
1088 0 : spreadCoh_fx = L_shl_sat( 1, sub( 31, spreadCoh_e ) );
1089 : }
1090 2042 : IF( ( spreadCoh_fx <= 0 ) )
1091 : {
1092 0 : spreadCoh_fx = 0;
1093 0 : move32();
1094 : }
1095 2042 : spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); /*Q31*/
1096 : /* Compute energy ratio tuning parameter */
1097 2042 : lsEnergySum_fx = 0;
1098 2042 : move32();
1099 2042 : lsEnergySum_e = 0;
1100 2042 : move16();
1101 24504 : FOR( i = 0; i < numAnalysisChannels; i++ )
1102 : {
1103 22462 : lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
1104 : }
1105 2042 : lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
1106 2042 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, lsEnergySum_fx, &lsEnergyRelation_e );
1107 2042 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, lsEnergySum_e ) );
1108 2042 : lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
1109 2042 : stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); // Q31
1110 :
1111 2042 : lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e );
1112 2042 : lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp2_e, lsEnergySum_e ) );
1113 2042 : lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
1114 2042 : cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); // Q31
1115 :
1116 2042 : IF( GT_32( stereoRatio_fx, cohPanRatio_fx ) )
1117 : {
1118 104 : cohRatio_fx = stereoRatio_fx;
1119 104 : move32();
1120 : }
1121 : ELSE
1122 : {
1123 1938 : cohRatio_fx = cohPanRatio_fx;
1124 1938 : move32();
1125 : }
1126 :
1127 2042 : IF( GE_32( cohRatio_fx, ONE_IN_Q31 ) )
1128 : {
1129 0 : cohRatio_fx = ONE_IN_Q31;
1130 0 : move32();
1131 : }
1132 :
1133 2042 : IF( cohRatio_fx <= 0 )
1134 : {
1135 595 : cohRatio_fx = 0;
1136 595 : move32();
1137 : }
1138 : }
1139 : ELSE /* Otherwise, set spread coherence to zero */
1140 : {
1141 12358 : spreadCoh_fx = 0;
1142 12358 : move32();
1143 12358 : cohRatio_fx = 0;
1144 12358 : move32();
1145 12358 : lsEnergySum_fx = 0;
1146 12358 : move32();
1147 148296 : FOR( i = 0; i < numAnalysisChannels; i++ )
1148 : {
1149 135938 : lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
1150 : }
1151 12358 : lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
1152 : }
1153 :
1154 : /* Store values */
1155 14400 : spreadCoherence_fx[block_m_idx][band_m_idx] = spreadCoh_fx; /*Q31*/
1156 14400 : move32();
1157 14400 : surroundingCoherence_fx[block_m_idx][band_m_idx] = surrCoh_fx; /*Q31*/
1158 14400 : move32();
1159 14400 : coherentEnergyRatio_fx[band_m_idx] = cohRatio_fx; /*Q31*/
1160 14400 : move32();
1161 : }
1162 :
1163 : /* Determine energy ratios */
1164 15000 : FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
1165 : {
1166 : Word16 diffuseness_m_e;
1167 14400 : IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) )
1168 : {
1169 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 );
1170 14400 : move32();
1171 14400 : diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
1172 14400 : diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31
1173 14400 : move32();
1174 : }
1175 : ELSE
1176 : {
1177 0 : diffuseness_m_fx[band_m_idx] = 0;
1178 0 : move32();
1179 : }
1180 :
1181 14400 : energyRatio_fx[block_m_idx][band_m_idx] = L_sub( ONE_IN_Q31, diffuseness_m_fx[band_m_idx] );
1182 14400 : move32();
1183 14400 : IF( GT_32( energyRatio_fx[block_m_idx][band_m_idx], coherentEnergyRatio_fx[band_m_idx] ) )
1184 : {
1185 13165 : energyRatio_fx[block_m_idx][band_m_idx] = energyRatio_fx[block_m_idx][band_m_idx];
1186 13165 : move32();
1187 : }
1188 : ELSE
1189 : {
1190 1235 : energyRatio_fx[block_m_idx][band_m_idx] = coherentEnergyRatio_fx[band_m_idx];
1191 1235 : move32();
1192 : }
1193 : }
1194 : }
1195 150 : return;
1196 : }
1197 :
1198 150 : static void ivas_mcmasa_dmx_fx(
1199 : MCMASA_ANA_HANDLE hMcMasa,
1200 : Word32 data_f_fx[][L_FRAME48k],
1201 : Word16 data_e,
1202 : const Word16 input_frame,
1203 : const Word16 nchan_transport,
1204 : const Word16 nchan_inp )
1205 : {
1206 : Word16 i, j;
1207 : Word16 numAnalysisChannels;
1208 :
1209 : Word32 dmx_c_fx;
1210 : Word32 multiChEne_fx, downmixEne_fx;
1211 : Word32 prevEQ_fx, currEQ_fx, instEQ_fx;
1212 : Word32 alpha_fx, L_tmp, L_tmp1;
1213 150 : Word16 multiChEne_e, scale, downmixEne_e = 0, prevEQ_e, tmp, currEQ_e, instEQ_e;
1214 150 : move16();
1215 :
1216 150 : numAnalysisChannels = sub( nchan_inp, 1 );
1217 :
1218 150 : multiChEne_fx = 0;
1219 150 : move32();
1220 150 : multiChEne_e = 0;
1221 150 : move16();
1222 :
1223 1800 : FOR( j = 0; j < numAnalysisChannels; j++ )
1224 : {
1225 1585650 : FOR( i = 0; i < input_frame; i++ )
1226 : {
1227 1584000 : L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
1228 1584000 : L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
1229 1584000 : multiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, multiChEne_fx, multiChEne_e, &scale );
1230 1584000 : multiChEne_e = scale;
1231 1584000 : move16();
1232 : }
1233 : }
1234 :
1235 150 : IF( EQ_16( nchan_transport, 2 ) )
1236 : {
1237 : Word16 numSideChannels; /* Channels other than left, right, center */
1238 : Word16 leftIndex, rightIndex;
1239 :
1240 150 : numSideChannels = sub( shr( numAnalysisChannels, 1 ), 1 );
1241 750 : FOR( j = 0; j < numSideChannels; j++ )
1242 : {
1243 600 : leftIndex = add( shl( j, 1 ), 3 );
1244 600 : rightIndex = add( shl( j, 1 ), 4 );
1245 :
1246 576600 : FOR( i = 0; i < input_frame; i++ )
1247 : {
1248 576000 : data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[leftIndex][i] );
1249 576000 : move32();
1250 576000 : data_f_fx[1][i] = L_add( data_f_fx[1][i], data_f_fx[rightIndex][i] );
1251 576000 : move32();
1252 : }
1253 : }
1254 :
1255 144150 : FOR( i = 0; i < input_frame; i++ )
1256 : {
1257 144000 : dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_f_fx[2][i] ) ); // data_e
1258 144000 : move32();
1259 144000 : data_f_fx[0][i] = L_add( dmx_c_fx, data_f_fx[0][i] );
1260 144000 : move32();
1261 144000 : data_f_fx[1][i] = L_add( dmx_c_fx, data_f_fx[1][i] );
1262 144000 : move32();
1263 : }
1264 : }
1265 0 : ELSE IF( EQ_16( nchan_transport, 1 ) )
1266 : {
1267 0 : FOR( i = 0; i < input_frame; i++ )
1268 : {
1269 0 : FOR( j = 1; j < numAnalysisChannels; j++ )
1270 : {
1271 0 : data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[j][i] );
1272 0 : move32();
1273 : }
1274 : }
1275 : }
1276 :
1277 150 : downmixEne_fx = 0;
1278 150 : move32();
1279 :
1280 450 : FOR( j = 0; j < nchan_transport; j++ )
1281 : {
1282 288300 : FOR( i = 0; i < input_frame; i++ )
1283 : {
1284 288000 : L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
1285 288000 : L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
1286 288000 : downmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, downmixEne_fx, downmixEne_e, &downmixEne_e );
1287 : }
1288 : }
1289 :
1290 150 : alpha_fx = 214748364; // 0.1 in Q31
1291 150 : move32();
1292 :
1293 150 : L_tmp = Mpy_32_32( alpha_fx, multiChEne_fx );
1294 150 : L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevMultiChEne_fx );
1295 150 : hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e );
1296 :
1297 :
1298 150 : L_tmp = Mpy_32_32( alpha_fx, downmixEne_fx );
1299 150 : L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevDownmixEne_fx );
1300 150 : hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e );
1301 :
1302 150 : prevEQ_fx = hMcMasa->prevEQ_fx;
1303 150 : move32();
1304 150 : prevEQ_e = hMcMasa->prevEQ_e;
1305 150 : move16();
1306 :
1307 150 : tmp = BASOP_Util_Divide3232_Scale( hMcMasa->prevMultiChEne_fx, L_add( hMcMasa->prevDownmixEne_fx, EPSILON_FX ), &scale );
1308 150 : currEQ_e = add( scale, sub( hMcMasa->prevMultiChEne_e, hMcMasa->prevDownmixEne_e ) );
1309 150 : currEQ_fx = Sqrt32( L_deposit_h( tmp ), &currEQ_e );
1310 :
1311 150 : hMcMasa->prevEQ_fx = currEQ_fx;
1312 150 : move32();
1313 150 : hMcMasa->prevEQ_e = currEQ_e;
1314 150 : move16();
1315 :
1316 144150 : FOR( i = 0; i < input_frame; i++ )
1317 : {
1318 144000 : L_tmp = Mpy_32_32( L_deposit_h( hMcMasa->interpolator_fx[i] ), currEQ_fx );
1319 144000 : L_tmp1 = L_sub( 1073741824 /* 1.0 in Q30*/, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); // Q30
1320 144000 : L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); // e = prevEQ_e + 1
1321 144000 : instEQ_fx = BASOP_Util_Add_Mant32Exp( L_tmp, currEQ_e, L_tmp1, add( prevEQ_e, 1 ), &instEQ_e );
1322 :
1323 432000 : FOR( j = 0; j < nchan_transport; j++ )
1324 : {
1325 288000 : data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); // e = data_e + instEQ_e
1326 288000 : move32();
1327 288000 : move32();
1328 288000 : data_f_fx[j][i] = L_shl( data_f_fx[j][i], instEQ_e ); // data_e
1329 : }
1330 : }
1331 :
1332 150 : return;
1333 : }
1334 :
1335 :
1336 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
1337 144000 : static void compute_cov_mtx_fx(
1338 : Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */
1339 : Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */
1340 : const Word16 freq, /* i : Freq to process */
1341 : const Word16 N, /* i : Number of channels */
1342 : CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */
1343 : Word16 inp_exp /* i : Stores exponent for sr and si */
1344 : )
1345 : {
1346 : Word16 i, j;
1347 : Word32 a, b, c, d;
1348 : Word32 temp;
1349 : Word16 norm_a, norm_b, norm_c, norm_d;
1350 : Word16 shift;
1351 1728000 : FOR( i = 0; i < N; i++ )
1352 : {
1353 1584000 : a = sr[i][freq];
1354 1584000 : b = si[i][freq];
1355 1584000 : norm_a = norm_l( a );
1356 1584000 : norm_b = norm_l( b );
1357 1584000 : a = L_shl( a, norm_a ); /*inp_exp-norm_a*/
1358 1584000 : b = L_shl( b, norm_b ); /*inp_exp-norm_b*/
1359 11088000 : FOR( j = i; j < N; j++ )
1360 : {
1361 9504000 : c = sr[j][freq];
1362 9504000 : d = si[j][freq];
1363 9504000 : norm_c = norm_l( c );
1364 9504000 : norm_d = norm_l( d );
1365 9504000 : c = L_shl( c, norm_c ); /*inp_exp-norm_c*/
1366 9504000 : d = L_shl( d, norm_d ); /*inp_exp-norm_d*/
1367 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 );
1368 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] );
1369 9504000 : move32();
1370 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 );
1371 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] );
1372 9504000 : move32();
1373 : }
1374 : }
1375 :
1376 144000 : return;
1377 : }
1378 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
1379 :
1380 : /*-------------------------------------------------------------------------
1381 : * computeVerticalDiffuseness()
1382 : *
1383 : *
1384 : *------------------------------------------------------------------------*/
1385 2400 : static void computeVerticalDiffuseness_fx(
1386 : Word32 **buffer_intensity, /* i : Intensity vectors */
1387 : const Word32 *buffer_energy, /* i : Energy */
1388 : const Word16 num_freq_bands, /* i : Number of frequency bands */
1389 : Word32 *diffuseness, /* o : Estimated diffuseness Q31 */
1390 : Word16 *buffer_intensity_q,
1391 : Word16 *buffer_energy_q )
1392 : {
1393 : Word32 intensity_slow[MASA_FREQUENCY_BANDS];
1394 : Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS];
1395 : Word32 energy_slow[MASA_FREQUENCY_BANDS];
1396 : Word16 i, k;
1397 2400 : Word32 tmp = 0;
1398 2400 : move32();
1399 : const Word32 *p_tmp_c;
1400 : Word16 intensity_slow_e[MASA_FREQUENCY_BANDS], energy_slow_e[MASA_FREQUENCY_BANDS];
1401 :
1402 : /* Set variables to zero */
1403 2400 : set32_fx( intensity_slow, 0, MASA_FREQUENCY_BANDS );
1404 2400 : set32_fx( energy_slow, 0, MASA_FREQUENCY_BANDS );
1405 2400 : set16_fx( intensity_slow_e, 0, MASA_FREQUENCY_BANDS );
1406 2400 : set16_fx( energy_slow_e, 0, MASA_FREQUENCY_BANDS );
1407 :
1408 79200 : FOR( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
1409 : {
1410 : /* Energy slow */
1411 76800 : p_tmp_c = buffer_energy + i_mult( i, num_freq_bands );
1412 1920000 : FOR( k = 0; k < num_freq_bands; k++ )
1413 : {
1414 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] );
1415 1843200 : move32();
1416 1843200 : p_tmp_c++;
1417 : }
1418 :
1419 : /* Intensity slow */
1420 1920000 : FOR( k = 0; k < num_freq_bands; k++ )
1421 : {
1422 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] );
1423 1843200 : move32();
1424 : }
1425 : }
1426 :
1427 : /* Compute absolute value */
1428 60000 : FOR( k = 0; k < num_freq_bands; k++ )
1429 : {
1430 57600 : intensity_slow_abs[k] = L_abs( intensity_slow[k] );
1431 57600 : move32();
1432 : }
1433 :
1434 : /* Compute Diffuseness */
1435 60000 : FOR( i = 0; i < num_freq_bands; ++i )
1436 : {
1437 : Word16 tmp_e1, tmp_e2;
1438 57600 : tmp = BASOP_Util_Divide3232_Scale( intensity_slow_abs[i], L_add( energy_slow[i], EPSILON_FX_SMALL ), &tmp_e1 );
1439 57600 : tmp_e1 = add( tmp_e1, sub( intensity_slow_e[i], energy_slow_e[i] ) );
1440 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 */
1441 57600 : tmp_e2 = add( tmp_e2, tmp_e1 );
1442 57600 : tmp = L_sub( L_shl( 1, sub( 15, tmp_e2 ) ), tmp );
1443 57600 : IF( tmp < 0 )
1444 : {
1445 0 : tmp = 0;
1446 0 : move32();
1447 : }
1448 57600 : ELSE IF( GE_32( tmp, L_shl( 1, sub( 15, tmp_e2 ) ) ) )
1449 : {
1450 1406 : tmp = ONE_IN_Q31; // Q31
1451 1406 : move32();
1452 : }
1453 : ELSE
1454 : {
1455 56194 : tmp = L_shl( tmp, add( 16, tmp_e2 ) ); // Q31
1456 : }
1457 57600 : diffuseness[i] = tmp; // Q31
1458 57600 : move32();
1459 : }
1460 :
1461 2400 : return;
1462 : }
1463 :
1464 :
1465 2 : static void computeEvenLayout_fx(
1466 : const Word32 *ls_azimuth, /* i: Q22 */
1467 : Word32 *ls_azimuth_even, /* o: Q22 */
1468 : const Word16 numChannels )
1469 : {
1470 : Word16 i;
1471 : Word16 j;
1472 : Word32 ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
1473 : Word32 ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
1474 : Word16 ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
1475 : Word32 smallestAzimuth;
1476 : Word16 smallestAzimuthIndex;
1477 : Word32 lsSpacing;
1478 : UWord8 oddLayout;
1479 : Word32 startAzimuth;
1480 : Word16 numChannelsHalf;
1481 :
1482 2 : lsSpacing = L_shl( L_mult0( 360, div_s( 1, numChannels ) ), 6 ); /*Q.21*/
1483 2 : oddLayout = (UWord8) s_and( numChannels, 1 );
1484 2 : move16();
1485 2 : numChannelsHalf = shr( numChannels, 1 );
1486 :
1487 2 : Copy32( ls_azimuth, ls_azimuth_temp, numChannels );
1488 2 : Scale_sig32( ls_azimuth_temp, numChannels, -1 ); /*Q.21*/
1489 13 : FOR( i = 0; i < numChannels; i++ )
1490 : {
1491 11 : smallestAzimuth = 1000 << 21; /*Q21*/
1492 11 : move32();
1493 11 : smallestAzimuthIndex = 0;
1494 11 : move16();
1495 76 : FOR( j = 0; j < numChannels; j++ )
1496 : {
1497 65 : IF( LT_32( ls_azimuth_temp[j], smallestAzimuth ) )
1498 : {
1499 21 : smallestAzimuth = ls_azimuth_temp[j]; /*Q21*/
1500 21 : move32();
1501 21 : smallestAzimuthIndex = j;
1502 21 : move16();
1503 : }
1504 : }
1505 11 : ls_azimuth_order[i] = smallestAzimuthIndex;
1506 11 : move32();
1507 11 : ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); /*Q21*/
1508 11 : move32();
1509 : }
1510 :
1511 2 : IF( oddLayout )
1512 : {
1513 1 : startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, shl( numChannelsHalf, 1 ) ) ); /*Q.22*/
1514 : }
1515 : ELSE
1516 : {
1517 1 : startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, sub( shl( numChannelsHalf, 1 ), 1 ) ) ); /*Q.22*/
1518 : }
1519 :
1520 13 : FOR( i = 0; i < numChannels; i++ )
1521 : {
1522 11 : ls_azimuth_even_ordered[i] = W_extract_l( W_add( W_mult_32_16( lsSpacing, i ), startAzimuth ) ); /*Q.22*/
1523 11 : move32();
1524 : }
1525 :
1526 13 : FOR( i = 0; i < numChannels; i++ )
1527 : {
1528 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*/
1529 11 : move32();
1530 : }
1531 :
1532 2 : return;
1533 : }
1534 :
1535 :
1536 : /*-------------------------------------------------------------------------
1537 : * ivas_create_masa_out_meta()
1538 : *
1539 : *
1540 : *------------------------------------------------------------------------*/
1541 :
1542 450 : void ivas_create_masa_out_meta_fx(
1543 : MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */
1544 : SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */
1545 : const Word16 nchan_transport, /* i : Number of transport channels */
1546 : Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation Q22 */
1547 : Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth Q22 */
1548 : Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */
1549 : Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */
1550 : Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */
1551 : Word16 energyRatio_q,
1552 : Word16 spreadCoherence_q,
1553 : Word16 surroundingCoherence_q
1554 :
1555 : )
1556 : {
1557 450 : const UWord8 ivasmasaFormatDescriptor[8] = { 0x49, 0x56, 0x41, 0x53, 0x4D, 0x41, 0x53, 0x41 }; /* "IVASMASA" */
1558 : Word16 i, sf, band;
1559 : UWord8 numFrequencyBands;
1560 : UWord8 numDirections;
1561 : UWord16 spherical_index;
1562 :
1563 450 : numDirections = 1;
1564 450 : move16();
1565 450 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1566 450 : move16();
1567 :
1568 : /* Construct descriptive meta */
1569 4050 : FOR( i = 0; i < 8; i++ )
1570 : {
1571 3600 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1572 3600 : move16();
1573 : }
1574 450 : extOutMeta->descriptiveMeta.numberOfDirections = (UWord8) sub( numDirections, 1 );
1575 450 : move16();
1576 450 : extOutMeta->descriptiveMeta.numberOfChannels = (UWord8) sub( nchan_transport, 1 );
1577 450 : move16();
1578 : /* Following correspond to "unknown" values */
1579 450 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1580 450 : move16();
1581 450 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1582 450 : move16();
1583 450 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1584 450 : move16();
1585 450 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1586 450 : move16();
1587 450 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1588 450 : move16();
1589 :
1590 : /* Construct spatial metadata from estimated values */
1591 2250 : FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1592 : {
1593 : /* Spherical index */
1594 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1595 : {
1596 43200 : spherical_index = index_theta_phi_16_fx( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1597 43200 : move16();
1598 43200 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1599 43200 : move16();
1600 43200 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1601 43200 : move16();
1602 : }
1603 :
1604 : /* Direct-to-total ratio */
1605 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1606 : {
1607 43200 : extOutMeta->directToTotalRatio[0][sf][band] = (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ); // Q8
1608 43200 : move16();
1609 43200 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1610 43200 : move16();
1611 : }
1612 :
1613 : /* Spread coherence */
1614 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1615 : {
1616 43200 : extOutMeta->spreadCoherence[0][sf][band] = (UWord8) L_shr( spreadCoherence[sf][band], sub( spreadCoherence_q, 8 ) ); // Q8
1617 43200 : move16();
1618 43200 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1619 43200 : move16();
1620 : }
1621 :
1622 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1623 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1624 : {
1625 43200 : extOutMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( UINT8_MAX, (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ) ); // Q8
1626 43200 : move16();
1627 : }
1628 :
1629 : /* Surround coherence */
1630 45000 : FOR( band = 0; band < numFrequencyBands; band++ )
1631 : {
1632 43200 : extOutMeta->surroundCoherence[sf][band] = (UWord8) L_shr( surroundingCoherence[sf][band], sub( surroundingCoherence_q, 8 ) ); // Q8
1633 43200 : move16();
1634 : }
1635 : }
1636 :
1637 450 : return;
1638 : }
|