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.h"
39 : #include "ivas_prot.h"
40 : #include "prot.h"
41 : #include "ivas_stat_rend.h"
42 : #include "ivas_rom_com.h"
43 : #ifdef DEBUGGING
44 : #include "debug.h"
45 : #endif
46 : #include "wmc_auto.h"
47 :
48 :
49 : /*-------------------------------------------------------------------------
50 : * Local constants
51 : *------------------------------------------------------------------------*/
52 :
53 : #define NEAR_HORIZONTAL_PLANE_ELEVATION 17.5f
54 : #define VERTICAL_ENERGY_RATIO_OFFSET 0.15f
55 :
56 :
57 : /*-------------------------------------------------------------------------
58 : * Local function prototypes
59 : *------------------------------------------------------------------------*/
60 :
61 : /* Structure for covariance matrix */
62 : typedef struct
63 : {
64 : float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
65 : float xi[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
66 : } CovarianceMatrix;
67 :
68 : void ivas_mcmasa_param_est_ana( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const int16_t input_frame, const int16_t nchan_inp );
69 :
70 : static void ivas_mcmasa_dmx( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_transport, const int16_t nchan_inp );
71 :
72 : static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], const int16_t freq, const int16_t N, CovarianceMatrix *COVls );
73 :
74 : static void computeVerticalDiffuseness( float **buffer_intensity, const float *buffer_energy, const int16_t num_freq_bands, float *diffuseness );
75 :
76 : static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, const int16_t numChannels );
77 :
78 :
79 : /*--------------------------------------------------------------------------*
80 : * ivas_mcmasa_ana_open()
81 : *
82 : *
83 : *--------------------------------------------------------------------------*/
84 :
85 4 : ivas_error ivas_mcmasa_ana_open(
86 : MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */
87 : const AUDIO_CONFIG inConfig, /* i : Input config */
88 : int32_t input_Fs /* i : Sampling frequency */
89 : )
90 : {
91 : int16_t i, j;
92 : MCMASA_ANA_HANDLE hMcMasa;
93 : float ls_azimuth[MCMASA_MAX_ANA_CHANS];
94 : float ls_elevation[MCMASA_MAX_ANA_CHANS];
95 : float ls_azimuth_even[MCMASA_MAX_ANA_CHANS];
96 : int16_t nchan_inp;
97 : int16_t numAnalysisChannels;
98 : float left_min, right_min, azi_diff;
99 : int16_t maxBin, input_frame;
100 : ivas_error error;
101 :
102 4 : error = IVAS_ERR_OK;
103 :
104 4 : if ( ( hMcMasa = (MCMASA_ANA_HANDLE) malloc( sizeof( MCMASA_ANA_DATA ) ) ) == NULL )
105 : {
106 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
107 : }
108 :
109 4 : if ( inConfig == IVAS_AUDIO_CONFIG_5_1 )
110 : {
111 0 : nchan_inp = 6;
112 0 : mvr2r( ls_azimuth_CICP6, ls_azimuth, nchan_inp - 1 );
113 0 : mvr2r( ls_elevation_CICP6, ls_elevation, nchan_inp - 1 );
114 0 : hMcMasa->numHorizontalChannels = 5;
115 0 : hMcMasa->isHorizontalSetup = 1;
116 : }
117 4 : else if ( inConfig == IVAS_AUDIO_CONFIG_7_1 )
118 : {
119 0 : nchan_inp = 8;
120 0 : mvr2r( ls_azimuth_CICP12, ls_azimuth, nchan_inp - 1 );
121 0 : mvr2r( ls_elevation_CICP12, ls_elevation, nchan_inp - 1 );
122 0 : hMcMasa->numHorizontalChannels = 7;
123 0 : hMcMasa->isHorizontalSetup = 1;
124 : }
125 4 : else if ( inConfig == IVAS_AUDIO_CONFIG_5_1_2 )
126 : {
127 0 : nchan_inp = 8;
128 0 : mvr2r( ls_azimuth_CICP14, ls_azimuth, nchan_inp - 1 );
129 0 : mvr2r( ls_elevation_CICP14, ls_elevation, nchan_inp - 1 );
130 0 : hMcMasa->numHorizontalChannels = 5;
131 0 : hMcMasa->isHorizontalSetup = 0;
132 : }
133 4 : else if ( inConfig == IVAS_AUDIO_CONFIG_5_1_4 )
134 : {
135 0 : nchan_inp = 10;
136 0 : mvr2r( ls_azimuth_CICP16, ls_azimuth, nchan_inp - 1 );
137 0 : mvr2r( ls_elevation_CICP16, ls_elevation, nchan_inp - 1 );
138 0 : hMcMasa->numHorizontalChannels = 5;
139 0 : hMcMasa->isHorizontalSetup = 0;
140 : }
141 : else
142 : {
143 4 : nchan_inp = 12;
144 4 : mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
145 4 : mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
146 4 : hMcMasa->numHorizontalChannels = 7;
147 4 : hMcMasa->isHorizontalSetup = 0;
148 : }
149 :
150 4 : numAnalysisChannels = nchan_inp - 1;
151 :
152 : /* Determine the number of bands */
153 4 : hMcMasa->nbands = MASA_FREQUENCY_BANDS;
154 :
155 : /* Determine band grouping */
156 4 : mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
157 :
158 4 : maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
159 96 : for ( i = 1; i < hMcMasa->nbands + 1; i++ )
160 : {
161 96 : if ( hMcMasa->band_grouping[i] >= maxBin )
162 : {
163 4 : hMcMasa->band_grouping[i] = maxBin;
164 4 : hMcMasa->nbands = i;
165 4 : break;
166 : }
167 : }
168 :
169 : /* Determine block grouping */
170 4 : mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
171 :
172 : /* open/initialize CLDFB */
173 4 : hMcMasa->num_Cldfb_instances = numAnalysisChannels;
174 48 : for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
175 : {
176 44 : if ( ( error = openCldfb( &( hMcMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
177 : {
178 0 : return error;
179 : }
180 : }
181 :
182 : /* intensity 3-dim */
183 16 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
184 : {
185 12 : if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL )
186 : {
187 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
188 : }
189 :
190 60 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
191 : {
192 48 : if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
193 : {
194 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
195 : }
196 48 : set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
197 : }
198 : }
199 :
200 16 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
201 : {
202 396 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
203 : {
204 384 : if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
205 : {
206 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
207 : }
208 384 : set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
209 : }
210 : }
211 :
212 132 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
213 : {
214 128 : if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
215 : {
216 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
217 : }
218 128 : set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
219 : }
220 :
221 4 : set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
222 :
223 4 : computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
224 :
225 4 : if ( !hMcMasa->isHorizontalSetup )
226 : {
227 4 : computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
228 : }
229 :
230 48 : for ( i = 0; i < numAnalysisChannels; i++ )
231 : {
232 44 : hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
233 44 : hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
234 44 : hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
235 44 : hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
236 :
237 44 : hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
238 44 : hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
239 44 : hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
240 44 : hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
241 : }
242 :
243 4 : mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
244 :
245 32 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
246 : {
247 28 : left_min = 360.0f;
248 28 : right_min = -360.0f;
249 :
250 224 : for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
251 : {
252 196 : azi_diff = ls_azimuth[j] - ls_azimuth[i];
253 :
254 196 : if ( azi_diff > 180.0f )
255 : {
256 12 : azi_diff -= 360.0f;
257 : }
258 184 : else if ( azi_diff < -180.0f )
259 : {
260 12 : azi_diff += 360.0f;
261 : }
262 :
263 196 : if ( azi_diff < left_min && azi_diff > 0.0f )
264 : {
265 48 : hMcMasa->leftNearest[i] = j;
266 48 : left_min = azi_diff;
267 : }
268 :
269 196 : if ( azi_diff > right_min && azi_diff < 0.0f )
270 : {
271 44 : hMcMasa->rightNearest[i] = j;
272 44 : right_min = azi_diff;
273 : }
274 : }
275 : }
276 :
277 4 : hMcMasa->prevMultiChEne = 0.0f;
278 4 : hMcMasa->prevDownmixEne = 0.0f;
279 4 : hMcMasa->prevEQ = 1.0f;
280 4 : input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
281 3844 : for ( i = 0; i < input_frame; i++ )
282 : {
283 3840 : hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
284 : }
285 :
286 4 : hMcMasa->index_buffer_intensity = 0;
287 :
288 4 : if ( ( hMcMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
289 : {
290 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
291 : }
292 :
293 4 : if ( ( hMcMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
294 : {
295 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
296 : }
297 4 : generate_gridEq( hMcMasa->sph_grid16 );
298 :
299 4 : ( *hMcMasaPtr ) = hMcMasa;
300 :
301 4 : return error;
302 : }
303 :
304 :
305 : /*--------------------------------------------------------------------------*
306 : * ivas_mcmasa_ana_close()
307 : *
308 : *
309 : *--------------------------------------------------------------------------*/
310 :
311 8382 : void ivas_mcmasa_ana_close(
312 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
313 : )
314 : {
315 : int16_t i, j;
316 :
317 8382 : if ( hMcMasa == NULL || *hMcMasa == NULL )
318 : {
319 8378 : return;
320 : }
321 :
322 48 : for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
323 : {
324 44 : deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
325 : }
326 :
327 : /* intensity 3-dim */
328 16 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
329 : {
330 60 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
331 : {
332 48 : free( ( *hMcMasa )->direction_vector_m[i][j] );
333 48 : ( *hMcMasa )->direction_vector_m[i][j] = NULL;
334 : }
335 :
336 396 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
337 : {
338 384 : free( ( *hMcMasa )->buffer_intensity_real[i][j] );
339 384 : ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
340 : }
341 :
342 12 : free( ( *hMcMasa )->direction_vector_m[i] );
343 12 : ( *hMcMasa )->direction_vector_m[i] = NULL;
344 : }
345 :
346 132 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
347 : {
348 128 : free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
349 128 : ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
350 : }
351 :
352 4 : free( ( *hMcMasa )->hMasaOut );
353 4 : ( *hMcMasa )->hMasaOut = NULL;
354 4 : free( ( *hMcMasa )->sph_grid16 );
355 4 : ( *hMcMasa )->sph_grid16 = NULL;
356 :
357 4 : free( ( *hMcMasa ) );
358 4 : ( *hMcMasa ) = NULL;
359 :
360 4 : return;
361 : }
362 :
363 :
364 : /*--------------------------------------------------------------------------*
365 : * ivas_mcmasa_ana()
366 : *
367 : * Multichannel MASA analysis
368 : *--------------------------------------------------------------------------*/
369 :
370 604 : void ivas_mcmasa_ana(
371 : MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */
372 : float data_f[][L_FRAME48k], /* i/o: Input / transport audio signals */
373 : const int16_t input_frame, /* i : Input frame size */
374 : const int16_t nchan_transport, /* i : Number of transport channels */
375 : const int16_t nchan_inp /* i : Number of input channels */
376 : )
377 : {
378 : int16_t i;
379 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
380 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
381 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
382 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
383 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
384 :
385 :
386 : /* Sum center and LFE, move surround channels */
387 604 : v_add( data_f[2], data_f[3], data_f[2], input_frame );
388 5436 : for ( i = 4; i < nchan_inp; i++ )
389 : {
390 4832 : mvr2r( data_f[i], data_f[i - 1], input_frame );
391 : }
392 :
393 : /* Analysis */
394 604 : ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp );
395 :
396 : /* Create MASA metadata buffer from the estimated values */
397 604 : ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
398 :
399 : /* Downmix */
400 604 : ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
401 :
402 604 : return;
403 : }
404 :
405 :
406 : /*--------------------------------------------------------------------------*
407 : * Local functions
408 : *--------------------------------------------------------------------------*/
409 :
410 : /* Estimate metadata parameters for McMASA */
411 604 : void ivas_mcmasa_param_est_ana(
412 : MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */
413 : float data_f[][L_FRAME48k], /* i : Audio frame in MC-format */
414 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */
415 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */
416 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */
417 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */
418 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */
419 : const int16_t input_frame, /* i : Input frame size */
420 : const int16_t nchan_inp /* i : Number of input channels */
421 : )
422 : {
423 : float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
424 : int16_t ts, i, j, d;
425 : int16_t num_freq_bins, num_freq_bands, index;
426 : float dir_v[DIRAC_NUM_DIMS];
427 : int16_t l_ts;
428 : float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
429 : float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
430 : float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
431 : float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
432 : float FoaEven_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
433 : float FoaEven_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
434 : float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
435 : float intensity_even_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
436 : float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
437 : float diffuseness_vector[MASA_FREQUENCY_BANDS];
438 : float vertical_diffuseness_vector[MASA_FREQUENCY_BANDS];
439 : float diffuseness_m[MASA_FREQUENCY_BANDS];
440 : float coherentEnergyRatio[MASA_FREQUENCY_BANDS];
441 : int16_t band_m_idx, block_m_idx;
442 : float renormalization_factor_diff[MASA_FREQUENCY_BANDS];
443 : float norm_tmp;
444 : int16_t mrange[2], brange[2];
445 : CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
446 : float absCOVls[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
447 : float lsEnergy[MCMASA_MAX_ANA_CHANS];
448 : float lsEnergySum, maxEne;
449 : int16_t loudestCh;
450 : float surrCoh, tempCoh, tempCoh2;
451 : int16_t i1, i2, i3;
452 : float angleDist, minAngleDist;
453 : float currentAzi;
454 : float lsEnergyRelation;
455 : float tempLsEnergyRelation;
456 : float stereoness, cohwideness, spreadCoh;
457 : float stereoRatio, cohPanRatio;
458 : float stereoCoh, cohPanCoh, cohRatio;
459 : int16_t numAnalysisChannels;
460 :
461 604 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
462 604 : num_freq_bands = hMcMasa->nbands;
463 604 : l_ts = input_frame / CLDFB_NO_COL_MAX;
464 604 : numAnalysisChannels = nchan_inp - 1;
465 :
466 : /* do processing over all CLDFB time slots */
467 3020 : for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
468 : {
469 2416 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
470 2416 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
471 :
472 60400 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
473 : {
474 57984 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
475 57984 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
476 57984 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0;
477 : }
478 :
479 : /* Need to initialize renormalization_factors, and variables to be normalized */
480 2416 : set_zero( renormalization_factor_diff, hMcMasa->nbands );
481 2416 : set_zero( diffuseness_m, hMcMasa->nbands );
482 2416 : set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
483 :
484 : /* Reset variable */
485 60400 : for ( i = 0; i < hMcMasa->nbands; i++ )
486 : {
487 695808 : for ( j = 0; j < numAnalysisChannels; j++ )
488 : {
489 637824 : set_zero( COVls[i].xr[j], numAnalysisChannels );
490 637824 : set_zero( COVls[i].xi[j], numAnalysisChannels );
491 : }
492 : }
493 :
494 12080 : for ( ts = mrange[0]; ts < mrange[1]; ts++ )
495 : {
496 115968 : for ( i = 0; i < numAnalysisChannels; i++ )
497 : {
498 106304 : cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hMcMasa->cldfbAnaEnc[i] );
499 : }
500 :
501 : /* Compute channel-based energy for metadata processing */
502 241600 : for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
503 : {
504 231936 : brange[0] = hMcMasa->band_grouping[band_m_idx];
505 231936 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
506 811776 : for ( j = brange[0]; j < brange[1]; j++ )
507 : {
508 6958080 : for ( i = 0; i < numAnalysisChannels; i++ )
509 : {
510 6378240 : hMcMasa->energy[block_m_idx][band_m_idx] += Chnl_RealBuffer[i][j] * Chnl_RealBuffer[i][j] + Chnl_ImagBuffer[i][j] * Chnl_ImagBuffer[i][j];
511 : }
512 : }
513 : }
514 :
515 : /* Compute covariance matrix */
516 241600 : for ( i = 0; i < num_freq_bands; i++ )
517 : {
518 231936 : brange[0] = hMcMasa->band_grouping[i];
519 231936 : brange[1] = hMcMasa->band_grouping[i + 1];
520 811776 : for ( j = brange[0]; j < brange[1]; j++ )
521 : {
522 579840 : compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
523 : }
524 : }
525 :
526 : /* Compute standard FOA */
527 : /* W */
528 9664 : v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
529 9664 : v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
530 96640 : for ( i = 2; i < numAnalysisChannels; i++ )
531 : {
532 86976 : v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
533 86976 : v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
534 : }
535 :
536 : /* Y */
537 9664 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
538 9664 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
539 106304 : for ( i = 1; i < numAnalysisChannels; i++ )
540 : {
541 96640 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
542 96640 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
543 : }
544 :
545 : /* Z */
546 9664 : if ( hMcMasa->isHorizontalSetup )
547 : {
548 : /* Set zero for horizontal setups */
549 0 : set_zero( Foa_RealBuffer[2], num_freq_bins );
550 0 : set_zero( Foa_ImagBuffer[2], num_freq_bins );
551 : }
552 : else
553 : {
554 9664 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
555 9664 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
556 106304 : for ( i = 1; i < numAnalysisChannels; i++ )
557 : {
558 96640 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
559 96640 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
560 : }
561 : }
562 :
563 : /* X */
564 9664 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
565 9664 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
566 106304 : for ( i = 1; i < numAnalysisChannels; i++ )
567 : {
568 96640 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
569 96640 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins );
570 : }
571 :
572 : /* Compute even FOA */
573 : /* W */
574 9664 : mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
575 9664 : mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
576 :
577 : /* Y */
578 9664 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
579 9664 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
580 106304 : for ( i = 1; i < numAnalysisChannels; i++ )
581 : {
582 96640 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
583 96640 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_ImagBuffer[1], num_freq_bins );
584 : }
585 :
586 : /* Z (even setups are handled as horizontal) */
587 9664 : set_zero( FoaEven_RealBuffer[2], num_freq_bins );
588 9664 : set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
589 :
590 : /* X */
591 9664 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
592 9664 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
593 106304 : for ( i = 1; i < numAnalysisChannels; i++ )
594 : {
595 96640 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
596 96640 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
597 : }
598 :
599 : /* Direction estimation */
600 9664 : computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
601 9664 : computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] );
602 :
603 : /* Power and intensity estimation for diffuseness */
604 9664 : computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
605 9664 : computeReferencePower_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, reference_power[ts], num_freq_bands );
606 :
607 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
608 9664 : hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
609 9664 : index = hMcMasa->index_buffer_intensity;
610 38656 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
611 : {
612 : /* only real part needed */
613 28992 : mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
614 : }
615 9664 : mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
616 :
617 9664 : computeDiffuseness( hMcMasa->buffer_intensity_real, hMcMasa->buffer_energy, num_freq_bands, diffuseness_vector );
618 :
619 : /* Compute vertical diffuseness, and tune original diffuseness if needed */
620 9664 : if ( !hMcMasa->isHorizontalSetup )
621 : {
622 9664 : mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
623 9664 : computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
624 9664 : v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
625 : }
626 :
627 241600 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
628 : {
629 231936 : norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
630 :
631 231936 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
632 231936 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
633 231936 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
634 :
635 231936 : diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
636 231936 : renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
637 : }
638 : }
639 :
640 60400 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
641 : {
642 231936 : for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
643 : {
644 173952 : dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
645 : }
646 57984 : ivas_qmetadata_direction_vector_to_azimuth_elevation( dir_v, &azimuth_m_values[block_m_idx][band_m_idx], &elevation_m_values[block_m_idx][band_m_idx] );
647 : }
648 :
649 : /* Coherence processing */
650 60400 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
651 : {
652 : /* Compute absolute values */
653 695808 : for ( i = 0; i < numAnalysisChannels; i++ )
654 : {
655 4464768 : for ( j = i; j < numAnalysisChannels; j++ )
656 : {
657 3826944 : absCOVls[i][j] = sqrtf( ( COVls[band_m_idx].xr[i][j] * COVls[band_m_idx].xr[i][j] + COVls[band_m_idx].xi[i][j] * COVls[band_m_idx].xi[i][j] ) );
658 : }
659 637824 : lsEnergy[i] = absCOVls[i][i];
660 : }
661 :
662 : /* Find loudest channel */
663 57984 : maxEne = lsEnergy[0];
664 57984 : loudestCh = 0;
665 637824 : for ( i = 1; i < numAnalysisChannels; i++ )
666 : {
667 579840 : if ( lsEnergy[i] > maxEne )
668 : {
669 110384 : maxEne = lsEnergy[i];
670 110384 : loudestCh = i;
671 : }
672 : }
673 :
674 : /* Compute surrounding coherence */
675 57984 : surrCoh = 1.0f;
676 695808 : for ( i = 0; i < numAnalysisChannels; i++ )
677 : {
678 637824 : if ( i != loudestCh )
679 : {
680 579840 : if ( i < loudestCh )
681 : {
682 353084 : i1 = i;
683 353084 : i2 = loudestCh;
684 : }
685 : else
686 : {
687 226756 : i1 = loudestCh;
688 226756 : i2 = i;
689 : }
690 579840 : tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
691 579840 : surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
692 : }
693 : }
694 57984 : surrCoh = surrCoh * surrCoh;
695 57984 : surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
696 57984 : surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
697 :
698 : /* Compute spread coherence */
699 57984 : if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
700 : {
701 4396 : minAngleDist = 180.0f;
702 4396 : i1 = 0;
703 4396 : currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
704 35168 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
705 : {
706 30772 : angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
707 30772 : if ( angleDist > 180.0f )
708 : {
709 768 : angleDist = fabsf( angleDist - 360.0f );
710 : }
711 30772 : if ( angleDist < minAngleDist )
712 : {
713 9816 : minAngleDist = angleDist;
714 9816 : i1 = i;
715 : }
716 : }
717 4396 : i2 = hMcMasa->leftNearest[i1];
718 4396 : i3 = hMcMasa->rightNearest[i1];
719 :
720 4396 : if ( i2 < i3 )
721 : {
722 3512 : stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
723 : }
724 : else
725 : {
726 884 : stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
727 : }
728 4396 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
729 4396 : stereoness = stereoCoh * lsEnergyRelation;
730 :
731 4396 : if ( i1 < i2 )
732 : {
733 1508 : tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
734 : }
735 : else
736 : {
737 2888 : tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
738 : }
739 4396 : if ( i1 < i3 )
740 : {
741 1380 : tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
742 : }
743 : else
744 : {
745 3016 : tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
746 : }
747 4396 : cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
748 4396 : lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
749 4396 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
750 4396 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
751 4396 : tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
752 4396 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
753 4396 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
754 4396 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
755 4396 : cohwideness = cohPanCoh * lsEnergyRelation;
756 :
757 4396 : spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
758 4396 : if ( spreadCoh > 0.5f )
759 : {
760 1396 : if ( cohwideness > stereoness )
761 : {
762 444 : tempCoh = stereoness - ( cohwideness - 0.5f );
763 444 : spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
764 : }
765 : }
766 4396 : spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
767 4396 : spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
768 :
769 : /* Compute energy ratio tuning parameter */
770 4396 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
771 4396 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
772 4396 : stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
773 :
774 4396 : lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
775 4396 : cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
776 :
777 4396 : cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
778 4396 : cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
779 4396 : cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
780 : }
781 : else /* Otherwise, set spread coherence to zero */
782 : {
783 53588 : spreadCoh = 0.0f;
784 53588 : cohRatio = 0.0f;
785 53588 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
786 : }
787 :
788 : /* Store values */
789 57984 : spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
790 57984 : surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
791 57984 : coherentEnergyRatio[band_m_idx] = cohRatio;
792 : }
793 :
794 : /* Determine energy ratios */
795 60400 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
796 : {
797 57984 : if ( renormalization_factor_diff[band_m_idx] > EPSILON )
798 : {
799 57888 : diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
800 : }
801 : else
802 : {
803 96 : diffuseness_m[band_m_idx] = 0.0f;
804 : }
805 :
806 57984 : energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
807 57984 : energyRatio[block_m_idx][band_m_idx] = ( energyRatio[block_m_idx][band_m_idx] > coherentEnergyRatio[band_m_idx] ) ? energyRatio[block_m_idx][band_m_idx] : coherentEnergyRatio[band_m_idx];
808 : }
809 : }
810 :
811 604 : return;
812 : }
813 :
814 :
815 : /* Compute downmix */
816 604 : static void ivas_mcmasa_dmx(
817 : MCMASA_ANA_HANDLE hMcMasa,
818 : float data_f[][L_FRAME48k],
819 : const int16_t input_frame,
820 : const int16_t nchan_transport,
821 : const int16_t nchan_inp )
822 : {
823 : int16_t i, j;
824 : int16_t numAnalysisChannels;
825 : float dmx_c;
826 : float multiChEne, downmixEne;
827 : float prevEQ, currEQ, instEQ;
828 : float alpha;
829 :
830 604 : numAnalysisChannels = nchan_inp - 1;
831 :
832 604 : multiChEne = 0.0f;
833 7248 : for ( j = 0; j < numAnalysisChannels; j++ )
834 : {
835 6384884 : for ( i = 0; i < input_frame; i++ )
836 : {
837 6378240 : multiChEne += data_f[j][i] * data_f[j][i];
838 : }
839 : }
840 :
841 604 : if ( nchan_transport == 2 )
842 : {
843 : int16_t numSideChannels; /* Channels other than left, right, center */
844 : int16_t leftIndex, rightIndex;
845 :
846 302 : numSideChannels = numAnalysisChannels / 2 - 1;
847 1510 : for ( j = 0; j < numSideChannels; j++ )
848 : {
849 1208 : leftIndex = j * 2 + 3;
850 1208 : rightIndex = j * 2 + 4;
851 :
852 1160888 : for ( i = 0; i < input_frame; i++ )
853 : {
854 1159680 : data_f[0][i] += data_f[leftIndex][i];
855 1159680 : data_f[1][i] += data_f[rightIndex][i];
856 : }
857 : }
858 :
859 290222 : for ( i = 0; i < input_frame; i++ )
860 : {
861 289920 : dmx_c = INV_SQRT2 * data_f[2][i];
862 289920 : data_f[0][i] += dmx_c;
863 289920 : data_f[1][i] += dmx_c;
864 : }
865 : }
866 302 : else if ( nchan_transport == 1 )
867 : {
868 290222 : for ( i = 0; i < input_frame; i++ )
869 : {
870 3189120 : for ( j = 1; j < numAnalysisChannels; j++ )
871 : {
872 2899200 : data_f[0][i] += data_f[j][i];
873 : }
874 : }
875 : }
876 :
877 604 : downmixEne = 0.0f;
878 1510 : for ( j = 0; j < nchan_transport; j++ )
879 : {
880 870666 : for ( i = 0; i < input_frame; i++ )
881 : {
882 869760 : downmixEne += data_f[j][i] * data_f[j][i];
883 : }
884 : }
885 :
886 604 : alpha = 0.1f;
887 604 : hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
888 604 : hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
889 :
890 604 : prevEQ = hMcMasa->prevEQ;
891 604 : currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
892 604 : hMcMasa->prevEQ = currEQ;
893 :
894 580444 : for ( i = 0; i < input_frame; i++ )
895 : {
896 579840 : instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
897 1449600 : for ( j = 0; j < nchan_transport; j++ )
898 : {
899 869760 : data_f[j][i] *= instEQ;
900 : }
901 : }
902 :
903 604 : return;
904 : }
905 :
906 :
907 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
908 579840 : static void compute_cov_mtx(
909 : float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */
910 : float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */
911 : const int16_t freq, /* i : Freq to process */
912 : const int16_t N, /* i : Number of channels */
913 : CovarianceMatrix *COVls /* o : Output matrix, contains upper part of cov mtx */
914 : )
915 : {
916 : int16_t i, j;
917 : float a, b, c, d;
918 :
919 6958080 : for ( i = 0; i < N; i++ )
920 : {
921 6378240 : a = sr[i][freq];
922 6378240 : b = si[i][freq];
923 44647680 : for ( j = i; j < N; j++ )
924 : {
925 38269440 : c = sr[j][freq];
926 38269440 : d = si[j][freq];
927 38269440 : COVls->xr[i][j] += a * c + b * d;
928 38269440 : COVls->xi[i][j] += b * c - a * d;
929 : }
930 : }
931 :
932 579840 : return;
933 : }
934 :
935 : /*-------------------------------------------------------------------------
936 : * computeVerticalDiffuseness()
937 : *
938 : *
939 : *------------------------------------------------------------------------*/
940 :
941 9664 : static void computeVerticalDiffuseness(
942 : float **buffer_intensity, /* i : Intensity vectors */
943 : const float *buffer_energy, /* i : Energy */
944 : const int16_t num_freq_bands, /* i : Number of frequency bands */
945 : float *diffuseness /* o : Estimated diffuseness */
946 : )
947 : {
948 : float intensity_slow[MASA_FREQUENCY_BANDS];
949 : float intensity_slow_abs[MASA_FREQUENCY_BANDS];
950 : float energy_slow[MASA_FREQUENCY_BANDS];
951 : int16_t i, k;
952 9664 : float tmp = 0;
953 : const float *p_tmp_c;
954 :
955 : /* Set variables to zero */
956 9664 : set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
957 9664 : set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
958 :
959 318912 : for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
960 : {
961 : /* Energy slow */
962 309248 : p_tmp_c = buffer_energy + i * num_freq_bands;
963 7731200 : for ( k = 0; k < num_freq_bands; k++ )
964 : {
965 7421952 : energy_slow[k] += *( p_tmp_c++ );
966 : }
967 :
968 : /* Intensity slow */
969 7731200 : for ( k = 0; k < num_freq_bands; k++ )
970 : {
971 7421952 : intensity_slow[k] += buffer_intensity[i][k];
972 : }
973 : }
974 :
975 : /* Compute absolute value */
976 241600 : for ( k = 0; k < num_freq_bands; k++ )
977 : {
978 231936 : intensity_slow_abs[k] = fabsf( intensity_slow[k] );
979 : }
980 :
981 : /* Compute Diffuseness */
982 241600 : for ( i = 0; i < num_freq_bands; ++i )
983 : {
984 231936 : tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
985 231936 : tmp = ( tmp - VERTICAL_ENERGY_RATIO_OFFSET ) / ( 1.0f - VERTICAL_ENERGY_RATIO_OFFSET ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
986 231936 : tmp = 1.0f - tmp;
987 231936 : diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
988 : }
989 :
990 9664 : return;
991 : }
992 :
993 :
994 8 : static void computeEvenLayout(
995 : const float *ls_azimuth,
996 : float *ls_azimuth_even,
997 : const int16_t numChannels )
998 : {
999 : int16_t i;
1000 : int16_t j;
1001 : float ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
1002 : float ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
1003 : int16_t ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
1004 : float smallestAzimuth;
1005 : int16_t smallestAzimuthIndex;
1006 : float lsSpacing;
1007 : uint8_t oddLayout;
1008 : float startAzimuth;
1009 : int16_t numChannelsHalf;
1010 :
1011 8 : lsSpacing = 360.0f / (float) numChannels;
1012 8 : oddLayout = numChannels % 2;
1013 8 : numChannelsHalf = numChannels / 2;
1014 :
1015 8 : mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
1016 52 : for ( i = 0; i < numChannels; i++ )
1017 : {
1018 44 : smallestAzimuth = 1000.0f;
1019 44 : smallestAzimuthIndex = 0;
1020 304 : for ( j = 0; j < numChannels; j++ )
1021 : {
1022 260 : if ( ls_azimuth_temp[j] < smallestAzimuth )
1023 : {
1024 84 : smallestAzimuth = ls_azimuth_temp[j];
1025 84 : smallestAzimuthIndex = j;
1026 : }
1027 : }
1028 44 : ls_azimuth_order[i] = smallestAzimuthIndex;
1029 44 : ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
1030 : }
1031 :
1032 8 : if ( oddLayout )
1033 : {
1034 4 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
1035 : }
1036 : else
1037 : {
1038 4 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
1039 : }
1040 :
1041 52 : for ( i = 0; i < numChannels; i++ )
1042 : {
1043 44 : ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
1044 : }
1045 :
1046 52 : for ( i = 0; i < numChannels; i++ )
1047 : {
1048 44 : ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
1049 : }
1050 :
1051 8 : return;
1052 : }
1053 :
1054 :
1055 : /*-------------------------------------------------------------------------
1056 : * ivas_create_masa_out_meta()
1057 : *
1058 : *
1059 : *------------------------------------------------------------------------*/
1060 :
1061 9044 : void ivas_create_masa_out_meta(
1062 : MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */
1063 : SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */
1064 : const int16_t nchan_transport, /* i : Number of transport channels */
1065 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation */
1066 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth */
1067 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */
1068 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */
1069 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i : Estimated surround coherence */
1070 : )
1071 : {
1072 : int16_t i, sf, band;
1073 : uint8_t numFrequencyBands;
1074 : uint8_t numDirections;
1075 : uint16_t spherical_index;
1076 :
1077 9044 : numDirections = 1;
1078 9044 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1079 :
1080 : /* Construct descriptive meta */
1081 81396 : for ( i = 0; i < 8; i++ )
1082 : {
1083 72352 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1084 : }
1085 9044 : extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
1086 9044 : extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
1087 : /* Following correspond to "unknown" values */
1088 9044 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1089 9044 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1090 9044 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1091 9044 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1092 9044 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1093 :
1094 : /* Construct spatial metadata from estimated values */
1095 45220 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1096 : {
1097 : /* Spherical index */
1098 904400 : for ( band = 0; band < numFrequencyBands; band++ )
1099 : {
1100 868224 : spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1101 868224 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1102 868224 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1103 : }
1104 :
1105 : /* Direct-to-total ratio */
1106 904400 : for ( band = 0; band < numFrequencyBands; band++ )
1107 : {
1108 868224 : extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1109 868224 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1110 : }
1111 :
1112 : /* Spread coherence */
1113 904400 : for ( band = 0; band < numFrequencyBands; band++ )
1114 : {
1115 868224 : extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
1116 868224 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1117 : }
1118 :
1119 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1120 904400 : for ( band = 0; band < numFrequencyBands; band++ )
1121 : {
1122 868224 : extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1123 : }
1124 :
1125 : /* Surround coherence */
1126 904400 : for ( band = 0; band < numFrequencyBands; band++ )
1127 : {
1128 868224 : extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
1129 : }
1130 : }
1131 :
1132 9044 : return;
1133 : }
|