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 <string.h>
34 : #include <stdio.h>
35 : #include <stdlib.h>
36 : #include <assert.h>
37 : #include <math.h>
38 : #include "options.h"
39 : #include "cnst.h"
40 : #include "rom_enc.h"
41 : #include "rom_com.h"
42 : #include "prot.h"
43 : #include "ivas_prot.h"
44 : #include "ivas_stat_dec.h"
45 : #include "ivas_cnst.h"
46 : #include "ivas_rom_com.h"
47 : #include "ivas_rom_dec.h"
48 : #ifdef DEBUGGING
49 : #include "debug.h"
50 : #endif
51 : #include "wmc_auto.h"
52 : #include "rom_dec.h"
53 :
54 : /*-----------------------------------------------------------------------*
55 : * Local constants
56 : *-----------------------------------------------------------------------*/
57 :
58 : #define SQRT_EPSILON 3.16227755e-08 /* square root of EPSILON */
59 :
60 : /*-------------------------------------------------------------------*
61 : * ivas_dirac_dec_output_synthesis_cov_open()
62 : *
63 : * Sets up the state and parameters for the Covariance Synthesis
64 : *-------------------------------------------------------------------*/
65 :
66 1023 : ivas_error ivas_dirac_dec_output_synthesis_cov_open(
67 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */
68 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: hanlde for the covariance synthesis state */
69 : const int16_t max_band_decorr, /* i : uppermost frequency band where decorrelation is applied */
70 : const int16_t interp_length, /* i : length for interpolating the mixing matrices in time slots */
71 : const int16_t num_param_bands, /* i : number of parameter bands */
72 : const int16_t num_param_bands_residual, /* i : number of parameter bands with a residual mixing matrix (i.e. decorrelation */
73 : const int16_t nchan_in, /* i : number of input (transport) channels */
74 : const int16_t nchan_out, /* i : number of output channels */
75 : const float *proto_matrix /* i : the prototype (upmix) matrix (only used if mode == 1) */
76 : )
77 : {
78 : int16_t idx;
79 :
80 1023 : h_dirac_output_synthesis_params->max_band_decorr = max_band_decorr;
81 :
82 : /*-----------------------------------------------------------------*
83 : * memory allocation
84 : *-----------------------------------------------------------------*/
85 :
86 : /* buffer length and interpolator */
87 1023 : h_dirac_output_synthesis_params->alpha_synthesis = NULL;
88 1023 : if ( ( h_dirac_output_synthesis_params->proto_matrix = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ) ) == NULL )
89 : {
90 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
91 : }
92 :
93 : /* cov buffers */
94 13335 : for ( idx = 0; idx < num_param_bands; idx++ )
95 : {
96 :
97 12312 : if ( ( h_dirac_output_synthesis_state->cx_old[idx] = (float *) malloc( nchan_in * nchan_in * sizeof( float ) ) ) == NULL )
98 : {
99 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
100 : }
101 12312 : if ( ( h_dirac_output_synthesis_state->cy_old[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ) ) == NULL )
102 : {
103 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
104 : }
105 12312 : if ( ( h_dirac_output_synthesis_state->mixing_matrix_old[idx] = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ) ) == NULL )
106 : {
107 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
108 : }
109 12312 : set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in );
110 12312 : set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out );
111 12312 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in );
112 :
113 12312 : if ( ( h_dirac_output_synthesis_state->mixing_matrix[idx] = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ) ) == NULL )
114 : {
115 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
116 : }
117 12312 : set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in );
118 : }
119 50091 : for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
120 : {
121 49068 : h_dirac_output_synthesis_state->cx_old[idx] = NULL;
122 49068 : h_dirac_output_synthesis_state->cy_old[idx] = NULL;
123 49068 : h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL;
124 49068 : h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL;
125 : }
126 :
127 10689 : for ( idx = 0; idx < num_param_bands_residual; idx++ )
128 : {
129 9666 : if ( ( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ) ) == NULL )
130 : {
131 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
132 : }
133 9666 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out );
134 :
135 9666 : if ( ( h_dirac_output_synthesis_state->mixing_matrix_res[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ) ) == NULL )
136 : {
137 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
138 : }
139 9666 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out );
140 : }
141 52737 : for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
142 : {
143 51714 : h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL;
144 51714 : h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL;
145 : }
146 :
147 : /*-----------------------------------------------------------------*
148 : * prepare processing parameters
149 : *-----------------------------------------------------------------*/
150 :
151 : /* compute interpolator */
152 1023 : if ( ( h_dirac_output_synthesis_params->interpolator = (float *) malloc( interp_length * sizeof( float ) ) ) == NULL )
153 : {
154 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
155 : }
156 :
157 33759 : for ( idx = 1; idx <= interp_length; ++idx )
158 : {
159 32736 : h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length;
160 : }
161 :
162 1023 : mvr2r( proto_matrix, h_dirac_output_synthesis_params->proto_matrix, nchan_in * nchan_out );
163 :
164 1023 : return IVAS_ERR_OK;
165 : }
166 :
167 :
168 : /*-------------------------------------------------------------------*
169 : * ivas_dirac_dec_output_synthesis_get_interpolator()
170 : *
171 : *
172 : *-------------------------------------------------------------------*/
173 :
174 983961 : void ivas_dirac_dec_output_synthesis_get_interpolator(
175 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */
176 : const uint16_t interp_length /* i : interpolator length */
177 : )
178 : {
179 : int16_t idx;
180 :
181 4893804 : for ( idx = 1; idx <= interp_length; ++idx )
182 : {
183 3909843 : h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length;
184 : }
185 :
186 983961 : return;
187 : }
188 :
189 :
190 : /*-------------------------------------------------------------------*
191 : * ivas_dirac_dec_output_synthesis_cov_init()
192 : *
193 : * initialize the states for the covariance synthesis
194 : *-------------------------------------------------------------------*/
195 :
196 1023 : void ivas_dirac_dec_output_synthesis_cov_init(
197 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: pointer to the state of the covariance synthesis */
198 : const int16_t nchan_in, /* i : number of input (tranport) channels */
199 : const int16_t nchan_out, /* i : number of output channels */
200 : const int16_t n_param_bands, /* i : number of total parameter bands */
201 : const int16_t n_param_bands_res /* i : number of parameter bands with a residual mixing matrix (i.e. decorrelation */
202 : )
203 : {
204 :
205 : int16_t idx;
206 :
207 : /* initialize buffers */
208 13335 : for ( idx = 0; idx < n_param_bands; idx++ )
209 : {
210 12312 : set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in );
211 12312 : set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out );
212 12312 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in );
213 12312 : set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in );
214 : }
215 :
216 10689 : for ( idx = 0; idx < n_param_bands_res; idx++ )
217 : {
218 9666 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out );
219 9666 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out );
220 : }
221 :
222 1023 : return;
223 : }
224 :
225 :
226 : /*-------------------------------------------------------------------*
227 : * ivas_dirac_dec_output_synthesis_cov_close()
228 : *
229 : * deallocate dynamic memory in the covariance synthesis state
230 : *-------------------------------------------------------------------*/
231 :
232 1023 : void ivas_dirac_dec_output_synthesis_cov_close(
233 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i : handle for the covariance synthesis parameters */
234 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state /* i/o: handle for the covariance synthesis state */
235 : )
236 : {
237 : int16_t idx;
238 :
239 : /*-----------------------------------------------------------------*
240 : * memory deallocation
241 : *-----------------------------------------------------------------*/
242 :
243 : /* free interpolator */
244 1023 : if ( h_dirac_output_synthesis_params->interpolator != NULL )
245 : {
246 1023 : free( h_dirac_output_synthesis_params->interpolator );
247 1023 : h_dirac_output_synthesis_params->interpolator = NULL;
248 : }
249 :
250 : /* free alpha */
251 1023 : if ( h_dirac_output_synthesis_params->alpha_synthesis != NULL )
252 : {
253 0 : free( h_dirac_output_synthesis_params->alpha_synthesis );
254 0 : h_dirac_output_synthesis_params->alpha_synthesis = NULL;
255 : }
256 :
257 : /* free proto_matrix */
258 1023 : if ( h_dirac_output_synthesis_params->proto_matrix != NULL )
259 : {
260 1023 : free( h_dirac_output_synthesis_params->proto_matrix );
261 1023 : h_dirac_output_synthesis_params->proto_matrix = NULL;
262 : }
263 :
264 : /* free cov buffers */
265 62403 : for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
266 : {
267 61380 : if ( h_dirac_output_synthesis_state->cx_old[idx] != NULL )
268 : {
269 12312 : free( h_dirac_output_synthesis_state->cx_old[idx] );
270 12312 : h_dirac_output_synthesis_state->cx_old[idx] = NULL;
271 : }
272 :
273 61380 : if ( h_dirac_output_synthesis_state->cy_old[idx] != NULL )
274 : {
275 12312 : free( h_dirac_output_synthesis_state->cy_old[idx] );
276 12312 : h_dirac_output_synthesis_state->cy_old[idx] = NULL;
277 : }
278 :
279 61380 : if ( h_dirac_output_synthesis_state->mixing_matrix_old[idx] != NULL )
280 : {
281 12312 : free( h_dirac_output_synthesis_state->mixing_matrix_old[idx] );
282 12312 : h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL;
283 : }
284 :
285 61380 : if ( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] != NULL )
286 : {
287 9666 : free( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] );
288 9666 : h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL;
289 : }
290 :
291 61380 : if ( h_dirac_output_synthesis_state->mixing_matrix[idx] != NULL )
292 : {
293 12312 : free( h_dirac_output_synthesis_state->mixing_matrix[idx] );
294 12312 : h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL;
295 : }
296 :
297 61380 : if ( h_dirac_output_synthesis_state->mixing_matrix_res[idx] != NULL )
298 : {
299 9666 : free( h_dirac_output_synthesis_state->mixing_matrix_res[idx] );
300 9666 : h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL;
301 : }
302 : }
303 :
304 1023 : return;
305 : }
306 :
307 :
308 : /*-------------------------------------------------------------------*
309 : * ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot()
310 : *
311 : * collect the multi channel input covariance for one filter bank time slot
312 : *-------------------------------------------------------------------*/
313 :
314 6255285 : void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot(
315 : float *RealBuffer, /* i : input channel filter bank samples (real part) */
316 : float *ImagBuffer, /* i : input channel filter bank samples (imaginary part */
317 : float cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (real part) */
318 : float cx_imag[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (imaginary part) */
319 : const int16_t param_band, /* i : parameter band */
320 : PARAM_MC_DEC_HANDLE hParamMC, /* i : handle to Parametric MC state */
321 : const int16_t nchan_in /* i : number of input channels */
322 : )
323 : {
324 : int16_t band_idx, ch_idx;
325 : int16_t brange[2];
326 : float real_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * MAX_TRANSPORT_CHANNELS];
327 : float imag_in_buffer[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * MAX_TRANSPORT_CHANNELS];
328 : float real_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
329 : float imag_buffer[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
330 :
331 : /* estimate input covariance */
332 : /* Already stack here instead of in the process_subframe */
333 :
334 : /* collect input frame */
335 : int16_t num_bands;
336 6255285 : brange[0] = hParamMC->band_grouping[param_band];
337 6255285 : brange[1] = hParamMC->band_grouping[param_band + 1];
338 6255285 : num_bands = brange[1] - brange[0];
339 :
340 32753805 : for ( band_idx = 0; band_idx < num_bands; band_idx++ )
341 : {
342 26498520 : int16_t band = brange[0] + band_idx;
343 79701840 : for ( ch_idx = 0; ch_idx < nchan_in; ch_idx++ )
344 : {
345 53203320 : real_in_buffer[band_idx + num_bands * ch_idx] = RealBuffer[ch_idx * hParamMC->num_freq_bands + band];
346 53203320 : imag_in_buffer[band_idx + num_bands * ch_idx] = ImagBuffer[ch_idx * hParamMC->num_freq_bands + band];
347 : }
348 : }
349 :
350 6255285 : cmplx_matrix_square( real_in_buffer, imag_in_buffer, num_bands, nchan_in, real_buffer, imag_buffer );
351 :
352 6255285 : v_add( cx, real_buffer, cx, nchan_in * nchan_in );
353 :
354 6255285 : v_add( cx_imag, imag_buffer, cx_imag, nchan_in * nchan_in );
355 :
356 :
357 6255285 : return;
358 : }
359 :
360 :
361 : /*-------------------------------------------------------------------*
362 : * ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot()
363 : *
364 : * synthesize one filter bank slot of multi channel output filter bank
365 : * samples with the covariance synthesis
366 : *-------------------------------------------------------------------*/
367 :
368 491193 : void ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot(
369 : float *Cldfb_RealBuffer_in, /* i : input channel filter bank samples (real part) */
370 : float *Cldfb_ImagBuffer_in, /* i : input channel filter bank samples (imaginary part) */
371 : float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) */
372 : float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) */
373 : float *mixing_matrix[], /* i : parameter band wise mixing matrices (direct part) */
374 : float *mixing_matrix_res[], /* i : parameter band wise mixing matrices (residual part) */
375 : const uint16_t slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */
376 : const uint16_t slot_idx_tot, /* i : time slot index for the current slot within the frame */
377 : const int16_t nX, /* i : number of input channels */
378 : const int16_t nY, /* i : number of output channels */
379 : PARAM_MC_DEC_HANDLE hParamMC /* i : handle to the Parametric MC decoder state */
380 : )
381 : {
382 : int16_t param_band_idx, band, ch_idx;
383 : float mixing_matrix_smooth[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS];
384 : float mixing_matrix_res_smooth[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
385 : float mixing_matrix_buffer[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
386 : int16_t have_residual;
387 : float input_f_real[PARAM_MC_MAX_TRANSPORT_CHANS];
388 : float input_f_imag[PARAM_MC_MAX_TRANSPORT_CHANS];
389 : float output_f_real[MAX_CICP_CHANNELS];
390 : float output_f_imag[MAX_CICP_CHANNELS];
391 : float diff_f_real[MAX_CICP_CHANNELS];
392 : float diff_f_imag[MAX_CICP_CHANNELS];
393 : int16_t brange[2];
394 491193 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE h_synthesis_state = hParamMC->h_output_synthesis_cov_state;
395 :
396 491193 : set_zero( input_f_real, PARAM_MC_MAX_TRANSPORT_CHANS );
397 491193 : set_zero( input_f_imag, PARAM_MC_MAX_TRANSPORT_CHANS );
398 491193 : set_zero( output_f_real, MAX_CICP_CHANNELS );
399 491193 : set_zero( output_f_imag, MAX_CICP_CHANNELS );
400 491193 : set_zero( diff_f_real, MAX_CICP_CHANNELS );
401 491193 : set_zero( diff_f_imag, MAX_CICP_CHANNELS );
402 :
403 6867210 : for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx++ )
404 : {
405 : /* final mixing */
406 6376017 : have_residual = 0;
407 6376017 : brange[0] = hParamMC->band_grouping[param_band_idx];
408 6376017 : brange[1] = hParamMC->band_grouping[param_band_idx + 1];
409 :
410 6376017 : if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr )
411 : {
412 5130792 : have_residual = 1;
413 : }
414 :
415 : /* mixing matrix interpolation*/
416 6376017 : v_multc( mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_smooth, nY * nX );
417 6376017 : v_multc( h_synthesis_state.mixing_matrix_old[param_band_idx], 1.0f - hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_buffer, nY * nX );
418 6376017 : v_add( mixing_matrix_smooth, mixing_matrix_buffer, mixing_matrix_smooth, nY * nX );
419 :
420 6376017 : if ( have_residual )
421 : {
422 : /* residual mixing matrix interpolation*/
423 5130792 : v_multc( mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_res_smooth, nY * nY );
424 5130792 : v_multc( h_synthesis_state.mixing_matrix_res_old[param_band_idx], 1.0f - hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_buffer, nY * nY );
425 5130792 : v_add( mixing_matrix_res_smooth, mixing_matrix_buffer, mixing_matrix_res_smooth, nY * nY );
426 : }
427 :
428 33366777 : for ( band = brange[0]; band < brange[1]; band++ )
429 : {
430 26990760 : assert( band >= 0 );
431 :
432 26990760 : if ( have_residual )
433 : {
434 : /* collect diffuse prototypes */
435 9823860 : assert( band < hParamMC->h_output_synthesis_params.max_band_decorr );
436 69823380 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
437 : {
438 59999520 : diff_f_real[ch_idx] = Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band];
439 59999520 : diff_f_imag[ch_idx] = Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band];
440 : }
441 :
442 : /* apply residual mixing */
443 9823860 : matrix_product( mixing_matrix_res_smooth, nY, nY, 0, diff_f_real, nY, 1, 0, output_f_real );
444 9823860 : matrix_product( mixing_matrix_res_smooth, nY, nY, 0, diff_f_imag, nY, 1, 0, output_f_imag );
445 :
446 69823380 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
447 : {
448 59999520 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] = output_f_real[ch_idx];
449 59999520 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] = output_f_imag[ch_idx];
450 : }
451 : }
452 : else
453 : {
454 121858260 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
455 : {
456 104691360 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] = 0.0f;
457 104691360 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] = 0.0f;
458 : }
459 : }
460 :
461 : /* collect input signals, still in cldfb buffers */
462 81202680 : for ( ch_idx = 0; ch_idx < nX; ch_idx++ )
463 : {
464 54211920 : input_f_real[ch_idx] = Cldfb_RealBuffer_in[ch_idx * hParamMC->num_freq_bands + band];
465 54211920 : input_f_imag[ch_idx] = Cldfb_ImagBuffer_in[ch_idx * hParamMC->num_freq_bands + band];
466 : }
467 :
468 : /* apply mixing matrix */
469 26990760 : matrix_product( mixing_matrix_smooth, nY, nX, 0, input_f_real, nX, 1, 0, output_f_real );
470 26990760 : matrix_product( mixing_matrix_smooth, nY, nX, 0, input_f_imag, nX, 1, 0, output_f_imag );
471 :
472 : /* collect output */
473 191681640 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
474 : {
475 164690880 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] += output_f_real[ch_idx];
476 164690880 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] += output_f_imag[ch_idx];
477 : }
478 : }
479 : }
480 :
481 491193 : return;
482 : }
483 :
484 :
485 : /*-------------------------------------------------------------------*
486 : * computeMixingMatrices()
487 : *
488 : * compute a mixing matrix using the convariance synthesis approach
489 : *-------------------------------------------------------------------*/
490 :
491 398496 : int16_t computeMixingMatrices(
492 : const int16_t num_inputs, /* i : number of input channels */
493 : const int16_t num_outputs, /* i : number of output channels */
494 : const float *Cx, /* i : input channel covariance matrix */
495 : const float *Cy, /* i : target covariance matrix */
496 : const float *Q, /* i : prototype matrix (usually a upmix matrix) */
497 : const int16_t energy_compensation_flag, /* i : flag indicating that the energy compensation should be performed (i.e. no residual mixing matrix will follow) */
498 : const float reg_Sx, /* i : regularization factor for the input channel singular values */
499 : const float reg_ghat, /* i : regularization factor for the normalization matrix */
500 : float *mixing_matrix, /* o : resulting mixing matrix */
501 : float *Cr /* o : residual covariance matrix */
502 : )
503 : {
504 : int16_t i, j;
505 398496 : int16_t out = EXIT_SUCCESS;
506 : int16_t nL, nC;
507 398496 : int16_t lengthCx = num_inputs;
508 398496 : int16_t lengthCy = num_outputs;
509 : float *Cr_p, *Cy_tilde_p;
510 : const float *Cy_p;
511 : float *adj;
512 : float limit;
513 : float svd_in_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
514 : float svd_u_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
515 : float svd_s_buffer[MAX_OUTPUT_CHANNELS];
516 : float svd_v_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
517 : float Kx[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
518 : float Ky[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
519 : float Kx_reg_inv[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
520 : float Q_Cx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
521 : float Cy_hat_diag[MAX_OUTPUT_CHANNELS];
522 : float G_hat[MAX_OUTPUT_CHANNELS];
523 : float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
524 : float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
525 : float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
526 :
527 398496 : push_wmops( "dirac_cov_mix_mat" );
528 :
529 398496 : set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS );
530 6774432 : for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
531 : {
532 6375936 : set_zero( svd_in_buffer[i], MAX_OUTPUT_CHANNELS );
533 6375936 : set_zero( svd_u_buffer[i], MAX_OUTPUT_CHANNELS );
534 6375936 : set_zero( svd_v_buffer[i], MAX_OUTPUT_CHANNELS );
535 : }
536 :
537 : /*-----------------------------------------------------------------*
538 : * Decomposition of Cy
539 : *-----------------------------------------------------------------*/
540 :
541 : /* Processing the SVD */
542 398496 : mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 );
543 :
544 398496 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy );
545 :
546 : /* Computing Ky */
547 2438223 : for ( i = 0; i < lengthCy; ++i )
548 : {
549 12633024 : for ( j = 0; j < lengthCy; ++j )
550 : {
551 10593297 : Ky[i + j * lengthCy] = svd_u_buffer[i][j] * sqrtf( svd_s_buffer[j] );
552 : }
553 : }
554 :
555 : /*-----------------------------------------------------------------*
556 : * Decomposition of Cx
557 : *-----------------------------------------------------------------*/
558 :
559 : /* Processing the SVD */
560 398496 : mat2svdMat( Cx, svd_in_buffer, lengthCx, lengthCx, 0 );
561 :
562 398496 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCx );
563 :
564 : /* Computing Kx */
565 1199568 : for ( i = 0; i < lengthCx; ++i )
566 : {
567 2415456 : for ( j = 0; j < lengthCx; ++j )
568 : {
569 1614384 : Kx[i + j * lengthCx] = svd_u_buffer[i][j] * sqrtf( svd_s_buffer[j] );
570 : }
571 : }
572 :
573 : /* Sx = sqrt(Sx) */
574 1199568 : for ( i = 0; i < lengthCx; ++i )
575 : {
576 801072 : svd_s_buffer[i] = sqrtf( svd_s_buffer[i] );
577 : }
578 :
579 : /*-----------------------------------------------------------------*
580 : * Regularization of Sx
581 : *-----------------------------------------------------------------*/
582 :
583 398496 : maximum( svd_s_buffer, lengthCx, &limit );
584 398496 : limit = (float) max( limit * reg_Sx, SQRT_EPSILON );
585 1199568 : for ( i = 0; i < lengthCx; ++i )
586 : {
587 801072 : svd_s_buffer[i] = ( ( svd_s_buffer[i] > limit ) ? svd_s_buffer[i] : limit );
588 : }
589 :
590 398496 : limit = 0.0f;
591 :
592 : /*-----------------------------------------------------------------*
593 : * regularized Kx-1
594 : *-----------------------------------------------------------------*/
595 :
596 1199568 : for ( i = 0; i < lengthCx; ++i )
597 : {
598 801072 : float reg_fac = ( 1.0f / svd_s_buffer[i] );
599 :
600 2415456 : for ( j = 0; j < lengthCx; ++j )
601 : {
602 1614384 : Kx_reg_inv[i + j * lengthCx] = reg_fac * svd_u_buffer[j][i];
603 : }
604 : }
605 :
606 : /*-----------------------------------------------------------------*
607 : * normalization matrix G hat
608 : *-----------------------------------------------------------------*/
609 :
610 : /* Computing Q*Cx*Q' */
611 398496 : matrix_product( Q, lengthCy, lengthCx, 0, Cx, lengthCx, lengthCx, 0, Q_Cx );
612 :
613 398496 : matrix_product_diag( Q_Cx, lengthCy, lengthCx, 0, Q, lengthCy, lengthCx, 1, Cy_hat_diag );
614 :
615 : /* Computing Cy_hat_diag */
616 2438223 : for ( i = 0; i < lengthCy; ++i )
617 : {
618 2039727 : if ( Cy_hat_diag[i] > limit )
619 : {
620 1016814 : limit = Cy_hat_diag[i];
621 : }
622 : }
623 :
624 398496 : limit = limit * reg_ghat + EPSILON;
625 :
626 : /* Computing G_hat */
627 2438223 : for ( i = 0; i < lengthCy; ++i )
628 : {
629 2039727 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
630 : {
631 54 : Cy_hat_diag[i] = limit;
632 : }
633 :
634 2039727 : G_hat[i] = sqrtf( Cy[i + i * lengthCy] / Cy_hat_diag[i] );
635 : }
636 :
637 : /*-----------------------------------------------------------------*
638 : * Formulate optimal P
639 : *-----------------------------------------------------------------*/
640 :
641 : /* Computing the input matrix Kx'*Q'*G_hat'*Ky */
642 398496 : matrix_product( Kx, lengthCx, lengthCx, 1, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 );
643 398496 : matrix_diag_product( mat_mult_buffer1, lengthCx, lengthCy, 0, G_hat, lengthCy, mat_mult_buffer2 );
644 398496 : matrix_product( mat_mult_buffer2, lengthCx, lengthCy, 0, Ky, lengthCy, lengthCy, 0, mat_mult_buffer1 );
645 :
646 398496 : if ( lengthCx < lengthCy )
647 : {
648 398496 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 1 );
649 :
650 398496 : nL = lengthCy;
651 398496 : nC = lengthCx;
652 :
653 398496 : svd( svd_in_buffer, svd_v_buffer, svd_s_buffer, svd_u_buffer, nL, nC );
654 : }
655 : else
656 : {
657 0 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 );
658 :
659 0 : nL = lengthCx;
660 0 : nC = lengthCy;
661 :
662 0 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, nL, nC );
663 : }
664 :
665 : /* Actually Processing P */
666 :
667 : /* can be skipped: lambda is always column-truncated identity matrix, so this operation just
668 : truncates V to num_input_channel columns */
669 :
670 398496 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx );
671 398496 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
672 :
673 398496 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0,
674 : mat_mult_buffer2, lengthCx, lengthCx, 1,
675 : mat_mult_buffer3 );
676 :
677 : /************************ Formulate M **********************/
678 :
679 398496 : matrix_product( Ky, lengthCy, lengthCy, 0, mat_mult_buffer3, lengthCy, lengthCx, 0, mat_mult_buffer1 );
680 398496 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, Kx_reg_inv, lengthCx, lengthCx, 0, mixing_matrix );
681 :
682 : /*-----------------------------------------------------------------*
683 : * Formulate Cr
684 : *-----------------------------------------------------------------*/
685 :
686 : /* Compute Cy_tilde = M*Cx*M' */
687 398496 : matrix_product( mixing_matrix, lengthCy, lengthCx, 0, Cx, lengthCx, lengthCx, 0, mat_mult_buffer1 );
688 398496 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, mat_mult_buffer2 );
689 :
690 : /* Compute Cr = Cy - Cy_tilde */
691 398496 : Cr_p = Cr;
692 398496 : Cy_p = Cy;
693 398496 : Cy_tilde_p = mat_mult_buffer2;
694 2438223 : for ( i = 0; i < lengthCy; ++i )
695 : {
696 12633024 : for ( j = 0; j < lengthCy; ++j )
697 : {
698 10593297 : *( Cr_p++ ) = *( Cy_p++ ) - *( Cy_tilde_p++ );
699 : }
700 :
701 : /* Avoid Meaningless negative main diagonal elements */
702 2039727 : if ( Cr[i + i * lengthCy] < 0.0f )
703 : {
704 232755 : Cr[i + i * lengthCy] = 0.0f;
705 : }
706 : }
707 :
708 : /*-----------------------------------------------------------------*
709 : * Energy Compensation
710 : *-----------------------------------------------------------------*/
711 :
712 398496 : if ( energy_compensation_flag == 1 )
713 : {
714 77826 : adj = svd_s_buffer;
715 77826 : Cy_tilde_p = mat_mult_buffer2;
716 475116 : for ( i = 0; i < lengthCy; ++i )
717 : {
718 : /* Avoid correction for very small energies,
719 : main diagonal elements of Cy_tilde_p may be negative */
720 397290 : if ( Cy_tilde_p[i + i * lengthCy] < 0.0f )
721 : {
722 0 : adj[i] = 1.0f;
723 : }
724 : else
725 : {
726 397290 : adj[i] = sqrtf( Cy[i + lengthCy * i] / ( Cy_tilde_p[i + i * lengthCy] + EPSILON ) );
727 : }
728 :
729 397290 : if ( adj[i] > 4.0f )
730 : {
731 15 : adj[i] = 4.0f;
732 : }
733 : }
734 :
735 77826 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
736 :
737 77826 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
738 : }
739 398496 : pop_wmops();
740 :
741 398496 : return out;
742 : }
743 :
744 :
745 : /*-------------------------------------------------------------------*
746 : * computeMixingMatricesResidual()
747 : *
748 : * compute a residual mixing matrix using the covariance synthesis approach
749 : *-------------------------------------------------------------------*/
750 :
751 320670 : int16_t computeMixingMatricesResidual(
752 : const int16_t num_outputs, /* i : number of output channels */
753 : const float *Cx, /* i : vector containing the diagonal diffuse prototype covariance */
754 : const float *Cy, /* i : matrix containing the missing cov (Cr from computeMixingMatrices()) */
755 : const float reg_Sx, /* i : regularization factor for the input channel singular values */
756 : const float reg_ghat, /* i : regularization factor for the normalization matrix */
757 : float *mixing_matrix /* o : resulting residual mixing matrix */
758 : )
759 : {
760 : int16_t i, j;
761 320670 : int16_t out = EXIT_SUCCESS;
762 320670 : int16_t lengthCx = num_outputs;
763 320670 : int16_t lengthCy = num_outputs;
764 : float *adj;
765 : float limit;
766 : float svd_in_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
767 : float svd_u_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
768 : float svd_s_buffer[MAX_OUTPUT_CHANNELS];
769 : float svd_v_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
770 : float Kx[MAX_OUTPUT_CHANNELS];
771 : float Ky[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
772 : float Kx_reg_inv[MAX_OUTPUT_CHANNELS];
773 : float Cy_hat_diag[MAX_OUTPUT_CHANNELS];
774 : float G_hat[MAX_OUTPUT_CHANNELS];
775 : float Cy_tilde[MAX_OUTPUT_CHANNELS];
776 : float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
777 : float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
778 : float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
779 :
780 320670 : push_wmops( "dirac_cov_mix_mat_r" );
781 :
782 : /*-----------------------------------------------------------------*
783 : * Decomposition of Cy
784 : *-----------------------------------------------------------------*/
785 :
786 : /* Processing the SVD */
787 :
788 : /* linear array to svd buffer */
789 320670 : mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 );
790 :
791 320670 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy );
792 :
793 : /* Computing Ky */
794 1963107 : for ( i = 0; i < lengthCy; ++i )
795 : {
796 10179204 : for ( j = 0; j < lengthCy; ++j )
797 : {
798 8536767 : Ky[i + j * lengthCy] = svd_u_buffer[i][j] * sqrtf( svd_s_buffer[j] );
799 : }
800 : }
801 :
802 : /*-----------------------------------------------------------------*
803 : * Decomposition of Cx
804 : *-----------------------------------------------------------------*/
805 :
806 : /* Processing the SVD of Cx*/
807 : /* Cx is a diagonal matrix, so SVD would lead to the sorted diagonal as S and u
808 : * would be just indicating the sorting index, so go straight to Kx as the
809 : * square root of the diagonal of Cx */
810 :
811 : /* Computing Kx */
812 1963107 : for ( i = 0; i < lengthCx; ++i )
813 : {
814 1642437 : Kx[i] = sqrtf( Cx[i] );
815 : }
816 :
817 : /*-----------------------------------------------------------------*
818 : * Regularization of Sx
819 : *-----------------------------------------------------------------*/
820 :
821 320670 : maximum( Kx, lengthCx, &limit );
822 320670 : limit = limit * reg_Sx + EPSILON;
823 :
824 1963107 : for ( i = 0; i < lengthCx; ++i )
825 : {
826 1642437 : float reg_fac = ( 1.0f / ( ( Kx[i] > limit ) ? Kx[i] : limit ) );
827 1642437 : Kx_reg_inv[i] = reg_fac;
828 : }
829 :
830 320670 : limit = 0.0f;
831 :
832 : /*-----------------------------------------------------------------*
833 : * regularized Kx-1
834 : *-----------------------------------------------------------------*/
835 :
836 : /*-----------------------------------------------------------------*
837 : * normalization matrix G hat
838 : *-----------------------------------------------------------------*/
839 :
840 : /* Computing Cy_hat_diag */
841 320670 : mvr2r( Cx, Cy_hat_diag, num_outputs );
842 :
843 1963107 : for ( i = 0; i < lengthCy; ++i )
844 : {
845 1642437 : if ( Cy_hat_diag[i] > limit )
846 : {
847 818316 : limit = Cy_hat_diag[i];
848 : }
849 : }
850 :
851 320670 : limit = limit * reg_ghat + EPSILON;
852 :
853 : /* Computing G_hat */
854 1963107 : for ( i = 0; i < lengthCy; ++i )
855 : {
856 1642437 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
857 : {
858 45 : Cy_hat_diag[i] = limit;
859 : }
860 1642437 : G_hat[i] = sqrtf( Cy[i + i * lengthCy] / Cy_hat_diag[i] );
861 : }
862 :
863 : /*-----------------------------------------------------------------*
864 : * Formulate optimal P
865 : *-----------------------------------------------------------------*/
866 :
867 1963107 : for ( i = 0; i < num_outputs; i++ )
868 : {
869 1642437 : Kx[i] *= G_hat[i];
870 : }
871 :
872 1963107 : for ( i = 0; i < num_outputs; i++ )
873 : {
874 1642437 : float fac = Kx[i];
875 :
876 10179204 : for ( j = 0; j < num_outputs; j++ )
877 : {
878 8536767 : mat_mult_buffer1[i + j * num_outputs] = Ky[i + j * num_outputs] * fac;
879 : }
880 : }
881 :
882 320670 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 );
883 :
884 320670 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCy );
885 :
886 : /* Actually Processing P */
887 320670 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx );
888 320670 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
889 :
890 320670 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0,
891 : mat_mult_buffer2, lengthCx, lengthCx, 1,
892 : mat_mult_buffer3 );
893 :
894 : /*-----------------------------------------------------------------*
895 : * Formulate M
896 : *-----------------------------------------------------------------*/
897 :
898 320670 : matrix_product( Ky, lengthCy, lengthCy, 0, mat_mult_buffer3, lengthCy, lengthCx, 0, mat_mult_buffer1 );
899 :
900 1963107 : for ( i = 0; i < num_outputs; i++ )
901 : {
902 1642437 : float fac = Kx_reg_inv[i];
903 :
904 10179204 : for ( j = 0; j < num_outputs; j++ )
905 : {
906 8536767 : mixing_matrix[j + i * num_outputs] = mat_mult_buffer1[j + i * num_outputs] * fac;
907 : }
908 : }
909 :
910 : /*-----------------------------------------------------------------*
911 : * Formulate Cr
912 : *-----------------------------------------------------------------*/
913 :
914 : /* Compute Cy_tilde = M*Cx*M' */
915 320670 : matrix_diag_product( mixing_matrix, lengthCy, lengthCx, 0, Cx, lengthCx, mat_mult_buffer1 );
916 :
917 320670 : matrix_product_diag( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, Cy_tilde );
918 :
919 : /*-----------------------------------------------------------------*
920 : * Energy Compensation
921 : *-----------------------------------------------------------------*/
922 :
923 320670 : adj = svd_s_buffer;
924 :
925 1963107 : for ( i = 0; i < lengthCy; ++i )
926 : {
927 1642437 : adj[i] = sqrtf( Cy[i + lengthCy * i] / ( Cy_tilde[i] + EPSILON ) );
928 1642437 : if ( adj[i] > 4.0f )
929 : {
930 9 : adj[i] = 4.0f;
931 : }
932 : }
933 :
934 320670 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
935 :
936 320670 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
937 :
938 320670 : pop_wmops();
939 :
940 320670 : return out;
941 : }
942 :
943 :
944 : /*-------------------------------------------------------------------*
945 : * computeMixingMatricesISM()
946 : *
947 : *
948 : *-------------------------------------------------------------------*/
949 :
950 1216440 : int16_t computeMixingMatricesISM(
951 : const int16_t num_inputs,
952 : const int16_t num_responses,
953 : const int16_t num_outputs,
954 : const float *responses,
955 : const float *ener,
956 : const float *Cx_diag,
957 : const float *Cy_diag,
958 : const float *Q,
959 : const int16_t energy_compensation_flag,
960 : const float reg_Sx,
961 : const float reg_ghat,
962 : float *mixing_matrix )
963 : {
964 : int16_t i, out;
965 : int16_t lengthCx, lengthCy;
966 : float *Cy_tilde_p;
967 : float *adj;
968 : float limit;
969 : float svd_in_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
970 : float svd_u_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
971 : float svd_s_buffer[MAX_OUTPUT_CHANNELS];
972 : float svd_v_buffer[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
973 : float Kx[MAX_TRANSPORT_CHANNELS];
974 : float Ky[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
975 : float Kx_reg_inv[MAX_TRANSPORT_CHANNELS];
976 : float Q_Cx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
977 : float Cy_hat_diag[MAX_OUTPUT_CHANNELS];
978 : float G_hat[MAX_OUTPUT_CHANNELS];
979 : float mat_mult_buffer1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
980 : float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
981 : float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
982 : int16_t nL, nC;
983 :
984 1216440 : push_wmops( "dirac_cov_mix_mat" );
985 :
986 1216440 : out = EXIT_SUCCESS;
987 1216440 : lengthCx = num_inputs;
988 1216440 : lengthCy = num_outputs;
989 :
990 1216440 : set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS );
991 20679480 : for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
992 : {
993 19463040 : set_zero( svd_in_buffer[i], MAX_OUTPUT_CHANNELS );
994 19463040 : set_zero( svd_u_buffer[i], MAX_OUTPUT_CHANNELS );
995 19463040 : set_zero( svd_v_buffer[i], MAX_OUTPUT_CHANNELS );
996 : }
997 :
998 : /* Decomposition of Cy = Ky*Ky' */
999 : /* Ky = responses*diag(ener) */
1000 1216440 : matrix_diag_product( responses, lengthCy, num_responses, 0, ener, num_responses, Ky );
1001 :
1002 : /* Decomposition of Cx -> Computing Kx */
1003 1216440 : v_sqrt( Cx_diag, Kx, lengthCx );
1004 :
1005 : /* Regularization of Sx */
1006 1216440 : maximum( Kx, lengthCx, &limit );
1007 1216440 : limit = limit * reg_Sx + EPSILON;
1008 :
1009 3649320 : for ( i = 0; i < lengthCx; ++i )
1010 : {
1011 2432880 : svd_s_buffer[i] = ( ( Kx[i] > limit ) ? Kx[i] : limit );
1012 : }
1013 :
1014 1216440 : limit = 0.0f;
1015 :
1016 : /* regularized Kx-1 */
1017 :
1018 3649320 : for ( i = 0; i < lengthCx; ++i )
1019 : {
1020 2432880 : float reg_fac = ( 1.0f / svd_s_buffer[i] );
1021 2432880 : Kx_reg_inv[i] = reg_fac;
1022 : }
1023 :
1024 : /************************ normalization matrix G hat **********************/
1025 :
1026 : /* Computing Q*Cx*Q' */
1027 1216440 : matrix_diag_product( Q, lengthCy, lengthCx, 0, Cx_diag, lengthCx, Q_Cx );
1028 1216440 : matrix_product_diag( Q_Cx, lengthCy, lengthCx, 0, Q, lengthCy, lengthCx, 1, Cy_hat_diag );
1029 :
1030 : /* Computing Cy_hat_diag */
1031 12833100 : for ( i = 0; i < lengthCy; ++i )
1032 : {
1033 11616660 : if ( Cy_hat_diag[i] > limit )
1034 : {
1035 1820064 : limit = Cy_hat_diag[i];
1036 : }
1037 : }
1038 :
1039 :
1040 1216440 : limit = limit * reg_ghat + EPSILON;
1041 :
1042 : /* Computing G_hat */
1043 12833100 : for ( i = 0; i < lengthCy; ++i )
1044 : {
1045 11616660 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
1046 : {
1047 130254 : Cy_hat_diag[i] = limit;
1048 : }
1049 11616660 : G_hat[i] = sqrtf( Cy_diag[i] / Cy_hat_diag[i] );
1050 : }
1051 :
1052 : /************************ Formulate optimal P **********************/
1053 :
1054 : /* Computing the input matrix Kx'*Q'*G_hat'*Ky */
1055 1216440 : diag_matrix_product( Kx, lengthCx, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 );
1056 1216440 : matrix_diag_product( mat_mult_buffer1, lengthCx, lengthCy, 0, G_hat, lengthCy, mat_mult_buffer2 );
1057 1216440 : matrix_product( mat_mult_buffer2, lengthCx, lengthCy, 0, Ky, lengthCy, num_responses, 0, mat_mult_buffer1 );
1058 :
1059 1216440 : if ( lengthCx < num_responses )
1060 : {
1061 10800 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 1 );
1062 10800 : nL = num_responses;
1063 10800 : nC = lengthCx;
1064 10800 : svd( svd_in_buffer, svd_v_buffer, svd_s_buffer, svd_u_buffer, nL, nC );
1065 : }
1066 : else
1067 : {
1068 1205640 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 0 );
1069 1205640 : nL = lengthCx;
1070 1205640 : nC = num_responses;
1071 1205640 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, nL, nC );
1072 : }
1073 :
1074 : /* Actually Processing P */
1075 :
1076 : /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */
1077 1216440 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, num_responses, lengthCx );
1078 1216440 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
1079 :
1080 1216440 : matrix_product( mat_mult_buffer1, num_responses, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 );
1081 :
1082 : /************************ Formulate M **********************/
1083 :
1084 1216440 : matrix_product( Ky, lengthCy, num_responses, 0, mat_mult_buffer3, num_responses, lengthCx, 0, mat_mult_buffer1 );
1085 :
1086 1216440 : matrix_diag_product( mat_mult_buffer1, lengthCy, lengthCx, 0, Kx_reg_inv, lengthCx, mixing_matrix );
1087 :
1088 : /*********************** Energy Compensation ****************/
1089 :
1090 : /* Compute Cy_tilde = M*Cx*M' */
1091 1216440 : matrix_diag_product( mixing_matrix, lengthCy, lengthCx, 0, Cx_diag, lengthCx, mat_mult_buffer1 );
1092 1216440 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, mat_mult_buffer2 );
1093 :
1094 1216440 : if ( energy_compensation_flag == 1 )
1095 : {
1096 1216440 : adj = svd_s_buffer;
1097 1216440 : Cy_tilde_p = mat_mult_buffer2;
1098 12833100 : for ( i = 0; i < lengthCy; ++i )
1099 : {
1100 : /* Avoid correction for very small energies, main diagonal elements of Cy_tilde_p may be negative */
1101 11616660 : if ( Cy_tilde_p[i + i * lengthCy] < 0.0f )
1102 : {
1103 0 : adj[i] = 1.0f;
1104 : }
1105 : else
1106 : {
1107 11616660 : adj[i] = sqrtf( Cy_diag[i] / ( Cy_tilde_p[i + i * lengthCy] + EPSILON ) );
1108 : }
1109 :
1110 11616660 : if ( adj[i] > 4.0f )
1111 : {
1112 39564 : adj[i] = 4.0f;
1113 : }
1114 : }
1115 :
1116 1216440 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
1117 :
1118 1216440 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
1119 : }
1120 :
1121 1216440 : pop_wmops();
1122 :
1123 1216440 : return out;
1124 : }
|