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 2 : 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 2 : error = IVAS_ERR_OK;
103 :
104 2 : 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 2 : 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 2 : 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 2 : 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 2 : 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 2 : nchan_inp = 12;
144 2 : mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
145 2 : mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
146 2 : hMcMasa->numHorizontalChannels = 7;
147 2 : hMcMasa->isHorizontalSetup = 0;
148 : }
149 :
150 2 : numAnalysisChannels = nchan_inp - 1;
151 :
152 : /* Determine the number of bands */
153 2 : hMcMasa->nbands = MASA_FREQUENCY_BANDS;
154 :
155 : /* Determine band grouping */
156 2 : mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
157 :
158 2 : maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
159 48 : for ( i = 1; i < hMcMasa->nbands + 1; i++ )
160 : {
161 48 : if ( hMcMasa->band_grouping[i] >= maxBin )
162 : {
163 2 : hMcMasa->band_grouping[i] = maxBin;
164 2 : hMcMasa->nbands = i;
165 2 : break;
166 : }
167 : }
168 :
169 : /* Determine block grouping */
170 2 : mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
171 :
172 : /* open/initialize CLDFB */
173 2 : hMcMasa->num_Cldfb_instances = numAnalysisChannels;
174 24 : for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
175 : {
176 22 : 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 8 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
184 : {
185 6 : 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 30 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
191 : {
192 24 : 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 24 : set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
197 : }
198 : }
199 :
200 8 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
201 : {
202 198 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
203 : {
204 192 : 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 192 : set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
209 : }
210 : }
211 :
212 66 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
213 : {
214 64 : 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 64 : set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
219 : }
220 :
221 2 : set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
222 :
223 2 : computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
224 :
225 2 : if ( !hMcMasa->isHorizontalSetup )
226 : {
227 2 : computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
228 : }
229 :
230 24 : for ( i = 0; i < numAnalysisChannels; i++ )
231 : {
232 22 : hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
233 22 : hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
234 22 : hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
235 22 : hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
236 :
237 22 : hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
238 22 : hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
239 22 : hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
240 22 : hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
241 : }
242 :
243 2 : mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
244 :
245 16 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
246 : {
247 14 : left_min = 360.0f;
248 14 : right_min = -360.0f;
249 :
250 112 : for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
251 : {
252 98 : azi_diff = ls_azimuth[j] - ls_azimuth[i];
253 :
254 98 : if ( azi_diff > 180.0f )
255 : {
256 6 : azi_diff -= 360.0f;
257 : }
258 92 : else if ( azi_diff < -180.0f )
259 : {
260 6 : azi_diff += 360.0f;
261 : }
262 :
263 98 : if ( azi_diff < left_min && azi_diff > 0.0f )
264 : {
265 24 : hMcMasa->leftNearest[i] = j;
266 24 : left_min = azi_diff;
267 : }
268 :
269 98 : if ( azi_diff > right_min && azi_diff < 0.0f )
270 : {
271 22 : hMcMasa->rightNearest[i] = j;
272 22 : right_min = azi_diff;
273 : }
274 : }
275 : }
276 :
277 2 : hMcMasa->prevMultiChEne = 0.0f;
278 2 : hMcMasa->prevDownmixEne = 0.0f;
279 2 : hMcMasa->prevEQ = 1.0f;
280 2 : input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
281 1922 : for ( i = 0; i < input_frame; i++ )
282 : {
283 1920 : hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
284 : }
285 :
286 2 : hMcMasa->index_buffer_intensity = 0;
287 :
288 2 : 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 2 : 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 2 : generate_gridEq( hMcMasa->sph_grid16 );
298 :
299 2 : ( *hMcMasaPtr ) = hMcMasa;
300 :
301 2 : return error;
302 : }
303 :
304 :
305 : /*--------------------------------------------------------------------------*
306 : * ivas_mcmasa_ana_close()
307 : *
308 : *
309 : *--------------------------------------------------------------------------*/
310 :
311 1316 : void ivas_mcmasa_ana_close(
312 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
313 : )
314 : {
315 : int16_t i, j;
316 :
317 1316 : if ( hMcMasa == NULL || *hMcMasa == NULL )
318 : {
319 1314 : return;
320 : }
321 :
322 24 : for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
323 : {
324 22 : deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
325 : }
326 :
327 : /* intensity 3-dim */
328 8 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
329 : {
330 30 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
331 : {
332 24 : free( ( *hMcMasa )->direction_vector_m[i][j] );
333 24 : ( *hMcMasa )->direction_vector_m[i][j] = NULL;
334 : }
335 :
336 198 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
337 : {
338 192 : free( ( *hMcMasa )->buffer_intensity_real[i][j] );
339 192 : ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
340 : }
341 :
342 6 : free( ( *hMcMasa )->direction_vector_m[i] );
343 6 : ( *hMcMasa )->direction_vector_m[i] = NULL;
344 : }
345 :
346 66 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
347 : {
348 64 : free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
349 64 : ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
350 : }
351 :
352 2 : free( ( *hMcMasa )->hMasaOut );
353 2 : ( *hMcMasa )->hMasaOut = NULL;
354 2 : free( ( *hMcMasa )->sph_grid16 );
355 2 : ( *hMcMasa )->sph_grid16 = NULL;
356 :
357 2 : free( ( *hMcMasa ) );
358 2 : ( *hMcMasa ) = NULL;
359 :
360 2 : return;
361 : }
362 :
363 :
364 : /*--------------------------------------------------------------------------*
365 : * ivas_mcmasa_ana()
366 : *
367 : * Multichannel MASA analysis
368 : *--------------------------------------------------------------------------*/
369 :
370 300 : 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 300 : v_add( data_f[2], data_f[3], data_f[2], input_frame );
388 2700 : for ( i = 4; i < nchan_inp; i++ )
389 : {
390 2400 : mvr2r( data_f[i], data_f[i - 1], input_frame );
391 : }
392 :
393 : /* Analysis */
394 300 : 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 300 : 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 300 : ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
401 :
402 300 : return;
403 : }
404 :
405 :
406 : /*--------------------------------------------------------------------------*
407 : * Local functions
408 : *--------------------------------------------------------------------------*/
409 :
410 : /* Estimate metadata parameters for McMASA */
411 300 : 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 300 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
462 300 : num_freq_bands = hMcMasa->nbands;
463 300 : l_ts = input_frame / CLDFB_NO_COL_MAX;
464 300 : numAnalysisChannels = nchan_inp - 1;
465 :
466 : /* do processing over all CLDFB time slots */
467 1500 : for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
468 : {
469 1200 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
470 1200 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
471 :
472 30000 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
473 : {
474 28800 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
475 28800 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
476 28800 : 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 1200 : set_zero( renormalization_factor_diff, hMcMasa->nbands );
481 1200 : set_zero( diffuseness_m, hMcMasa->nbands );
482 1200 : set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
483 :
484 : /* Reset variable */
485 30000 : for ( i = 0; i < hMcMasa->nbands; i++ )
486 : {
487 345600 : for ( j = 0; j < numAnalysisChannels; j++ )
488 : {
489 316800 : set_zero( COVls[i].xr[j], numAnalysisChannels );
490 316800 : set_zero( COVls[i].xi[j], numAnalysisChannels );
491 : }
492 : }
493 :
494 6000 : for ( ts = mrange[0]; ts < mrange[1]; ts++ )
495 : {
496 57600 : for ( i = 0; i < numAnalysisChannels; i++ )
497 : {
498 52800 : 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 120000 : for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
503 : {
504 115200 : brange[0] = hMcMasa->band_grouping[band_m_idx];
505 115200 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
506 403200 : for ( j = brange[0]; j < brange[1]; j++ )
507 : {
508 3456000 : for ( i = 0; i < numAnalysisChannels; i++ )
509 : {
510 3168000 : 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 120000 : for ( i = 0; i < num_freq_bands; i++ )
517 : {
518 115200 : brange[0] = hMcMasa->band_grouping[i];
519 115200 : brange[1] = hMcMasa->band_grouping[i + 1];
520 403200 : for ( j = brange[0]; j < brange[1]; j++ )
521 : {
522 288000 : compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
523 : }
524 : }
525 :
526 : /* Compute standard FOA */
527 : /* W */
528 4800 : v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
529 4800 : v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
530 48000 : for ( i = 2; i < numAnalysisChannels; i++ )
531 : {
532 43200 : v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
533 43200 : v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
534 : }
535 :
536 : /* Y */
537 4800 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
538 4800 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
539 52800 : for ( i = 1; i < numAnalysisChannels; i++ )
540 : {
541 48000 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
542 48000 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
543 : }
544 :
545 : /* Z */
546 4800 : 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 4800 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
555 4800 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
556 52800 : for ( i = 1; i < numAnalysisChannels; i++ )
557 : {
558 48000 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
559 48000 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
560 : }
561 : }
562 :
563 : /* X */
564 4800 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
565 4800 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
566 52800 : for ( i = 1; i < numAnalysisChannels; i++ )
567 : {
568 48000 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
569 48000 : 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 4800 : mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
575 4800 : mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
576 :
577 : /* Y */
578 4800 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
579 4800 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
580 52800 : for ( i = 1; i < numAnalysisChannels; i++ )
581 : {
582 48000 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
583 48000 : 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 4800 : set_zero( FoaEven_RealBuffer[2], num_freq_bins );
588 4800 : set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
589 :
590 : /* X */
591 4800 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
592 4800 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
593 52800 : for ( i = 1; i < numAnalysisChannels; i++ )
594 : {
595 48000 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
596 48000 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
597 : }
598 :
599 : /* Direction estimation */
600 4800 : computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
601 4800 : 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 4800 : computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
605 4800 : 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 4800 : hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
609 4800 : index = hMcMasa->index_buffer_intensity;
610 19200 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
611 : {
612 : /* only real part needed */
613 14400 : mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
614 : }
615 4800 : mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
616 :
617 4800 : 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 4800 : if ( !hMcMasa->isHorizontalSetup )
621 : {
622 4800 : mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
623 4800 : computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
624 4800 : v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
625 : }
626 :
627 120000 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
628 : {
629 115200 : norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
630 :
631 115200 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
632 115200 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
633 115200 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
634 :
635 115200 : diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
636 115200 : renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
637 : }
638 : }
639 :
640 30000 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
641 : {
642 115200 : for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
643 : {
644 86400 : dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
645 : }
646 28800 : 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 30000 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
651 : {
652 : /* Compute absolute values */
653 345600 : for ( i = 0; i < numAnalysisChannels; i++ )
654 : {
655 2217600 : for ( j = i; j < numAnalysisChannels; j++ )
656 : {
657 1900800 : 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 316800 : lsEnergy[i] = absCOVls[i][i];
660 : }
661 :
662 : /* Find loudest channel */
663 28800 : maxEne = lsEnergy[0];
664 28800 : loudestCh = 0;
665 316800 : for ( i = 1; i < numAnalysisChannels; i++ )
666 : {
667 288000 : if ( lsEnergy[i] > maxEne )
668 : {
669 54980 : maxEne = lsEnergy[i];
670 54980 : loudestCh = i;
671 : }
672 : }
673 :
674 : /* Compute surrounding coherence */
675 28800 : surrCoh = 1.0f;
676 345600 : for ( i = 0; i < numAnalysisChannels; i++ )
677 : {
678 316800 : if ( i != loudestCh )
679 : {
680 288000 : if ( i < loudestCh )
681 : {
682 175770 : i1 = i;
683 175770 : i2 = loudestCh;
684 : }
685 : else
686 : {
687 112230 : i1 = loudestCh;
688 112230 : i2 = i;
689 : }
690 288000 : tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
691 288000 : surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
692 : }
693 : }
694 28800 : surrCoh = surrCoh * surrCoh;
695 28800 : surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
696 28800 : surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
697 :
698 : /* Compute spread coherence */
699 28800 : if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
700 : {
701 2130 : minAngleDist = 180.0f;
702 2130 : i1 = 0;
703 2130 : currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
704 17040 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
705 : {
706 14910 : angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
707 14910 : if ( angleDist > 180.0f )
708 : {
709 384 : angleDist = fabsf( angleDist - 360.0f );
710 : }
711 14910 : if ( angleDist < minAngleDist )
712 : {
713 4768 : minAngleDist = angleDist;
714 4768 : i1 = i;
715 : }
716 : }
717 2130 : i2 = hMcMasa->leftNearest[i1];
718 2130 : i3 = hMcMasa->rightNearest[i1];
719 :
720 2130 : if ( i2 < i3 )
721 : {
722 1688 : stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
723 : }
724 : else
725 : {
726 442 : stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
727 : }
728 2130 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
729 2130 : stereoness = stereoCoh * lsEnergyRelation;
730 :
731 2130 : if ( i1 < i2 )
732 : {
733 744 : tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
734 : }
735 : else
736 : {
737 1386 : tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
738 : }
739 2130 : if ( i1 < i3 )
740 : {
741 680 : tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
742 : }
743 : else
744 : {
745 1450 : tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
746 : }
747 2130 : cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
748 2130 : lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
749 2130 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
750 2130 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
751 2130 : tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
752 2130 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
753 2130 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
754 2130 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
755 2130 : cohwideness = cohPanCoh * lsEnergyRelation;
756 :
757 2130 : spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
758 2130 : if ( spreadCoh > 0.5f )
759 : {
760 688 : if ( cohwideness > stereoness )
761 : {
762 218 : tempCoh = stereoness - ( cohwideness - 0.5f );
763 218 : spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
764 : }
765 : }
766 2130 : spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
767 2130 : spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
768 :
769 : /* Compute energy ratio tuning parameter */
770 2130 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
771 2130 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
772 2130 : stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
773 :
774 2130 : lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
775 2130 : cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
776 :
777 2130 : cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
778 2130 : cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
779 2130 : cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
780 : }
781 : else /* Otherwise, set spread coherence to zero */
782 : {
783 26670 : spreadCoh = 0.0f;
784 26670 : cohRatio = 0.0f;
785 26670 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
786 : }
787 :
788 : /* Store values */
789 28800 : spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
790 28800 : surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
791 28800 : coherentEnergyRatio[band_m_idx] = cohRatio;
792 : }
793 :
794 : /* Determine energy ratios */
795 30000 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
796 : {
797 28800 : if ( renormalization_factor_diff[band_m_idx] > EPSILON )
798 : {
799 28800 : diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
800 : }
801 : else
802 : {
803 0 : diffuseness_m[band_m_idx] = 0.0f;
804 : }
805 :
806 28800 : energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
807 28800 : 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 300 : return;
812 : }
813 :
814 :
815 : /* Compute downmix */
816 300 : 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 300 : numAnalysisChannels = nchan_inp - 1;
831 :
832 300 : multiChEne = 0.0f;
833 3600 : for ( j = 0; j < numAnalysisChannels; j++ )
834 : {
835 3171300 : for ( i = 0; i < input_frame; i++ )
836 : {
837 3168000 : multiChEne += data_f[j][i] * data_f[j][i];
838 : }
839 : }
840 :
841 300 : if ( nchan_transport == 2 )
842 : {
843 : int16_t numSideChannels; /* Channels other than left, right, center */
844 : int16_t leftIndex, rightIndex;
845 :
846 300 : numSideChannels = numAnalysisChannels / 2 - 1;
847 1500 : for ( j = 0; j < numSideChannels; j++ )
848 : {
849 1200 : leftIndex = j * 2 + 3;
850 1200 : rightIndex = j * 2 + 4;
851 :
852 1153200 : for ( i = 0; i < input_frame; i++ )
853 : {
854 1152000 : data_f[0][i] += data_f[leftIndex][i];
855 1152000 : data_f[1][i] += data_f[rightIndex][i];
856 : }
857 : }
858 :
859 288300 : for ( i = 0; i < input_frame; i++ )
860 : {
861 288000 : dmx_c = INV_SQRT2 * data_f[2][i];
862 288000 : data_f[0][i] += dmx_c;
863 288000 : data_f[1][i] += dmx_c;
864 : }
865 : }
866 0 : else if ( nchan_transport == 1 )
867 : {
868 0 : for ( i = 0; i < input_frame; i++ )
869 : {
870 0 : for ( j = 1; j < numAnalysisChannels; j++ )
871 : {
872 0 : data_f[0][i] += data_f[j][i];
873 : }
874 : }
875 : }
876 :
877 300 : downmixEne = 0.0f;
878 900 : for ( j = 0; j < nchan_transport; j++ )
879 : {
880 576600 : for ( i = 0; i < input_frame; i++ )
881 : {
882 576000 : downmixEne += data_f[j][i] * data_f[j][i];
883 : }
884 : }
885 :
886 300 : alpha = 0.1f;
887 300 : hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
888 300 : hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
889 :
890 300 : prevEQ = hMcMasa->prevEQ;
891 300 : currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
892 300 : hMcMasa->prevEQ = currEQ;
893 :
894 288300 : for ( i = 0; i < input_frame; i++ )
895 : {
896 288000 : instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
897 864000 : for ( j = 0; j < nchan_transport; j++ )
898 : {
899 576000 : data_f[j][i] *= instEQ;
900 : }
901 : }
902 :
903 300 : return;
904 : }
905 :
906 :
907 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
908 288000 : 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 3456000 : for ( i = 0; i < N; i++ )
920 : {
921 3168000 : a = sr[i][freq];
922 3168000 : b = si[i][freq];
923 22176000 : for ( j = i; j < N; j++ )
924 : {
925 19008000 : c = sr[j][freq];
926 19008000 : d = si[j][freq];
927 19008000 : COVls->xr[i][j] += a * c + b * d;
928 19008000 : COVls->xi[i][j] += b * c - a * d;
929 : }
930 : }
931 :
932 288000 : return;
933 : }
934 :
935 : /*-------------------------------------------------------------------------
936 : * computeVerticalDiffuseness()
937 : *
938 : *
939 : *------------------------------------------------------------------------*/
940 :
941 4800 : 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 4800 : float tmp = 0;
953 : const float *p_tmp_c;
954 :
955 : /* Set variables to zero */
956 4800 : set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
957 4800 : set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
958 :
959 158400 : for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
960 : {
961 : /* Energy slow */
962 153600 : p_tmp_c = buffer_energy + i * num_freq_bands;
963 3840000 : for ( k = 0; k < num_freq_bands; k++ )
964 : {
965 3686400 : energy_slow[k] += *( p_tmp_c++ );
966 : }
967 :
968 : /* Intensity slow */
969 3840000 : for ( k = 0; k < num_freq_bands; k++ )
970 : {
971 3686400 : intensity_slow[k] += buffer_intensity[i][k];
972 : }
973 : }
974 :
975 : /* Compute absolute value */
976 120000 : for ( k = 0; k < num_freq_bands; k++ )
977 : {
978 115200 : intensity_slow_abs[k] = fabsf( intensity_slow[k] );
979 : }
980 :
981 : /* Compute Diffuseness */
982 120000 : for ( i = 0; i < num_freq_bands; ++i )
983 : {
984 115200 : tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
985 115200 : 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 115200 : tmp = 1.0f - tmp;
987 115200 : diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
988 : }
989 :
990 4800 : return;
991 : }
992 :
993 :
994 4 : 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 4 : lsSpacing = 360.0f / (float) numChannels;
1012 4 : oddLayout = numChannels % 2;
1013 4 : numChannelsHalf = numChannels / 2;
1014 :
1015 4 : mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
1016 26 : for ( i = 0; i < numChannels; i++ )
1017 : {
1018 22 : smallestAzimuth = 1000.0f;
1019 22 : smallestAzimuthIndex = 0;
1020 152 : for ( j = 0; j < numChannels; j++ )
1021 : {
1022 130 : if ( ls_azimuth_temp[j] < smallestAzimuth )
1023 : {
1024 42 : smallestAzimuth = ls_azimuth_temp[j];
1025 42 : smallestAzimuthIndex = j;
1026 : }
1027 : }
1028 22 : ls_azimuth_order[i] = smallestAzimuthIndex;
1029 22 : ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
1030 : }
1031 :
1032 4 : if ( oddLayout )
1033 : {
1034 2 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
1035 : }
1036 : else
1037 : {
1038 2 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
1039 : }
1040 :
1041 26 : for ( i = 0; i < numChannels; i++ )
1042 : {
1043 22 : ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
1044 : }
1045 :
1046 26 : for ( i = 0; i < numChannels; i++ )
1047 : {
1048 22 : ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
1049 : }
1050 :
1051 4 : return;
1052 : }
1053 :
1054 :
1055 : /*-------------------------------------------------------------------------
1056 : * ivas_create_masa_out_meta()
1057 : *
1058 : *
1059 : *------------------------------------------------------------------------*/
1060 :
1061 900 : 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 900 : numDirections = 1;
1078 900 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1079 :
1080 : /* Construct descriptive meta */
1081 8100 : for ( i = 0; i < 8; i++ )
1082 : {
1083 7200 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1084 : }
1085 900 : extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
1086 900 : extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
1087 : /* Following correspond to "unknown" values */
1088 900 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1089 900 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1090 900 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1091 900 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1092 900 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1093 :
1094 : /* Construct spatial metadata from estimated values */
1095 4500 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1096 : {
1097 : /* Spherical index */
1098 90000 : for ( band = 0; band < numFrequencyBands; band++ )
1099 : {
1100 86400 : spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1101 86400 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1102 86400 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1103 : }
1104 :
1105 : /* Direct-to-total ratio */
1106 90000 : for ( band = 0; band < numFrequencyBands; band++ )
1107 : {
1108 86400 : extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1109 86400 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1110 : }
1111 :
1112 : /* Spread coherence */
1113 90000 : for ( band = 0; band < numFrequencyBands; band++ )
1114 : {
1115 86400 : extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
1116 86400 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1117 : }
1118 :
1119 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1120 90000 : for ( band = 0; band < numFrequencyBands; band++ )
1121 : {
1122 86400 : extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1123 : }
1124 :
1125 : /* Surround coherence */
1126 90000 : for ( band = 0; band < numFrequencyBands; band++ )
1127 : {
1128 86400 : extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
1129 : }
1130 : }
1131 :
1132 900 : return;
1133 : }
|