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 1 : 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 1 : error = IVAS_ERR_OK;
103 :
104 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : nchan_inp = 12;
144 1 : mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
145 1 : mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
146 1 : hMcMasa->numHorizontalChannels = 7;
147 1 : hMcMasa->isHorizontalSetup = 0;
148 : }
149 :
150 1 : numAnalysisChannels = nchan_inp - 1;
151 :
152 : /* Determine the number of bands */
153 1 : hMcMasa->nbands = MASA_FREQUENCY_BANDS;
154 :
155 : /* Determine band grouping */
156 1 : mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
157 :
158 1 : maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
159 24 : for ( i = 1; i < hMcMasa->nbands + 1; i++ )
160 : {
161 24 : if ( hMcMasa->band_grouping[i] >= maxBin )
162 : {
163 1 : hMcMasa->band_grouping[i] = maxBin;
164 1 : hMcMasa->nbands = i;
165 1 : break;
166 : }
167 : }
168 :
169 : /* Determine block grouping */
170 1 : mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
171 :
172 : /* open/initialize CLDFB */
173 1 : hMcMasa->num_Cldfb_instances = numAnalysisChannels;
174 12 : for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
175 : {
176 11 : 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 4 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
184 : {
185 3 : 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 15 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
191 : {
192 12 : 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 12 : set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
197 : }
198 : }
199 :
200 4 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
201 : {
202 99 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
203 : {
204 96 : 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 96 : set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
209 : }
210 : }
211 :
212 33 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
213 : {
214 32 : 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 32 : set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
219 : }
220 :
221 1 : set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
222 :
223 1 : computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
224 :
225 1 : if ( !hMcMasa->isHorizontalSetup )
226 : {
227 1 : computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
228 : }
229 :
230 12 : for ( i = 0; i < numAnalysisChannels; i++ )
231 : {
232 11 : hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
233 11 : hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
234 11 : hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
235 11 : hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
236 :
237 11 : hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
238 11 : hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
239 11 : hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
240 11 : hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
241 : }
242 :
243 1 : mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
244 :
245 8 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
246 : {
247 7 : left_min = 360.0f;
248 7 : right_min = -360.0f;
249 :
250 56 : for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
251 : {
252 49 : azi_diff = ls_azimuth[j] - ls_azimuth[i];
253 :
254 49 : if ( azi_diff > 180.0f )
255 : {
256 3 : azi_diff -= 360.0f;
257 : }
258 46 : else if ( azi_diff < -180.0f )
259 : {
260 3 : azi_diff += 360.0f;
261 : }
262 :
263 49 : if ( azi_diff < left_min && azi_diff > 0.0f )
264 : {
265 12 : hMcMasa->leftNearest[i] = j;
266 12 : left_min = azi_diff;
267 : }
268 :
269 49 : if ( azi_diff > right_min && azi_diff < 0.0f )
270 : {
271 11 : hMcMasa->rightNearest[i] = j;
272 11 : right_min = azi_diff;
273 : }
274 : }
275 : }
276 :
277 1 : hMcMasa->prevMultiChEne = 0.0f;
278 1 : hMcMasa->prevDownmixEne = 0.0f;
279 1 : hMcMasa->prevEQ = 1.0f;
280 1 : input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
281 961 : for ( i = 0; i < input_frame; i++ )
282 : {
283 960 : hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
284 : }
285 :
286 1 : hMcMasa->index_buffer_intensity = 0;
287 :
288 1 : 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 1 : 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 1 : generate_gridEq( hMcMasa->sph_grid16 );
298 :
299 1 : ( *hMcMasaPtr ) = hMcMasa;
300 :
301 1 : return error;
302 : }
303 :
304 :
305 : /*--------------------------------------------------------------------------*
306 : * ivas_mcmasa_ana_close()
307 : *
308 : *
309 : *--------------------------------------------------------------------------*/
310 :
311 666 : void ivas_mcmasa_ana_close(
312 : MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */
313 : )
314 : {
315 : int16_t i, j;
316 :
317 666 : if ( hMcMasa == NULL || *hMcMasa == NULL )
318 : {
319 665 : return;
320 : }
321 :
322 12 : for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
323 : {
324 11 : deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
325 : }
326 :
327 : /* intensity 3-dim */
328 4 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
329 : {
330 15 : for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
331 : {
332 12 : free( ( *hMcMasa )->direction_vector_m[i][j] );
333 12 : ( *hMcMasa )->direction_vector_m[i][j] = NULL;
334 : }
335 :
336 99 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
337 : {
338 96 : free( ( *hMcMasa )->buffer_intensity_real[i][j] );
339 96 : ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
340 : }
341 :
342 3 : free( ( *hMcMasa )->direction_vector_m[i] );
343 3 : ( *hMcMasa )->direction_vector_m[i] = NULL;
344 : }
345 :
346 33 : for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
347 : {
348 32 : free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
349 32 : ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
350 : }
351 :
352 1 : free( ( *hMcMasa )->hMasaOut );
353 1 : ( *hMcMasa )->hMasaOut = NULL;
354 1 : free( ( *hMcMasa )->sph_grid16 );
355 1 : ( *hMcMasa )->sph_grid16 = NULL;
356 :
357 1 : free( ( *hMcMasa ) );
358 1 : ( *hMcMasa ) = NULL;
359 :
360 1 : return;
361 : }
362 :
363 :
364 : /*--------------------------------------------------------------------------*
365 : * ivas_mcmasa_ana()
366 : *
367 : * Multichannel MASA analysis
368 : *--------------------------------------------------------------------------*/
369 :
370 151 : 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 151 : v_add( data_f[2], data_f[3], data_f[2], input_frame );
388 1359 : for ( i = 4; i < nchan_inp; i++ )
389 : {
390 1208 : mvr2r( data_f[i], data_f[i - 1], input_frame );
391 : }
392 :
393 : /* Analysis */
394 151 : 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 151 : if ( hMcMasa->nbands < MASA_FREQUENCY_BANDS )
398 : {
399 0 : 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 151 : 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 151 : ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
407 :
408 151 : return;
409 : }
410 :
411 :
412 : /*--------------------------------------------------------------------------*
413 : * Local functions
414 : *--------------------------------------------------------------------------*/
415 :
416 : /* Estimate metadata parameters for McMASA */
417 151 : 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 151 : num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
468 151 : num_freq_bands = hMcMasa->nbands;
469 151 : l_ts = input_frame / CLDFB_NO_COL_MAX;
470 151 : numAnalysisChannels = nchan_inp - 1;
471 :
472 : /* do processing over all CLDFB time slots */
473 755 : for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
474 : {
475 604 : mrange[0] = hMcMasa->block_grouping[block_m_idx];
476 604 : mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
477 :
478 15100 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
479 : {
480 14496 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
481 14496 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
482 14496 : 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 604 : set_zero( renormalization_factor_diff, hMcMasa->nbands );
487 604 : set_zero( diffuseness_m, hMcMasa->nbands );
488 604 : set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
489 :
490 : /* Reset variable */
491 15100 : for ( i = 0; i < hMcMasa->nbands; i++ )
492 : {
493 173952 : for ( j = 0; j < numAnalysisChannels; j++ )
494 : {
495 159456 : set_zero( COVls[i].xr[j], numAnalysisChannels );
496 159456 : set_zero( COVls[i].xi[j], numAnalysisChannels );
497 : }
498 : }
499 :
500 3020 : for ( ts = mrange[0]; ts < mrange[1]; ts++ )
501 : {
502 28992 : for ( i = 0; i < numAnalysisChannels; i++ )
503 : {
504 26576 : 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 60400 : for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
509 : {
510 57984 : brange[0] = hMcMasa->band_grouping[band_m_idx];
511 57984 : brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
512 202944 : for ( j = brange[0]; j < brange[1]; j++ )
513 : {
514 1739520 : for ( i = 0; i < numAnalysisChannels; i++ )
515 : {
516 1594560 : 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 60400 : for ( i = 0; i < num_freq_bands; i++ )
523 : {
524 57984 : brange[0] = hMcMasa->band_grouping[i];
525 57984 : brange[1] = hMcMasa->band_grouping[i + 1];
526 202944 : for ( j = brange[0]; j < brange[1]; j++ )
527 : {
528 144960 : compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
529 : }
530 : }
531 :
532 : /* Compute standard FOA */
533 : /* W */
534 2416 : v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
535 2416 : v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
536 24160 : for ( i = 2; i < numAnalysisChannels; i++ )
537 : {
538 21744 : v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
539 21744 : v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
540 : }
541 :
542 : /* Y */
543 2416 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
544 2416 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
545 26576 : for ( i = 1; i < numAnalysisChannels; i++ )
546 : {
547 24160 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
548 24160 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
549 : }
550 :
551 : /* Z */
552 2416 : 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 2416 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
561 2416 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
562 26576 : for ( i = 1; i < numAnalysisChannels; i++ )
563 : {
564 24160 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
565 24160 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
566 : }
567 : }
568 :
569 : /* X */
570 2416 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
571 2416 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
572 26576 : for ( i = 1; i < numAnalysisChannels; i++ )
573 : {
574 24160 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
575 24160 : 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 2416 : mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
581 2416 : mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
582 :
583 : /* Y */
584 2416 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
585 2416 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
586 26576 : for ( i = 1; i < numAnalysisChannels; i++ )
587 : {
588 24160 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
589 24160 : 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 2416 : set_zero( FoaEven_RealBuffer[2], num_freq_bins );
594 2416 : set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
595 :
596 : /* X */
597 2416 : v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
598 2416 : v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
599 26576 : for ( i = 1; i < numAnalysisChannels; i++ )
600 : {
601 24160 : v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
602 24160 : v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
603 : }
604 :
605 : /* Direction estimation */
606 2416 : computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
607 2416 : 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 2416 : computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
611 2416 : 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 2416 : hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
615 2416 : index = hMcMasa->index_buffer_intensity;
616 9664 : for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
617 : {
618 : /* only real part needed */
619 7248 : mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
620 : }
621 2416 : mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
622 :
623 2416 : 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 2416 : if ( !hMcMasa->isHorizontalSetup )
627 : {
628 2416 : mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
629 2416 : computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
630 2416 : v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
631 : }
632 :
633 60400 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
634 : {
635 57984 : norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
636 :
637 57984 : hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
638 57984 : hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
639 57984 : hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
640 :
641 57984 : diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
642 57984 : renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
643 : }
644 : }
645 :
646 15100 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
647 : {
648 57984 : for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
649 : {
650 43488 : dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
651 : }
652 14496 : 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 15100 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
657 : {
658 : /* Compute absolute values */
659 173952 : for ( i = 0; i < numAnalysisChannels; i++ )
660 : {
661 1116192 : for ( j = i; j < numAnalysisChannels; j++ )
662 : {
663 956736 : 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 159456 : lsEnergy[i] = absCOVls[i][i];
666 : }
667 :
668 : /* Find loudest channel */
669 14496 : maxEne = lsEnergy[0];
670 14496 : loudestCh = 0;
671 159456 : for ( i = 1; i < numAnalysisChannels; i++ )
672 : {
673 144960 : if ( lsEnergy[i] > maxEne )
674 : {
675 27596 : maxEne = lsEnergy[i];
676 27596 : loudestCh = i;
677 : }
678 : }
679 :
680 : /* Compute surrounding coherence */
681 14496 : surrCoh = 1.0f;
682 173952 : for ( i = 0; i < numAnalysisChannels; i++ )
683 : {
684 159456 : if ( i != loudestCh )
685 : {
686 144960 : if ( i < loudestCh )
687 : {
688 88271 : i1 = i;
689 88271 : i2 = loudestCh;
690 : }
691 : else
692 : {
693 56689 : i1 = loudestCh;
694 56689 : i2 = i;
695 : }
696 144960 : tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
697 144960 : surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
698 : }
699 : }
700 14496 : surrCoh = surrCoh * surrCoh;
701 14496 : surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
702 14496 : surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
703 :
704 : /* Compute spread coherence */
705 14496 : if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
706 : {
707 1099 : minAngleDist = 180.0f;
708 1099 : i1 = 0;
709 1099 : currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
710 8792 : for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
711 : {
712 7693 : angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
713 7693 : if ( angleDist > 180.0f )
714 : {
715 192 : angleDist = fabsf( angleDist - 360.0f );
716 : }
717 7693 : if ( angleDist < minAngleDist )
718 : {
719 2454 : minAngleDist = angleDist;
720 2454 : i1 = i;
721 : }
722 : }
723 1099 : i2 = hMcMasa->leftNearest[i1];
724 1099 : i3 = hMcMasa->rightNearest[i1];
725 :
726 1099 : if ( i2 < i3 )
727 : {
728 878 : stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
729 : }
730 : else
731 : {
732 221 : stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
733 : }
734 1099 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
735 1099 : stereoness = stereoCoh * lsEnergyRelation;
736 :
737 1099 : if ( i1 < i2 )
738 : {
739 377 : tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
740 : }
741 : else
742 : {
743 722 : tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
744 : }
745 1099 : if ( i1 < i3 )
746 : {
747 345 : tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
748 : }
749 : else
750 : {
751 754 : tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
752 : }
753 1099 : cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
754 1099 : lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
755 1099 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
756 1099 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
757 1099 : tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
758 1099 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
759 1099 : tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
760 1099 : lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
761 1099 : cohwideness = cohPanCoh * lsEnergyRelation;
762 :
763 1099 : spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
764 1099 : if ( spreadCoh > 0.5f )
765 : {
766 349 : if ( cohwideness > stereoness )
767 : {
768 111 : tempCoh = stereoness - ( cohwideness - 0.5f );
769 111 : spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
770 : }
771 : }
772 1099 : spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
773 1099 : spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
774 :
775 : /* Compute energy ratio tuning parameter */
776 1099 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
777 1099 : lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
778 1099 : stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
779 :
780 1099 : lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
781 1099 : cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
782 :
783 1099 : cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
784 1099 : cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
785 1099 : cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
786 : }
787 : else /* Otherwise, set spread coherence to zero */
788 : {
789 13397 : spreadCoh = 0.0f;
790 13397 : cohRatio = 0.0f;
791 13397 : lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
792 : }
793 :
794 : /* Store values */
795 14496 : spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
796 14496 : surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
797 14496 : coherentEnergyRatio[band_m_idx] = cohRatio;
798 : }
799 :
800 : /* Determine energy ratios */
801 15100 : for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
802 : {
803 14496 : if ( renormalization_factor_diff[band_m_idx] > EPSILON )
804 : {
805 14472 : diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
806 : }
807 : else
808 : {
809 24 : diffuseness_m[band_m_idx] = 0.0f;
810 : }
811 :
812 14496 : energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
813 14496 : 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 151 : return;
818 : }
819 :
820 :
821 : /* Compute downmix */
822 151 : 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 151 : numAnalysisChannels = nchan_inp - 1;
837 :
838 151 : multiChEne = 0.0f;
839 1812 : for ( j = 0; j < numAnalysisChannels; j++ )
840 : {
841 1596221 : for ( i = 0; i < input_frame; i++ )
842 : {
843 1594560 : multiChEne += data_f[j][i] * data_f[j][i];
844 : }
845 : }
846 :
847 151 : if ( nchan_transport == 2 )
848 : {
849 : int16_t numSideChannels; /* Channels other than left, right, center */
850 : int16_t leftIndex, rightIndex;
851 :
852 151 : numSideChannels = numAnalysisChannels / 2 - 1;
853 755 : for ( j = 0; j < numSideChannels; j++ )
854 : {
855 604 : leftIndex = j * 2 + 3;
856 604 : rightIndex = j * 2 + 4;
857 :
858 580444 : for ( i = 0; i < input_frame; i++ )
859 : {
860 579840 : data_f[0][i] += data_f[leftIndex][i];
861 579840 : data_f[1][i] += data_f[rightIndex][i];
862 : }
863 : }
864 :
865 145111 : for ( i = 0; i < input_frame; i++ )
866 : {
867 144960 : dmx_c = INV_SQRT2 * data_f[2][i];
868 144960 : data_f[0][i] += dmx_c;
869 144960 : data_f[1][i] += dmx_c;
870 : }
871 : }
872 0 : else if ( nchan_transport == 1 )
873 : {
874 0 : for ( i = 0; i < input_frame; i++ )
875 : {
876 0 : for ( j = 1; j < numAnalysisChannels; j++ )
877 : {
878 0 : data_f[0][i] += data_f[j][i];
879 : }
880 : }
881 : }
882 :
883 151 : downmixEne = 0.0f;
884 453 : for ( j = 0; j < nchan_transport; j++ )
885 : {
886 290222 : for ( i = 0; i < input_frame; i++ )
887 : {
888 289920 : downmixEne += data_f[j][i] * data_f[j][i];
889 : }
890 : }
891 :
892 151 : alpha = 0.1f;
893 151 : hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
894 151 : hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
895 :
896 151 : prevEQ = hMcMasa->prevEQ;
897 151 : currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
898 151 : hMcMasa->prevEQ = currEQ;
899 :
900 145111 : for ( i = 0; i < input_frame; i++ )
901 : {
902 144960 : instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
903 434880 : for ( j = 0; j < nchan_transport; j++ )
904 : {
905 289920 : data_f[j][i] *= instEQ;
906 : }
907 : }
908 :
909 151 : return;
910 : }
911 :
912 :
913 : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
914 144960 : 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 1739520 : for ( i = 0; i < N; i++ )
926 : {
927 1594560 : a = sr[i][freq];
928 1594560 : b = si[i][freq];
929 11161920 : for ( j = i; j < N; j++ )
930 : {
931 9567360 : c = sr[j][freq];
932 9567360 : d = si[j][freq];
933 9567360 : COVls->xr[i][j] += a * c + b * d;
934 9567360 : COVls->xi[i][j] += b * c - a * d;
935 : }
936 : }
937 :
938 144960 : return;
939 : }
940 :
941 : /*-------------------------------------------------------------------------
942 : * computeVerticalDiffuseness()
943 : *
944 : *
945 : *------------------------------------------------------------------------*/
946 :
947 2416 : 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 2416 : float tmp = 0;
959 : const float *p_tmp_c;
960 :
961 : /* Set variables to zero */
962 2416 : set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
963 2416 : set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
964 :
965 79728 : for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
966 : {
967 : /* Energy slow */
968 77312 : p_tmp_c = buffer_energy + i * num_freq_bands;
969 1932800 : for ( k = 0; k < num_freq_bands; k++ )
970 : {
971 1855488 : energy_slow[k] += *( p_tmp_c++ );
972 : }
973 :
974 : /* Intensity slow */
975 1932800 : for ( k = 0; k < num_freq_bands; k++ )
976 : {
977 1855488 : intensity_slow[k] += buffer_intensity[i][k];
978 : }
979 : }
980 :
981 : /* Compute absolute value */
982 60400 : for ( k = 0; k < num_freq_bands; k++ )
983 : {
984 57984 : intensity_slow_abs[k] = fabsf( intensity_slow[k] );
985 : }
986 :
987 : /* Compute Diffuseness */
988 60400 : for ( i = 0; i < num_freq_bands; ++i )
989 : {
990 57984 : tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
991 57984 : 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 57984 : tmp = 1.0f - tmp;
993 57984 : diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
994 : }
995 :
996 2416 : return;
997 : }
998 :
999 :
1000 2 : 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 2 : lsSpacing = 360.0f / (float) numChannels;
1018 2 : oddLayout = numChannels % 2;
1019 2 : numChannelsHalf = numChannels / 2;
1020 :
1021 2 : mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
1022 13 : for ( i = 0; i < numChannels; i++ )
1023 : {
1024 11 : smallestAzimuth = 1000.0f;
1025 11 : smallestAzimuthIndex = 0;
1026 76 : for ( j = 0; j < numChannels; j++ )
1027 : {
1028 65 : if ( ls_azimuth_temp[j] < smallestAzimuth )
1029 : {
1030 21 : smallestAzimuth = ls_azimuth_temp[j];
1031 21 : smallestAzimuthIndex = j;
1032 : }
1033 : }
1034 11 : ls_azimuth_order[i] = smallestAzimuthIndex;
1035 11 : ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
1036 : }
1037 :
1038 2 : if ( oddLayout )
1039 : {
1040 1 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
1041 : }
1042 : else
1043 : {
1044 1 : startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
1045 : }
1046 :
1047 13 : for ( i = 0; i < numChannels; i++ )
1048 : {
1049 11 : ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
1050 : }
1051 :
1052 13 : for ( i = 0; i < numChannels; i++ )
1053 : {
1054 11 : ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
1055 : }
1056 :
1057 2 : return;
1058 : }
1059 :
1060 :
1061 : /*-------------------------------------------------------------------------
1062 : * ivas_create_masa_out_meta()
1063 : *
1064 : *
1065 : *------------------------------------------------------------------------*/
1066 :
1067 453 : 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 453 : numDirections = 1;
1084 453 : numFrequencyBands = MASA_FREQUENCY_BANDS;
1085 :
1086 : /* Construct descriptive meta */
1087 4077 : for ( i = 0; i < 8; i++ )
1088 : {
1089 3624 : extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
1090 : }
1091 453 : extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
1092 453 : extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
1093 : /* Following correspond to "unknown" values */
1094 453 : extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
1095 453 : extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
1096 453 : extOutMeta->descriptiveMeta.channelAngle = 0x0u;
1097 453 : extOutMeta->descriptiveMeta.channelDistance = 0x0u;
1098 453 : extOutMeta->descriptiveMeta.channelLayout = 0x0u;
1099 :
1100 : /* Construct spatial metadata from estimated values */
1101 2265 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1102 : {
1103 : /* Spherical index */
1104 45300 : for ( band = 0; band < numFrequencyBands; band++ )
1105 : {
1106 43488 : spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
1107 43488 : extOutMeta->directionIndex[0][sf][band] = spherical_index;
1108 43488 : extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
1109 : }
1110 :
1111 : /* Direct-to-total ratio */
1112 45300 : for ( band = 0; band < numFrequencyBands; band++ )
1113 : {
1114 43488 : extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1115 43488 : extOutMeta->directToTotalRatio[1][sf][band] = 0;
1116 : }
1117 :
1118 : /* Spread coherence */
1119 45300 : for ( band = 0; band < numFrequencyBands; band++ )
1120 : {
1121 43488 : extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
1122 43488 : extOutMeta->spreadCoherence[1][sf][band] = 0;
1123 : }
1124 :
1125 : /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
1126 45300 : for ( band = 0; band < numFrequencyBands; band++ )
1127 : {
1128 43488 : extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
1129 : }
1130 :
1131 : /* Surround coherence */
1132 45300 : for ( band = 0; band < numFrequencyBands; band++ )
1133 : {
1134 43488 : extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
1135 : }
1136 : }
1137 :
1138 453 : return;
1139 : }
1140 :
1141 :
1142 : /*-------------------------------------------------------------------------
1143 : * ivas_masa_zero_high_bands()
1144 : *
1145 : *
1146 : *------------------------------------------------------------------------*/
1147 :
1148 0 : 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 0 : for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
1160 : {
1161 0 : for ( band = nbands; band < MASA_FREQUENCY_BANDS; band++ )
1162 : {
1163 0 : elevation_m_values[sf][band] = 0.0f;
1164 0 : azimuth_m_values[sf][band] = 0.0f;
1165 0 : energyRatio[sf][band] = 0.0f;
1166 0 : spreadCoherence[sf][band] = 0.0f;
1167 0 : surroundingCoherence[sf][band] = 0.0f;
1168 : }
1169 : }
1170 :
1171 0 : return;
1172 : }
|