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 6632 : 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 6632 : h_dirac_output_synthesis_params->max_band_decorr = max_band_decorr;
81 :
82 : /*-----------------------------------------------------------------*
83 : * memory allocation
84 : *-----------------------------------------------------------------*/
85 :
86 : /* buffer length and interpolator */
87 6632 : h_dirac_output_synthesis_params->alpha_synthesis = NULL;
88 6632 : 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 93734 : for ( idx = 0; idx < num_param_bands; idx++ )
95 : {
96 :
97 87102 : 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 87102 : 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 87102 : 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 87102 : set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in );
110 87102 : set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out );
111 87102 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in );
112 :
113 87102 : 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 87102 : set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in );
118 : }
119 317450 : for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
120 : {
121 310818 : h_dirac_output_synthesis_state->cx_old[idx] = NULL;
122 310818 : h_dirac_output_synthesis_state->cy_old[idx] = NULL;
123 310818 : h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL;
124 310818 : h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL;
125 : }
126 :
127 71416 : for ( idx = 0; idx < num_param_bands_residual; idx++ )
128 : {
129 64784 : 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 64784 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out );
134 :
135 64784 : 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 64784 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out );
140 : }
141 339768 : for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
142 : {
143 333136 : h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL;
144 333136 : h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL;
145 : }
146 :
147 : /*-----------------------------------------------------------------*
148 : * prepare processing parameters
149 : *-----------------------------------------------------------------*/
150 :
151 : /* compute interpolator */
152 6632 : 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 218856 : for ( idx = 1; idx <= interp_length; ++idx )
158 : {
159 212224 : h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length;
160 : }
161 :
162 6632 : mvr2r( proto_matrix, h_dirac_output_synthesis_params->proto_matrix, nchan_in * nchan_out );
163 :
164 6632 : return IVAS_ERR_OK;
165 : }
166 :
167 :
168 : /*-------------------------------------------------------------------*
169 : * ivas_dirac_dec_output_synthesis_get_interpolator()
170 : *
171 : *
172 : *-------------------------------------------------------------------*/
173 :
174 12730928 : 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 63485255 : for ( idx = 1; idx <= interp_length; ++idx )
182 : {
183 50754327 : h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length;
184 : }
185 :
186 12730928 : 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 6632 : 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 93734 : for ( idx = 0; idx < n_param_bands; idx++ )
209 : {
210 87102 : set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in );
211 87102 : set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out );
212 87102 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in );
213 87102 : set_zero( h_dirac_output_synthesis_state->mixing_matrix[idx], nchan_out * nchan_in );
214 : }
215 :
216 71416 : for ( idx = 0; idx < n_param_bands_res; idx++ )
217 : {
218 64784 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out );
219 64784 : set_zero( h_dirac_output_synthesis_state->mixing_matrix_res[idx], nchan_out * nchan_out );
220 : }
221 :
222 6632 : 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 6632 : 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 6632 : if ( h_dirac_output_synthesis_params->interpolator != NULL )
245 : {
246 6632 : free( h_dirac_output_synthesis_params->interpolator );
247 6632 : h_dirac_output_synthesis_params->interpolator = NULL;
248 : }
249 :
250 : /* free alpha */
251 6632 : 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 6632 : if ( h_dirac_output_synthesis_params->proto_matrix != NULL )
259 : {
260 6632 : free( h_dirac_output_synthesis_params->proto_matrix );
261 6632 : h_dirac_output_synthesis_params->proto_matrix = NULL;
262 : }
263 :
264 : /* free cov buffers */
265 404552 : for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
266 : {
267 397920 : if ( h_dirac_output_synthesis_state->cx_old[idx] != NULL )
268 : {
269 87102 : free( h_dirac_output_synthesis_state->cx_old[idx] );
270 87102 : h_dirac_output_synthesis_state->cx_old[idx] = NULL;
271 : }
272 :
273 397920 : if ( h_dirac_output_synthesis_state->cy_old[idx] != NULL )
274 : {
275 87102 : free( h_dirac_output_synthesis_state->cy_old[idx] );
276 87102 : h_dirac_output_synthesis_state->cy_old[idx] = NULL;
277 : }
278 :
279 397920 : if ( h_dirac_output_synthesis_state->mixing_matrix_old[idx] != NULL )
280 : {
281 87102 : free( h_dirac_output_synthesis_state->mixing_matrix_old[idx] );
282 87102 : h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL;
283 : }
284 :
285 397920 : if ( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] != NULL )
286 : {
287 64784 : free( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] );
288 64784 : h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL;
289 : }
290 :
291 397920 : if ( h_dirac_output_synthesis_state->mixing_matrix[idx] != NULL )
292 : {
293 87102 : free( h_dirac_output_synthesis_state->mixing_matrix[idx] );
294 87102 : h_dirac_output_synthesis_state->mixing_matrix[idx] = NULL;
295 : }
296 :
297 397920 : if ( h_dirac_output_synthesis_state->mixing_matrix_res[idx] != NULL )
298 : {
299 64784 : free( h_dirac_output_synthesis_state->mixing_matrix_res[idx] );
300 64784 : h_dirac_output_synthesis_state->mixing_matrix_res[idx] = NULL;
301 : }
302 : }
303 :
304 6632 : 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 40888788 : 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 40888788 : brange[0] = hParamMC->band_grouping[param_band];
337 40888788 : brange[1] = hParamMC->band_grouping[param_band + 1];
338 40888788 : num_bands = brange[1] - brange[0];
339 :
340 198460808 : for ( band_idx = 0; band_idx < num_bands; band_idx++ )
341 : {
342 157572020 : int16_t band = brange[0] + band_idx;
343 491757040 : for ( ch_idx = 0; ch_idx < nchan_in; ch_idx++ )
344 : {
345 334185020 : real_in_buffer[band_idx + num_bands * ch_idx] = RealBuffer[ch_idx * hParamMC->num_freq_bands + band];
346 334185020 : imag_in_buffer[band_idx + num_bands * ch_idx] = ImagBuffer[ch_idx * hParamMC->num_freq_bands + band];
347 : }
348 : }
349 :
350 40888788 : cmplx_matrix_square( real_in_buffer, imag_in_buffer, num_bands, nchan_in, real_buffer, imag_buffer );
351 :
352 40888788 : v_add( cx, real_buffer, cx, nchan_in * nchan_in );
353 :
354 40888788 : v_add( cx_imag, imag_buffer, cx_imag, nchan_in * nchan_in );
355 :
356 :
357 40888788 : 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 3193723 : 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_LS_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS];
384 : float mixing_matrix_res_smooth[MAX_LS_CHANNELS * MAX_LS_CHANNELS];
385 : float mixing_matrix_buffer[MAX_LS_CHANNELS * MAX_LS_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_LS_CHANNELS];
390 : float output_f_imag[MAX_LS_CHANNELS];
391 : float diff_f_real[MAX_LS_CHANNELS];
392 : float diff_f_imag[MAX_LS_CHANNELS];
393 : int16_t brange[2];
394 3193723 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE h_synthesis_state = hParamMC->h_output_synthesis_cov_state;
395 :
396 3193723 : set_zero( input_f_real, PARAM_MC_MAX_TRANSPORT_CHANS );
397 3193723 : set_zero( input_f_imag, PARAM_MC_MAX_TRANSPORT_CHANS );
398 3193723 : set_zero( output_f_real, MAX_LS_CHANNELS );
399 3193723 : set_zero( output_f_imag, MAX_LS_CHANNELS );
400 3193723 : set_zero( diff_f_real, MAX_LS_CHANNELS );
401 3193723 : set_zero( diff_f_imag, MAX_LS_CHANNELS );
402 :
403 44902319 : for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx++ )
404 : {
405 : /* final mixing */
406 41708596 : have_residual = 0;
407 41708596 : brange[0] = hParamMC->band_grouping[param_band_idx];
408 41708596 : brange[1] = hParamMC->band_grouping[param_band_idx + 1];
409 :
410 41708596 : if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr )
411 : {
412 34161011 : have_residual = 1;
413 : }
414 :
415 : /* mixing matrix interpolation*/
416 41708596 : v_multc( mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_smooth, nY * nX );
417 41708596 : 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 41708596 : v_add( mixing_matrix_smooth, mixing_matrix_buffer, mixing_matrix_smooth, nY * nX );
419 :
420 41708596 : if ( have_residual )
421 : {
422 : /* residual mixing matrix interpolation*/
423 34161011 : v_multc( mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_params.interpolator[slot_idx_tot], mixing_matrix_res_smooth, nY * nY );
424 34161011 : 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 34161011 : v_add( mixing_matrix_res_smooth, mixing_matrix_buffer, mixing_matrix_res_smooth, nY * nY );
426 : }
427 :
428 202340016 : for ( band = brange[0]; band < brange[1]; band++ )
429 : {
430 160631420 : assert( band >= 0 );
431 :
432 160631420 : if ( have_residual )
433 : {
434 : /* collect diffuse prototypes */
435 63874460 : assert( band < hParamMC->h_output_synthesis_params.max_band_decorr );
436 504587660 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
437 : {
438 440713200 : diff_f_real[ch_idx] = Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band];
439 440713200 : diff_f_imag[ch_idx] = Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band];
440 : }
441 :
442 : /* apply residual mixing */
443 63874460 : matrix_product( mixing_matrix_res_smooth, nY, nY, 0, diff_f_real, nY, 1, 0, output_f_real );
444 63874460 : matrix_product( mixing_matrix_res_smooth, nY, nY, 0, diff_f_imag, nY, 1, 0, output_f_imag );
445 :
446 504587660 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
447 : {
448 440713200 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] = output_f_real[ch_idx];
449 440713200 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] = output_f_imag[ch_idx];
450 : }
451 : }
452 : else
453 : {
454 747784960 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
455 : {
456 651028000 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] = 0.0f;
457 651028000 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] = 0.0f;
458 : }
459 : }
460 :
461 : /* collect input signals, still in cldfb buffers */
462 501725120 : for ( ch_idx = 0; ch_idx < nX; ch_idx++ )
463 : {
464 341093700 : input_f_real[ch_idx] = Cldfb_RealBuffer_in[ch_idx * hParamMC->num_freq_bands + band];
465 341093700 : input_f_imag[ch_idx] = Cldfb_ImagBuffer_in[ch_idx * hParamMC->num_freq_bands + band];
466 : }
467 :
468 : /* apply mixing matrix */
469 160631420 : matrix_product( mixing_matrix_smooth, nY, nX, 0, input_f_real, nX, 1, 0, output_f_real );
470 160631420 : matrix_product( mixing_matrix_smooth, nY, nX, 0, input_f_imag, nX, 1, 0, output_f_imag );
471 :
472 : /* collect output */
473 1252372620 : for ( ch_idx = 0; ch_idx < nY; ch_idx++ )
474 : {
475 1091741200 : Cldfb_RealBuffer[ch_idx][slot_idx_sfr][band] += output_f_real[ch_idx];
476 1091741200 : Cldfb_ImagBuffer[ch_idx][slot_idx_sfr][band] += output_f_imag[ch_idx];
477 : }
478 : }
479 : }
480 :
481 3193723 : return;
482 : }
483 :
484 :
485 : /*-------------------------------------------------------------------*
486 : * computeMixingMatrices()
487 : *
488 : * compute a mixing matrix using the convariance synthesis approach
489 : *-------------------------------------------------------------------*/
490 :
491 2606783 : 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 2606783 : int16_t out = EXIT_SUCCESS;
506 : int16_t nL, nC;
507 2606783 : int16_t lengthCx = num_inputs;
508 2606783 : 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 2606783 : push_wmops( "dirac_cov_mix_mat" );
528 :
529 2606783 : set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS );
530 44315311 : for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
531 : {
532 41708528 : set_zero( svd_in_buffer[i], MAX_OUTPUT_CHANNELS );
533 41708528 : set_zero( svd_u_buffer[i], MAX_OUTPUT_CHANNELS );
534 41708528 : set_zero( svd_v_buffer[i], MAX_OUTPUT_CHANNELS );
535 : }
536 :
537 : /*-----------------------------------------------------------------*
538 : * Decomposition of Cy
539 : *-----------------------------------------------------------------*/
540 :
541 : /* Processing the SVD */
542 2606783 : mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 );
543 :
544 2606783 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy );
545 :
546 : /* Computing Ky */
547 18229077 : for ( i = 0; i < lengthCy; ++i )
548 : {
549 115116382 : for ( j = 0; j < lengthCy; ++j )
550 : {
551 99494088 : 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 2606783 : mat2svdMat( Cx, svd_in_buffer, lengthCx, lengthCx, 0 );
561 :
562 2606783 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCx );
563 :
564 : /* Computing Kx */
565 8271647 : for ( i = 0; i < lengthCx; ++i )
566 : {
567 18348486 : for ( j = 0; j < lengthCx; ++j )
568 : {
569 12683622 : Kx[i + j * lengthCx] = svd_u_buffer[i][j] * sqrtf( svd_s_buffer[j] );
570 : }
571 : }
572 :
573 : /* Sx = sqrt(Sx) */
574 8271647 : for ( i = 0; i < lengthCx; ++i )
575 : {
576 5664864 : svd_s_buffer[i] = sqrtf( svd_s_buffer[i] );
577 : }
578 :
579 : /*-----------------------------------------------------------------*
580 : * Regularization of Sx
581 : *-----------------------------------------------------------------*/
582 :
583 2606783 : maximum( svd_s_buffer, lengthCx, &limit );
584 2606783 : limit = (float) max( limit * reg_Sx, SQRT_EPSILON );
585 8271647 : for ( i = 0; i < lengthCx; ++i )
586 : {
587 5664864 : svd_s_buffer[i] = ( ( svd_s_buffer[i] > limit ) ? svd_s_buffer[i] : limit );
588 : }
589 :
590 2606783 : limit = 0.0f;
591 :
592 : /*-----------------------------------------------------------------*
593 : * regularized Kx-1
594 : *-----------------------------------------------------------------*/
595 :
596 8271647 : for ( i = 0; i < lengthCx; ++i )
597 : {
598 5664864 : float reg_fac = ( 1.0f / svd_s_buffer[i] );
599 :
600 18348486 : for ( j = 0; j < lengthCx; ++j )
601 : {
602 12683622 : 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 2606783 : matrix_product( Q, lengthCy, lengthCx, 0, Cx, lengthCx, lengthCx, 0, Q_Cx );
612 :
613 2606783 : matrix_product_diag( Q_Cx, lengthCy, lengthCx, 0, Q, lengthCy, lengthCx, 1, Cy_hat_diag );
614 :
615 : /* Computing Cy_hat_diag */
616 18229077 : for ( i = 0; i < lengthCy; ++i )
617 : {
618 15622294 : if ( Cy_hat_diag[i] > limit )
619 : {
620 5849046 : limit = Cy_hat_diag[i];
621 : }
622 : }
623 :
624 2606783 : limit = limit * reg_ghat + EPSILON;
625 :
626 : /* Computing G_hat */
627 18229077 : for ( i = 0; i < lengthCy; ++i )
628 : {
629 15622294 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
630 : {
631 23664 : Cy_hat_diag[i] = limit;
632 : }
633 :
634 15622294 : 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 2606783 : matrix_product( Kx, lengthCx, lengthCx, 1, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 );
643 2606783 : matrix_diag_product( mat_mult_buffer1, lengthCx, lengthCy, 0, G_hat, lengthCy, mat_mult_buffer2 );
644 2606783 : matrix_product( mat_mult_buffer2, lengthCx, lengthCy, 0, Ky, lengthCy, lengthCy, 0, mat_mult_buffer1 );
645 :
646 2606783 : if ( lengthCx < lengthCy )
647 : {
648 2606783 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 1 );
649 :
650 2606783 : nL = lengthCy;
651 2606783 : nC = lengthCx;
652 :
653 2606783 : 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 2606783 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx );
671 2606783 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
672 :
673 2606783 : 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 2606783 : matrix_product( Ky, lengthCy, lengthCy, 0, mat_mult_buffer3, lengthCy, lengthCx, 0, mat_mult_buffer1 );
680 2606783 : 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 2606783 : matrix_product( mixing_matrix, lengthCy, lengthCx, 0, Cx, lengthCx, lengthCx, 0, mat_mult_buffer1 );
688 2606783 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, mat_mult_buffer2 );
689 :
690 : /* Compute Cr = Cy - Cy_tilde */
691 2606783 : Cr_p = Cr;
692 2606783 : Cy_p = Cy;
693 2606783 : Cy_tilde_p = mat_mult_buffer2;
694 18229077 : for ( i = 0; i < lengthCy; ++i )
695 : {
696 115116382 : for ( j = 0; j < lengthCy; ++j )
697 : {
698 99494088 : *( Cr_p++ ) = *( Cy_p++ ) - *( Cy_tilde_p++ );
699 : }
700 :
701 : /* Avoid Meaningless negative main diagonal elements */
702 15622294 : if ( Cr[i + i * lengthCy] < 0.0f )
703 : {
704 2491713 : Cr[i + i * lengthCy] = 0.0f;
705 : }
706 : }
707 :
708 : /*-----------------------------------------------------------------*
709 : * Energy Compensation
710 : *-----------------------------------------------------------------*/
711 :
712 2606783 : if ( energy_compensation_flag == 1 )
713 : {
714 471724 : adj = svd_s_buffer;
715 471724 : Cy_tilde_p = mat_mult_buffer2;
716 3234364 : 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 2762640 : if ( Cy_tilde_p[i + i * lengthCy] < 0.0f )
721 : {
722 0 : adj[i] = 1.0f;
723 : }
724 : else
725 : {
726 2762640 : adj[i] = sqrtf( Cy[i + lengthCy * i] / ( Cy_tilde_p[i + i * lengthCy] + EPSILON ) );
727 : }
728 :
729 2762640 : if ( adj[i] > 4.0f )
730 : {
731 3597 : adj[i] = 4.0f;
732 : }
733 : }
734 :
735 471724 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
736 :
737 471724 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
738 : }
739 2606783 : pop_wmops();
740 :
741 2606783 : return out;
742 : }
743 :
744 :
745 : /*-------------------------------------------------------------------*
746 : * computeMixingMatricesResidual()
747 : *
748 : * compute a residual mixing matrix using the covariance synthesis approach
749 : *-------------------------------------------------------------------*/
750 :
751 2135059 : 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 2135059 : int16_t out = EXIT_SUCCESS;
762 2135059 : int16_t lengthCx = num_outputs;
763 2135059 : 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 2135059 : 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 2135059 : mat2svdMat( Cy, svd_in_buffer, lengthCy, lengthCy, 0 );
790 :
791 2135059 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCy, lengthCy );
792 :
793 : /* Computing Ky */
794 14994713 : for ( i = 0; i < lengthCy; ++i )
795 : {
796 95168098 : for ( j = 0; j < lengthCy; ++j )
797 : {
798 82308444 : 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 14994713 : for ( i = 0; i < lengthCx; ++i )
813 : {
814 12859654 : Kx[i] = sqrtf( Cx[i] );
815 : }
816 :
817 : /*-----------------------------------------------------------------*
818 : * Regularization of Sx
819 : *-----------------------------------------------------------------*/
820 :
821 2135059 : maximum( Kx, lengthCx, &limit );
822 2135059 : limit = limit * reg_Sx + EPSILON;
823 :
824 14994713 : for ( i = 0; i < lengthCx; ++i )
825 : {
826 12859654 : float reg_fac = ( 1.0f / ( ( Kx[i] > limit ) ? Kx[i] : limit ) );
827 12859654 : Kx_reg_inv[i] = reg_fac;
828 : }
829 :
830 2135059 : 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 2135059 : mvr2r( Cx, Cy_hat_diag, num_outputs );
842 :
843 14994713 : for ( i = 0; i < lengthCy; ++i )
844 : {
845 12859654 : if ( Cy_hat_diag[i] > limit )
846 : {
847 4827538 : limit = Cy_hat_diag[i];
848 : }
849 : }
850 :
851 2135059 : limit = limit * reg_ghat + EPSILON;
852 :
853 : /* Computing G_hat */
854 14994713 : for ( i = 0; i < lengthCy; ++i )
855 : {
856 12859654 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
857 : {
858 18692 : Cy_hat_diag[i] = limit;
859 : }
860 12859654 : G_hat[i] = sqrtf( Cy[i + i * lengthCy] / Cy_hat_diag[i] );
861 : }
862 :
863 : /*-----------------------------------------------------------------*
864 : * Formulate optimal P
865 : *-----------------------------------------------------------------*/
866 :
867 14994713 : for ( i = 0; i < num_outputs; i++ )
868 : {
869 12859654 : Kx[i] *= G_hat[i];
870 : }
871 :
872 14994713 : for ( i = 0; i < num_outputs; i++ )
873 : {
874 12859654 : float fac = Kx[i];
875 :
876 95168098 : for ( j = 0; j < num_outputs; j++ )
877 : {
878 82308444 : mat_mult_buffer1[i + j * num_outputs] = Ky[i + j * num_outputs] * fac;
879 : }
880 : }
881 :
882 2135059 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, lengthCy, 0 );
883 :
884 2135059 : svd( svd_in_buffer, svd_u_buffer, svd_s_buffer, svd_v_buffer, lengthCx, lengthCy );
885 :
886 : /* Actually Processing P */
887 2135059 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, lengthCy, lengthCx );
888 2135059 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
889 :
890 2135059 : 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 2135059 : matrix_product( Ky, lengthCy, lengthCy, 0, mat_mult_buffer3, lengthCy, lengthCx, 0, mat_mult_buffer1 );
899 :
900 14994713 : for ( i = 0; i < num_outputs; i++ )
901 : {
902 12859654 : float fac = Kx_reg_inv[i];
903 :
904 95168098 : for ( j = 0; j < num_outputs; j++ )
905 : {
906 82308444 : 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 2135059 : matrix_diag_product( mixing_matrix, lengthCy, lengthCx, 0, Cx, lengthCx, mat_mult_buffer1 );
916 :
917 2135059 : matrix_product_diag( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, Cy_tilde );
918 :
919 : /*-----------------------------------------------------------------*
920 : * Energy Compensation
921 : *-----------------------------------------------------------------*/
922 :
923 2135059 : adj = svd_s_buffer;
924 :
925 14994713 : for ( i = 0; i < lengthCy; ++i )
926 : {
927 12859654 : adj[i] = sqrtf( Cy[i + lengthCy * i] / ( Cy_tilde[i] + EPSILON ) );
928 12859654 : if ( adj[i] > 4.0f )
929 : {
930 1529 : adj[i] = 4.0f;
931 : }
932 : }
933 :
934 2135059 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
935 :
936 2135059 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
937 :
938 2135059 : pop_wmops();
939 :
940 2135059 : return out;
941 : }
942 :
943 :
944 : /*-------------------------------------------------------------------*
945 : * computeMixingMatricesISM()
946 : *
947 : *
948 : *-------------------------------------------------------------------*/
949 :
950 5576640 : 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 5576640 : push_wmops( "dirac_cov_mix_mat" );
985 :
986 5576640 : out = EXIT_SUCCESS;
987 5576640 : lengthCx = num_inputs;
988 5576640 : lengthCy = num_outputs;
989 :
990 5576640 : set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS );
991 94802880 : for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
992 : {
993 89226240 : set_zero( svd_in_buffer[i], MAX_OUTPUT_CHANNELS );
994 89226240 : set_zero( svd_u_buffer[i], MAX_OUTPUT_CHANNELS );
995 89226240 : set_zero( svd_v_buffer[i], MAX_OUTPUT_CHANNELS );
996 : }
997 :
998 : /* Decomposition of Cy = Ky*Ky' */
999 : /* Ky = responses*diag(ener) */
1000 5576640 : matrix_diag_product( responses, lengthCy, num_responses, 0, ener, num_responses, Ky );
1001 :
1002 : /* Decomposition of Cx -> Computing Kx */
1003 5576640 : v_sqrt( Cx_diag, Kx, lengthCx );
1004 :
1005 : /* Regularization of Sx */
1006 5576640 : maximum( Kx, lengthCx, &limit );
1007 5576640 : limit = limit * reg_Sx + EPSILON;
1008 :
1009 16729920 : for ( i = 0; i < lengthCx; ++i )
1010 : {
1011 11153280 : svd_s_buffer[i] = ( ( Kx[i] > limit ) ? Kx[i] : limit );
1012 : }
1013 :
1014 5576640 : limit = 0.0f;
1015 :
1016 : /* regularized Kx-1 */
1017 :
1018 16729920 : for ( i = 0; i < lengthCx; ++i )
1019 : {
1020 11153280 : float reg_fac = ( 1.0f / svd_s_buffer[i] );
1021 11153280 : Kx_reg_inv[i] = reg_fac;
1022 : }
1023 :
1024 : /************************ normalization matrix G hat **********************/
1025 :
1026 : /* Computing Q*Cx*Q' */
1027 5576640 : matrix_diag_product( Q, lengthCy, lengthCx, 0, Cx_diag, lengthCx, Q_Cx );
1028 5576640 : matrix_product_diag( Q_Cx, lengthCy, lengthCx, 0, Q, lengthCy, lengthCx, 1, Cy_hat_diag );
1029 :
1030 : /* Computing Cy_hat_diag */
1031 57120540 : for ( i = 0; i < lengthCy; ++i )
1032 : {
1033 51543900 : if ( Cy_hat_diag[i] > limit )
1034 : {
1035 8025305 : limit = Cy_hat_diag[i];
1036 : }
1037 : }
1038 :
1039 :
1040 5576640 : limit = limit * reg_ghat + EPSILON;
1041 :
1042 : /* Computing G_hat */
1043 57120540 : for ( i = 0; i < lengthCy; ++i )
1044 : {
1045 51543900 : if ( limit > Cy_hat_diag[i] ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
1046 : {
1047 920423 : Cy_hat_diag[i] = limit;
1048 : }
1049 51543900 : 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 5576640 : diag_matrix_product( Kx, lengthCx, Q, lengthCy, lengthCx, 1, mat_mult_buffer1 );
1056 5576640 : matrix_diag_product( mat_mult_buffer1, lengthCx, lengthCy, 0, G_hat, lengthCy, mat_mult_buffer2 );
1057 5576640 : matrix_product( mat_mult_buffer2, lengthCx, lengthCy, 0, Ky, lengthCy, num_responses, 0, mat_mult_buffer1 );
1058 :
1059 5576640 : if ( lengthCx < num_responses )
1060 : {
1061 51060 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 1 );
1062 51060 : nL = num_responses;
1063 51060 : nC = lengthCx;
1064 51060 : svd( svd_in_buffer, svd_v_buffer, svd_s_buffer, svd_u_buffer, nL, nC );
1065 : }
1066 : else
1067 : {
1068 5525580 : mat2svdMat( mat_mult_buffer1, svd_in_buffer, lengthCx, num_responses, 0 );
1069 5525580 : nL = lengthCx;
1070 5525580 : nC = num_responses;
1071 5525580 : 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 5576640 : svdMat2mat( svd_v_buffer, mat_mult_buffer1, num_responses, lengthCx );
1078 5576640 : svdMat2mat( svd_u_buffer, mat_mult_buffer2, lengthCx, lengthCx );
1079 :
1080 5576640 : matrix_product( mat_mult_buffer1, num_responses, lengthCx, 0, mat_mult_buffer2, lengthCx, lengthCx, 1, mat_mult_buffer3 );
1081 :
1082 : /************************ Formulate M **********************/
1083 :
1084 5576640 : matrix_product( Ky, lengthCy, num_responses, 0, mat_mult_buffer3, num_responses, lengthCx, 0, mat_mult_buffer1 );
1085 :
1086 5576640 : 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 5576640 : matrix_diag_product( mixing_matrix, lengthCy, lengthCx, 0, Cx_diag, lengthCx, mat_mult_buffer1 );
1092 5576640 : matrix_product( mat_mult_buffer1, lengthCy, lengthCx, 0, mixing_matrix, lengthCy, lengthCx, 1, mat_mult_buffer2 );
1093 :
1094 5576640 : if ( energy_compensation_flag == 1 )
1095 : {
1096 5576640 : adj = svd_s_buffer;
1097 5576640 : Cy_tilde_p = mat_mult_buffer2;
1098 57120540 : 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 51543900 : if ( Cy_tilde_p[i + i * lengthCy] < 0.0f )
1102 : {
1103 0 : adj[i] = 1.0f;
1104 : }
1105 : else
1106 : {
1107 51543900 : adj[i] = sqrtf( Cy_diag[i] / ( Cy_tilde_p[i + i * lengthCy] + EPSILON ) );
1108 : }
1109 :
1110 51543900 : if ( adj[i] > 4.0f )
1111 : {
1112 190684 : adj[i] = 4.0f;
1113 : }
1114 : }
1115 :
1116 5576640 : diag_matrix_product( adj, lengthCy, mixing_matrix, lengthCy, lengthCx, 0, mat_mult_buffer3 );
1117 :
1118 5576640 : mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx );
1119 : }
1120 :
1121 5576640 : pop_wmops();
1122 :
1123 5576640 : return out;
1124 : }
|