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 6 : 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 6 : error = IVAS_ERR_OK;
103 :
104 6 : 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 6 : 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 6 : 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 6 : 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 6 : 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 6 : nchan_inp = 12;
144 6 : mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
145 6 : mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
146 6 : hMcMasa->numHorizontalChannels = 7;
147 6 : hMcMasa->isHorizontalSetup = 0;
148 : }
149 :
150 6 : numAnalysisChannels = nchan_inp - 1;
151 :
152 : /* Determine the number of bands */
153 6 : hMcMasa->nbands = MASA_FREQUENCY_BANDS;
154 :
155 : /* Determine band grouping */
156 6 : mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
157 :
158 6 : maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
159 134 : for ( i = 1; i < hMcMasa->nbands + 1; i++ )
160 : {
161 134 : if ( hMcMasa->band_grouping[i] >= maxBin )
162 : {
163 6 : hMcMasa->band_grouping[i] = maxBin;
164 6 : hMcMasa->nbands = i;
165 6 : break;
166 : }
167 : }
168 :
169 : /* Determine block grouping */
170 6 : mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
171 :
172 : /* open/initialize CLDFB */
173 6 : hMcMasa->num_Cldfb_instances = numAnalysisChannels;
174 72 : for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
175 : {
176 66 : 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 24 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
184 : {
185 18 : 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 90 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
191 : {
192 72 : 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 72 : set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
197 : }
198 : }
199 :
200 24 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
201 : {
202 594 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
203 : {
204 576 : 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 576 : set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
209 : }
210 : }
211 :
212 198 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
213 : {
214 192 : 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 192 : set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
219 : }
220 :
221 6 : set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
222 :
223 6 : computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
224 :
225 6 : if ( !hMcMasa->isHorizontalSetup )
226 : {
227 6 : computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
228 : }
229 :
230 72 : for ( i = 0; i < numAnalysisChannels; i++ )
231 : {
232 66 : hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
233 66 : hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
234 66 : hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
235 66 : hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
236 :
237 66 : hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
238 66 : hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
239 66 : hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
240 66 : hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
241 : }
242 :
243 6 : mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
244 :
245 48 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
246 : {
247 42 : left_min = 360.0f;
248 42 : right_min = -360.0f;
249 :
250 336 : for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
251 : {
252 294 : azi_diff = ls_azimuth[j] - ls_azimuth[i];
253 :
254 294 : if ( azi_diff > 180.0f )
255 : {
256 18 : azi_diff -= 360.0f;
257 : }
258 276 : else if ( azi_diff < -180.0f )
259 : {
260 18 : azi_diff += 360.0f;
261 : }
262 :
263 294 : if ( azi_diff < left_min && azi_diff > 0.0f )
264 : {
265 72 : hMcMasa->leftNearest[i] = j;
266 72 : left_min = azi_diff;
267 : }
268 :
269 294 : if ( azi_diff > right_min && azi_diff < 0.0f )
270 : {
271 66 : hMcMasa->rightNearest[i] = j;
272 66 : right_min = azi_diff;
273 : }
274 : }
275 : }
276 :
277 6 : hMcMasa->prevMultiChEne = 0.0f;
278 6 : hMcMasa->prevDownmixEne = 0.0f;
279 6 : hMcMasa->prevEQ = 1.0f;
280 6 : input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
281 3846 : for ( i = 0; i < input_frame; i++ )
282 : {
283 3840 : hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
284 : }
285 :
286 6 : hMcMasa->index_buffer_intensity = 0;
287 :
288 6 : 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 6 : 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 6 : generate_gridEq( hMcMasa->sph_grid16 );
298 :
299 6 : ( *hMcMasaPtr ) = hMcMasa;
300 :
301 6 : return error;
302 : }
303 :
304 :
305 : /*--------------------------------------------------------------------------*
306 : * ivas_mcmasa_ana_close()
307 : *
308 : *
309 : *--------------------------------------------------------------------------*/
310 :
311 4407 : void ivas_mcmasa_ana_close(
312 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
313 : )
314 : {
315 : int16_t i, j;
316 :
317 4407 : if ( hMcMasa == NULL || *hMcMasa == NULL )
318 : {
319 4401 : return;
320 : }
321 :
322 72 : for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
323 : {
324 66 : deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
325 : }
326 :
327 : /* intensity 3-dim */
328 24 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
329 : {
330 90 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
331 : {
332 72 : free( ( *hMcMasa )->direction_vector_m[i][j] );
333 72 : ( *hMcMasa )->direction_vector_m[i][j] = NULL;
334 : }
335 :
336 594 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
337 : {
338 576 : free( ( *hMcMasa )->buffer_intensity_real[i][j] );
339 576 : ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
340 : }
341 :
342 18 : free( ( *hMcMasa )->direction_vector_m[i] );
343 18 : ( *hMcMasa )->direction_vector_m[i] = NULL;
344 : }
345 :
346 198 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
347 : {
348 192 : free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
349 192 : ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
350 : }
351 :
352 6 : free( ( *hMcMasa )->hMasaOut );
353 6 : ( *hMcMasa )->hMasaOut = NULL;
354 6 : free( ( *hMcMasa )->sph_grid16 );
355 6 : ( *hMcMasa )->sph_grid16 = NULL;
356 :
357 6 : free( ( *hMcMasa ) );
358 6 : ( *hMcMasa ) = NULL;
359 :
360 6 : return;
361 : }
362 :
363 :
364 : /*--------------------------------------------------------------------------*
365 : * ivas_mcmasa_ana()
366 : *
367 : * Multichannel MASA analysis
368 : *--------------------------------------------------------------------------*/
369 :
370 906 : 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 906 : v_add( data_f[2], data_f[3], data_f[2], input_frame );
388 8154 : for ( i = 4; i < nchan_inp; i++ )
389 : {
390 7248 : mvr2r( data_f[i], data_f[i - 1], input_frame );
391 : }
392 :
393 : /* Analysis */
394 906 : ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp );
395 :
396 : /* Add zeros to higher bands in case of lower sampling rates */
397 906 : if ( hMcMasa->nbands < MASA_FREQUENCY_BANDS )
398 : {
399 604 : ivas_masa_zero_high_bands( hMcMasa->nbands, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
400 : }
401 :
402 : /* Create MASA metadata buffer from the estimated values */
403 906 : ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
404 :
405 : /* Downmix */
406 906 : ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
407 :
408 906 : return;
409 : }
410 :
411 :
412 : /*--------------------------------------------------------------------------*
413 : * Local functions
414 : *--------------------------------------------------------------------------*/
415 :
416 : /* Estimate metadata parameters for McMASA */
417 906 : void ivas_mcmasa_param_est_ana(
418 : MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */
419 : float data_f[][L_FRAME48k], /* i : Audio frame in MC-format */
420 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */
421 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */
422 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */
423 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */
424 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */
425 : const int16_t input_frame, /* i : Input frame size */
426 : const int16_t nchan_inp /* i : Number of input channels */
427 : )
428 : {
429 : float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
430 : int16_t ts, i, j, d;
431 : int16_t num_freq_bins, num_freq_bands, index;
432 : float dir_v[DIRAC_NUM_DIMS];
433 : int16_t l_ts;
434 : float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
435 : float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
436 : float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
437 : float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
438 : float FoaEven_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
439 : float FoaEven_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
440 : float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
441 : float intensity_even_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
442 : float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
443 : float diffuseness_vector[MASA_FREQUENCY_BANDS];
444 : float vertical_diffuseness_vector[MASA_FREQUENCY_BANDS];
445 : float diffuseness_m[MASA_FREQUENCY_BANDS];
446 : float coherentEnergyRatio[MASA_FREQUENCY_BANDS];
447 : int16_t band_m_idx, block_m_idx;
448 : float renormalization_factor_diff[MASA_FREQUENCY_BANDS];
449 : float norm_tmp;
450 : int16_t mrange[2], brange[2];
451 : CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
452 : float absCOVls[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
453 : float lsEnergy[MCMASA_MAX_ANA_CHANS];
454 : float lsEnergySum, maxEne;
455 : int16_t loudestCh;
456 : float surrCoh, tempCoh, tempCoh2;
457 : int16_t i1, i2, i3;
458 : float angleDist, minAngleDist;
459 : float currentAzi;
460 : float lsEnergyRelation;
461 : float tempLsEnergyRelation;
462 : float stereoness, cohwideness, spreadCoh;
463 : float stereoRatio, cohPanRatio;
464 : float stereoCoh, cohPanCoh, cohRatio;
465 : int16_t numAnalysisChannels;
466 :
467 906 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
468 906 : num_freq_bands = hMcMasa->nbands;
469 906 : l_ts = input_frame / CLDFB_NO_COL_MAX;
470 906 : numAnalysisChannels = nchan_inp - 1;
471 :
472 : /* do processing over all CLDFB time slots */
473 4530 : for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
474 : {
475 3624 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
476 3624 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
477 :
478 84560 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
479 : {
480 80936 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
481 80936 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
482 80936 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0;
483 : }
484 :
485 : /* Need to initialize renormalization_factors, and variables to be normalized */
486 3624 : set_zero( renormalization_factor_diff, hMcMasa->nbands );
487 3624 : set_zero( diffuseness_m, hMcMasa->nbands );
488 3624 : set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
489 :
490 : /* Reset variable */
491 84560 : for ( i = 0; i < hMcMasa->nbands; i++ )
492 : {
493 971232 : for ( j = 0; j < numAnalysisChannels; j++ )
494 : {
495 890296 : set_zero( COVls[i].xr[j], numAnalysisChannels );
496 890296 : set_zero( COVls[i].xi[j], numAnalysisChannels );
497 : }
498 : }
499 :
500 18120 : for ( ts = mrange[0]; ts < mrange[1]; ts++ )
501 : {
502 173952 : for ( i = 0; i < numAnalysisChannels; i++ )
503 : {
504 159456 : cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hMcMasa->cldfbAnaEnc[i] );
505 : }
506 :
507 : /* Compute channel-based energy for metadata processing */
508 338240 : for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
509 : {
510 323744 : brange[0] = hMcMasa->band_grouping[band_m_idx];
511 323744 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
512 903584 : for ( j = brange[0]; j < brange[1]; j++ )
513 : {
514 6958080 : for ( i = 0; i < numAnalysisChannels; i++ )
515 : {
516 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];
517 : }
518 : }
519 : }
520 :
521 : /* Compute covariance matrix */
522 338240 : for ( i = 0; i < num_freq_bands; i++ )
523 : {
524 323744 : brange[0] = hMcMasa->band_grouping[i];
525 323744 : brange[1] = hMcMasa->band_grouping[i + 1];
526 903584 : for ( j = brange[0]; j < brange[1]; j++ )
527 : {
528 579840 : compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
529 : }
530 : }
531 :
532 : /* Compute standard FOA */
533 : /* W */
534 14496 : v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
535 14496 : v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
536 144960 : for ( i = 2; i < numAnalysisChannels; i++ )
537 : {
538 130464 : v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
539 130464 : v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
540 : }
541 :
542 : /* Y */
543 14496 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
544 14496 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
545 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
546 : {
547 144960 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
548 144960 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
549 : }
550 :
551 : /* Z */
552 14496 : if ( hMcMasa->isHorizontalSetup )
553 : {
554 : /* Set zero for horizontal setups */
555 0 : set_zero( Foa_RealBuffer[2], num_freq_bins );
556 0 : set_zero( Foa_ImagBuffer[2], num_freq_bins );
557 : }
558 : else
559 : {
560 14496 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
561 14496 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
562 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
563 : {
564 144960 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
565 144960 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
566 : }
567 : }
568 :
569 : /* X */
570 14496 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
571 14496 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
572 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
573 : {
574 144960 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
575 144960 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins );
576 : }
577 :
578 : /* Compute even FOA */
579 : /* W */
580 14496 : mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
581 14496 : mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
582 :
583 : /* Y */
584 14496 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
585 14496 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
586 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
587 : {
588 144960 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
589 144960 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_ImagBuffer[1], num_freq_bins );
590 : }
591 :
592 : /* Z (even setups are handled as horizontal) */
593 14496 : set_zero( FoaEven_RealBuffer[2], num_freq_bins );
594 14496 : set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
595 :
596 : /* X */
597 14496 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
598 14496 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
599 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
600 : {
601 144960 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
602 144960 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
603 : }
604 :
605 : /* Direction estimation */
606 14496 : computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
607 14496 : computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] );
608 :
609 : /* Power and intensity estimation for diffuseness */
610 14496 : computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
611 14496 : computeReferencePower_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, reference_power[ts], num_freq_bands );
612 :
613 : /* Fill buffers of length "averaging_length" time slots for intensity and energy */
614 14496 : hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
615 14496 : index = hMcMasa->index_buffer_intensity;
616 57984 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
617 : {
618 : /* only real part needed */
619 43488 : mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
620 : }
621 14496 : mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
622 :
623 14496 : computeDiffuseness( hMcMasa->buffer_intensity_real, hMcMasa->buffer_energy, num_freq_bands, diffuseness_vector );
624 :
625 : /* Compute vertical diffuseness, and tune original diffuseness if needed */
626 14496 : if ( !hMcMasa->isHorizontalSetup )
627 : {
628 14496 : mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
629 14496 : computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
630 14496 : v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
631 : }
632 :
633 338240 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
634 : {
635 323744 : norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
636 :
637 323744 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
638 323744 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
639 323744 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
640 :
641 323744 : diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
642 323744 : renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
643 : }
644 : }
645 :
646 84560 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
647 : {
648 323744 : for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
649 : {
650 242808 : dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
651 : }
652 80936 : 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] );
653 : }
654 :
655 : /* Coherence processing */
656 84560 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
657 : {
658 : /* Compute absolute values */
659 971232 : for ( i = 0; i < numAnalysisChannels; i++ )
660 : {
661 6232072 : for ( j = i; j < numAnalysisChannels; j++ )
662 : {
663 5341776 : 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] ) );
664 : }
665 890296 : lsEnergy[i] = absCOVls[i][i];
666 : }
667 :
668 : /* Find loudest channel */
669 80936 : maxEne = lsEnergy[0];
670 80936 : loudestCh = 0;
671 890296 : for ( i = 1; i < numAnalysisChannels; i++ )
672 : {
673 809360 : if ( lsEnergy[i] > maxEne )
674 : {
675 150610 : maxEne = lsEnergy[i];
676 150610 : loudestCh = i;
677 : }
678 : }
679 :
680 : /* Compute surrounding coherence */
681 80936 : surrCoh = 1.0f;
682 971232 : for ( i = 0; i < numAnalysisChannels; i++ )
683 : {
684 890296 : if ( i != loudestCh )
685 : {
686 809360 : if ( i < loudestCh )
687 : {
688 480772 : i1 = i;
689 480772 : i2 = loudestCh;
690 : }
691 : else
692 : {
693 328588 : i1 = loudestCh;
694 328588 : i2 = i;
695 : }
696 809360 : tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
697 809360 : surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
698 : }
699 : }
700 80936 : surrCoh = surrCoh * surrCoh;
701 80936 : surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
702 80936 : surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
703 :
704 : /* Compute spread coherence */
705 80936 : if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
706 : {
707 6490 : minAngleDist = 180.0f;
708 6490 : i1 = 0;
709 6490 : currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
710 51920 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
711 : {
712 45430 : angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
713 45430 : if ( angleDist > 180.0f )
714 : {
715 1142 : angleDist = fabsf( angleDist - 360.0f );
716 : }
717 45430 : if ( angleDist < minAngleDist )
718 : {
719 14496 : minAngleDist = angleDist;
720 14496 : i1 = i;
721 : }
722 : }
723 6490 : i2 = hMcMasa->leftNearest[i1];
724 6490 : i3 = hMcMasa->rightNearest[i1];
725 :
726 6490 : if ( i2 < i3 )
727 : {
728 5154 : stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
729 : }
730 : else
731 : {
732 1336 : stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
733 : }
734 6490 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
735 6490 : stereoness = stereoCoh * lsEnergyRelation;
736 :
737 6490 : if ( i1 < i2 )
738 : {
739 2268 : tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
740 : }
741 : else
742 : {
743 4222 : tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
744 : }
745 6490 : if ( i1 < i3 )
746 : {
747 2078 : tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
748 : }
749 : else
750 : {
751 4412 : tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
752 : }
753 6490 : cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
754 6490 : lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
755 6490 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
756 6490 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
757 6490 : tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
758 6490 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
759 6490 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
760 6490 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
761 6490 : cohwideness = cohPanCoh * lsEnergyRelation;
762 :
763 6490 : spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
764 6490 : if ( spreadCoh > 0.5f )
765 : {
766 1996 : if ( cohwideness > stereoness )
767 : {
768 630 : tempCoh = stereoness - ( cohwideness - 0.5f );
769 630 : spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
770 : }
771 : }
772 6490 : spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
773 6490 : spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
774 :
775 : /* Compute energy ratio tuning parameter */
776 6490 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
777 6490 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
778 6490 : stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
779 :
780 6490 : lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
781 6490 : cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
782 :
783 6490 : cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
784 6490 : cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
785 6490 : cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
786 : }
787 : else /* Otherwise, set spread coherence to zero */
788 : {
789 74446 : spreadCoh = 0.0f;
790 74446 : cohRatio = 0.0f;
791 74446 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
792 : }
793 :
794 : /* Store values */
795 80936 : spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
796 80936 : surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
797 80936 : coherentEnergyRatio[band_m_idx] = cohRatio;
798 : }
799 :
800 : /* Determine energy ratios */
801 84560 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
802 : {
803 80936 : if ( renormalization_factor_diff[band_m_idx] > EPSILON )
804 : {
805 80802 : diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
806 : }
807 : else
808 : {
809 134 : diffuseness_m[band_m_idx] = 0.0f;
810 : }
811 :
812 80936 : energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
813 80936 : 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];
814 : }
815 : }
816 :
817 906 : return;
818 : }
819 :
820 :
821 : /* Compute downmix */
822 906 : static void ivas_mcmasa_dmx(
823 : MCMASA_ANA_HANDLE hMcMasa,
824 : float data_f[][L_FRAME48k],
825 : const int16_t input_frame,
826 : const int16_t nchan_transport,
827 : const int16_t nchan_inp )
828 : {
829 : int16_t i, j;
830 : int16_t numAnalysisChannels;
831 : float dmx_c;
832 : float multiChEne, downmixEne;
833 : float prevEQ, currEQ, instEQ;
834 : float alpha;
835 :
836 906 : numAnalysisChannels = nchan_inp - 1;
837 :
838 906 : multiChEne = 0.0f;
839 10872 : for ( j = 0; j < numAnalysisChannels; j++ )
840 : {
841 6388206 : for ( i = 0; i < input_frame; i++ )
842 : {
843 6378240 : multiChEne += data_f[j][i] * data_f[j][i];
844 : }
845 : }
846 :
847 906 : if ( nchan_transport == 2 )
848 : {
849 : int16_t numSideChannels; /* Channels other than left, right, center */
850 : int16_t leftIndex, rightIndex;
851 :
852 453 : numSideChannels = numAnalysisChannels / 2 - 1;
853 2265 : for ( j = 0; j < numSideChannels; j++ )
854 : {
855 1812 : leftIndex = j * 2 + 3;
856 1812 : rightIndex = j * 2 + 4;
857 :
858 1161492 : for ( i = 0; i < input_frame; i++ )
859 : {
860 1159680 : data_f[0][i] += data_f[leftIndex][i];
861 1159680 : data_f[1][i] += data_f[rightIndex][i];
862 : }
863 : }
864 :
865 290373 : for ( i = 0; i < input_frame; i++ )
866 : {
867 289920 : dmx_c = INV_SQRT2 * data_f[2][i];
868 289920 : data_f[0][i] += dmx_c;
869 289920 : data_f[1][i] += dmx_c;
870 : }
871 : }
872 453 : else if ( nchan_transport == 1 )
873 : {
874 290373 : for ( i = 0; i < input_frame; i++ )
875 : {
876 3189120 : for ( j = 1; j < numAnalysisChannels; j++ )
877 : {
878 2899200 : data_f[0][i] += data_f[j][i];
879 : }
880 : }
881 : }
882 :
883 906 : downmixEne = 0.0f;
884 2265 : for ( j = 0; j < nchan_transport; j++ )
885 : {
886 871119 : for ( i = 0; i < input_frame; i++ )
887 : {
888 869760 : downmixEne += data_f[j][i] * data_f[j][i];
889 : }
890 : }
891 :
892 906 : alpha = 0.1f;
893 906 : hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
894 906 : hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
895 :
896 906 : prevEQ = hMcMasa->prevEQ;
897 906 : currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
898 906 : hMcMasa->prevEQ = currEQ;
899 :
900 580746 : for ( i = 0; i < input_frame; i++ )
901 : {
902 579840 : instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
903 1449600 : for ( j = 0; j < nchan_transport; j++ )
904 : {
905 869760 : data_f[j][i] *= instEQ;
906 : }
907 : }
908 :
909 906 : return;
910 : }
911 :
912 :
913 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
914 579840 : static void compute_cov_mtx(
915 : float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */
916 : float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */
917 : const int16_t freq, /* i : Freq to process */
918 : const int16_t N, /* i : Number of channels */
919 : CovarianceMatrix *COVls /* o : Output matrix, contains upper part of cov mtx */
920 : )
921 : {
922 : int16_t i, j;
923 : float a, b, c, d;
924 :
925 6958080 : for ( i = 0; i < N; i++ )
926 : {
927 6378240 : a = sr[i][freq];
928 6378240 : b = si[i][freq];
929 44647680 : for ( j = i; j < N; j++ )
930 : {
931 38269440 : c = sr[j][freq];
932 38269440 : d = si[j][freq];
933 38269440 : COVls->xr[i][j] += a * c + b * d;
934 38269440 : COVls->xi[i][j] += b * c - a * d;
935 : }
936 : }
937 :
938 579840 : return;
939 : }
940 :
941 : /*-------------------------------------------------------------------------
942 : * computeVerticalDiffuseness()
943 : *
944 : *
945 : *------------------------------------------------------------------------*/
946 :
947 14496 : static void computeVerticalDiffuseness(
948 : float **buffer_intensity, /* i : Intensity vectors */
949 : const float *buffer_energy, /* i : Energy */
950 : const int16_t num_freq_bands, /* i : Number of frequency bands */
951 : float *diffuseness /* o : Estimated diffuseness */
952 : )
953 : {
954 : float intensity_slow[MASA_FREQUENCY_BANDS];
955 : float intensity_slow_abs[MASA_FREQUENCY_BANDS];
956 : float energy_slow[MASA_FREQUENCY_BANDS];
957 : int16_t i, k;
958 14496 : float tmp = 0;
959 : const float *p_tmp_c;
960 :
961 : /* Set variables to zero */
962 14496 : set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
963 14496 : set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
964 :
965 478368 : for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
966 : {
967 : /* Energy slow */
968 463872 : p_tmp_c = buffer_energy + i * num_freq_bands;
969 10823680 : for ( k = 0; k < num_freq_bands; k++ )
970 : {
971 10359808 : energy_slow[k] += *( p_tmp_c++ );
972 : }
973 :
974 : /* Intensity slow */
975 10823680 : for ( k = 0; k < num_freq_bands; k++ )
976 : {
977 10359808 : intensity_slow[k] += buffer_intensity[i][k];
978 : }
979 : }
980 :
981 : /* Compute absolute value */
982 338240 : for ( k = 0; k < num_freq_bands; k++ )
983 : {
984 323744 : intensity_slow_abs[k] = fabsf( intensity_slow[k] );
985 : }
986 :
987 : /* Compute Diffuseness */
988 338240 : for ( i = 0; i < num_freq_bands; ++i )
989 : {
990 323744 : tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
991 323744 : tmp = ( tmp - VERTICAL_ENERGY_RATIO_OFFSET ) / ( 1.0f - VERTICAL_ENERGY_RATIO_OFFSET ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
992 323744 : tmp = 1.0f - tmp;
993 323744 : diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
994 : }
995 :
996 14496 : return;
997 : }
998 :
999 :
1000 12 : static void computeEvenLayout(
1001 : const float *ls_azimuth,
1002 : float *ls_azimuth_even,
1003 : const int16_t numChannels )
1004 : {
1005 : int16_t i;
1006 : int16_t j;
1007 : float ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
1008 : float ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
1009 : int16_t ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
1010 : float smallestAzimuth;
1011 : int16_t smallestAzimuthIndex;
1012 : float lsSpacing;
1013 : uint8_t oddLayout;
1014 : float startAzimuth;
1015 : int16_t numChannelsHalf;
1016 :
1017 12 : lsSpacing = 360.0f / (float) numChannels;
1018 12 : oddLayout = numChannels % 2;
1019 12 : numChannelsHalf = numChannels / 2;
1020 :
1021 12 : mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
1022 78 : for ( i = 0; i < numChannels; i++ )
1023 : {
1024 66 : smallestAzimuth = 1000.0f;
1025 66 : smallestAzimuthIndex = 0;
1026 456 : for ( j = 0; j < numChannels; j++ )
1027 : {
1028 390 : if ( ls_azimuth_temp[j] < smallestAzimuth )
1029 : {
1030 126 : smallestAzimuth = ls_azimuth_temp[j];
1031 126 : smallestAzimuthIndex = j;
1032 : }
1033 : }
1034 66 : ls_azimuth_order[i] = smallestAzimuthIndex;
1035 66 : ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
1036 : }
1037 :
1038 12 : if ( oddLayout )
1039 : {
1040 6 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
1041 : }
1042 : else
1043 : {
1044 6 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
1045 : }
1046 :
1047 78 : for ( i = 0; i < numChannels; i++ )
1048 : {
1049 66 : ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
1050 : }
1051 :
1052 78 : for ( i = 0; i < numChannels; i++ )
1053 : {
1054 66 : ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
1055 : }
1056 :
1057 12 : return;
1058 : }
1059 :
1060 :
1061 : /*-------------------------------------------------------------------------
1062 : * ivas_create_masa_out_meta()
1063 : *
1064 : *
1065 : *------------------------------------------------------------------------*/
1066 :
1067 290766 : void ivas_create_masa_out_meta(
1068 : MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */
1069 : SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */
1070 : const int16_t nchan_transport, /* i : Number of transport channels */
1071 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation */
1072 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth */
1073 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */
1074 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */
1075 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i : Estimated surround coherence */
1076 : )
1077 : {
1078 : int16_t i, sf, band;
1079 : uint8_t numFrequencyBands;
1080 : uint8_t numDirections;
1081 : uint16_t spherical_index;
1082 :
1083 290766 : numDirections = 1;
1084 290766 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1085 :
1086 : /* Construct descriptive meta */
1087 2616894 : for ( i = 0; i < 8; i++ )
1088 : {
1089 2326128 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1090 : }
1091 290766 : extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
1092 290766 : extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
1093 : /* Following correspond to "unknown" values */
1094 290766 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1095 290766 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1096 290766 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1097 290766 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1098 290766 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1099 :
1100 : /* Construct spatial metadata from estimated values */
1101 1453830 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1102 : {
1103 : /* Spherical index */
1104 29076600 : for ( band = 0; band < numFrequencyBands; band++ )
1105 : {
1106 27913536 : spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1107 27913536 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1108 27913536 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1109 : }
1110 :
1111 : /* Direct-to-total ratio */
1112 29076600 : for ( band = 0; band < numFrequencyBands; band++ )
1113 : {
1114 27913536 : extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1115 27913536 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1116 : }
1117 :
1118 : /* Spread coherence */
1119 29076600 : for ( band = 0; band < numFrequencyBands; band++ )
1120 : {
1121 27913536 : extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
1122 27913536 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1123 : }
1124 :
1125 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1126 29076600 : for ( band = 0; band < numFrequencyBands; band++ )
1127 : {
1128 27913536 : extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1129 : }
1130 :
1131 : /* Surround coherence */
1132 29076600 : for ( band = 0; band < numFrequencyBands; band++ )
1133 : {
1134 27913536 : extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
1135 : }
1136 : }
1137 :
1138 290766 : return;
1139 : }
1140 :
1141 :
1142 : /*-------------------------------------------------------------------------
1143 : * ivas_masa_zero_high_bands()
1144 : *
1145 : *
1146 : *------------------------------------------------------------------------*/
1147 :
1148 193844 : void ivas_masa_zero_high_bands(
1149 : const int16_t nbands, /* i : Number of frequency bands with estimated values */
1150 : float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i/o : Estimated elevation */
1151 : float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i/o : Estimated azimuth */
1152 : float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i/o : Estimated direct-to-total ratio */
1153 : float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i/o : Estimated spread coherence */
1154 : float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i/o : Estimated surround coherence */
1155 : )
1156 : {
1157 : int16_t sf, band;
1158 :
1159 969220 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1160 : {
1161 2713816 : for ( band = nbands; band < MASA_FREQUENCY_BANDS; band++ )
1162 : {
1163 1938440 : elevation_m_values[sf][band] = 0.0f;
1164 1938440 : azimuth_m_values[sf][band] = 0.0f;
1165 1938440 : energyRatio[sf][band] = 0.0f;
1166 1938440 : spreadCoherence[sf][band] = 0.0f;
1167 1938440 : surroundingCoherence[sf][band] = 0.0f;
1168 : }
1169 : }
1170 :
1171 193844 : return;
1172 : }
|