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 :
34 : #include <stdint.h>
35 : #include <string.h>
36 : #include <stdio.h>
37 : #include <stdlib.h>
38 : #include <assert.h>
39 : #include <math.h>
40 : #include "options.h"
41 : #include "cnst.h"
42 : #include "rom_enc.h"
43 : #include "rom_com.h"
44 : #include "prot_fx.h"
45 : #include "ivas_stat_dec.h"
46 : #include "ivas_cnst.h"
47 : #include "ivas_rom_com.h"
48 : #include "ivas_rom_dec.h"
49 : #include "wmc_auto.h"
50 : #include "rom_dec.h"
51 : #include "ivas_prot_fx.h"
52 :
53 :
54 : /*-------------------------------------------------------------------*
55 : * ivas_dirac_dec_output_synthesis_cov_open()
56 : *
57 : * Sets up the state and parameters for the Covariance Synthesis
58 : *-------------------------------------------------------------------*/
59 :
60 297 : ivas_error ivas_dirac_dec_output_synthesis_cov_open_fx(
61 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */
62 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: hanlde for the covariance synthesis state */
63 : const Word16 max_band_decorr, /* i : uppermost frequency band where decorrelation is applied */
64 : const Word16 interp_length, /* i : length for interpolating the mixing matrices in time slots */
65 : const Word16 num_param_bands, /* i : number of parameter bands */
66 : const Word16 num_param_bands_residual, /* i : number of parameter bands with a residual mixing matrix (i.e. decorrelation */
67 : const Word16 nchan_in, /* i : number of input (transport) channels */
68 : const Word16 nchan_out, /* i : number of output channels */
69 : const Word32 *proto_matrix /* i : the prototype (upmix) matrix (only used if mode == 1) Q(15-proto_matrix_e) */
70 : )
71 : {
72 : Word16 idx;
73 :
74 297 : h_dirac_output_synthesis_params->max_band_decorr = max_band_decorr;
75 297 : move16();
76 :
77 : /*-----------------------------------------------------------------*
78 : * memory allocation
79 : *-----------------------------------------------------------------*/
80 :
81 : /* buffer length and interpolator */
82 297 : h_dirac_output_synthesis_params->alpha_synthesis_fx = NULL;
83 297 : IF( ( h_dirac_output_synthesis_params->proto_matrix_fx = (Word32 *) malloc( nchan_out * nchan_in * sizeof( Word32 ) ) ) == NULL )
84 : {
85 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
86 : }
87 297 : h_dirac_output_synthesis_params->proto_matrix_len = imult1616( nchan_out, nchan_in );
88 297 : move16();
89 : /* cov buffers */
90 3803 : FOR( idx = 0; idx < num_param_bands; idx++ )
91 : {
92 3506 : IF( ( h_dirac_output_synthesis_state->cx_old_fx[idx] = (Word32 *) malloc( nchan_in * nchan_in * sizeof( Word32 ) ) ) == NULL )
93 : {
94 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
95 : }
96 3506 : h_dirac_output_synthesis_state->cx_old_len = imult1616( nchan_in, nchan_in );
97 3506 : IF( ( h_dirac_output_synthesis_state->cy_old_fx[idx] = (Word32 *) malloc( nchan_out * nchan_out * sizeof( Word32 ) ) ) == NULL )
98 : {
99 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
100 : }
101 3506 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx] = (Word32 *) malloc( nchan_out * nchan_in * sizeof( Word32 ) ) ) == NULL )
102 : {
103 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
104 : }
105 3506 : set_zero_fx( h_dirac_output_synthesis_state->cx_old_fx[idx], imult1616( nchan_in, nchan_in ) );
106 3506 : set_zero_fx( h_dirac_output_synthesis_state->cy_old_fx[idx], imult1616( nchan_out, nchan_out ) );
107 3506 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx], imult1616( nchan_out, nchan_in ) );
108 :
109 3506 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_fx[idx] = (Word32 *) malloc( nchan_out * nchan_in * sizeof( Word32 ) ) ) == NULL )
110 : {
111 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
112 : }
113 3506 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_fx[idx], imult1616( nchan_out, nchan_in ) );
114 3506 : h_dirac_output_synthesis_state->mixing_matrix_len = i_mult( nchan_out, nchan_in );
115 3506 : move16();
116 : }
117 14611 : FOR( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
118 : {
119 14314 : h_dirac_output_synthesis_state->cx_old_fx[idx] = NULL;
120 14314 : h_dirac_output_synthesis_state->cy_old_fx[idx] = NULL;
121 14314 : h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx] = NULL;
122 14314 : h_dirac_output_synthesis_state->mixing_matrix_fx[idx] = NULL;
123 : }
124 :
125 3053 : FOR( idx = 0; idx < num_param_bands_residual; idx++ )
126 : {
127 2756 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx] = (Word32 *) malloc( imult1616( nchan_out, nchan_out ) * sizeof( Word32 ) ) ) == NULL )
128 : {
129 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
130 : }
131 2756 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx], imult1616( nchan_out, nchan_out ) );
132 :
133 2756 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx] = (Word32 *) malloc( imult1616( nchan_out, nchan_out ) * sizeof( Word32 ) ) ) == NULL )
134 : {
135 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
136 : }
137 2756 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx], imult1616( nchan_out, nchan_out ) );
138 2756 : h_dirac_output_synthesis_state->mixing_matrix_res_len = i_mult( nchan_out, nchan_out );
139 2756 : move16();
140 : }
141 15361 : FOR( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
142 : {
143 15064 : h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx] = NULL;
144 15064 : h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx] = NULL;
145 : }
146 :
147 297 : IF( ( h_dirac_output_synthesis_state->cx_old_e = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
148 : {
149 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
150 : }
151 297 : IF( ( h_dirac_output_synthesis_state->cy_old_e = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
152 : {
153 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
154 : }
155 :
156 297 : set16_fx( h_dirac_output_synthesis_state->cx_old_e, 0, CLDFB_NO_CHANNELS_MAX );
157 297 : set16_fx( h_dirac_output_synthesis_state->cy_old_e, 0, CLDFB_NO_CHANNELS_MAX );
158 :
159 297 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_res_exp = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
160 : {
161 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
162 : }
163 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_res_exp, 0, CLDFB_NO_CHANNELS_MAX );
164 :
165 297 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_res_old_exp = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
166 : {
167 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
168 : }
169 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_res_old_exp, 0, CLDFB_NO_CHANNELS_MAX );
170 :
171 297 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_exp = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
172 : {
173 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
174 : }
175 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_exp, 0, CLDFB_NO_CHANNELS_MAX );
176 :
177 297 : IF( ( h_dirac_output_synthesis_state->mixing_matrix_old_exp = (Word16 *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( Word16 ) ) ) == NULL )
178 : {
179 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis matrix\n" ) );
180 : }
181 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_old_exp, 0, CLDFB_NO_CHANNELS_MAX );
182 :
183 : /*-----------------------------------------------------------------*
184 : * prepare processing parameters
185 : *-----------------------------------------------------------------*/
186 :
187 : /* compute interpolator */
188 297 : IF( ( h_dirac_output_synthesis_params->interpolator_fx = (Word16 *) malloc( interp_length * sizeof( Word16 ) ) ) == NULL )
189 : {
190 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) );
191 : }
192 9801 : FOR( idx = 1; idx <= interp_length; ++idx )
193 : {
194 9504 : h_dirac_output_synthesis_params->interpolator_fx[idx - 1] = div_s( idx, interp_length );
195 9504 : move16();
196 : }
197 297 : Copy32( proto_matrix, h_dirac_output_synthesis_params->proto_matrix_fx, imult1616( nchan_in, nchan_out ) );
198 297 : h_dirac_output_synthesis_params->proto_matrix_e = 5;
199 297 : move16();
200 297 : return IVAS_ERR_OK;
201 : }
202 :
203 :
204 : /*-------------------------------------------------------------------*
205 : * ivas_dirac_dec_output_synthesis_get_interpolator_fx()
206 : *
207 : *
208 : *-------------------------------------------------------------------*/
209 :
210 318405 : void ivas_dirac_dec_output_synthesis_get_interpolator_fx(
211 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */
212 : const UWord16 interp_length /* i : interpolator length */
213 : )
214 : {
215 : Word16 idx;
216 318405 : Word16 tmp, exp_diff = 0;
217 318405 : move16();
218 :
219 1583754 : FOR( idx = 1; idx <= interp_length; ++idx )
220 : {
221 1265349 : tmp = BASOP_Util_Divide3232_Scale( L_deposit_l( idx ), L_deposit_l( interp_length ), &exp_diff ); // (Q15 - exp_diff)
222 1265349 : h_dirac_output_synthesis_params->interpolator_fx[idx - 1] = shl_sat( tmp, exp_diff ); // Q15
223 1265349 : move16();
224 : }
225 :
226 318405 : return;
227 : }
228 :
229 :
230 : /*-------------------------------------------------------------------*
231 : * ivas_dirac_dec_output_synthesis_cov_init()
232 : *
233 : * initialize the states for the covariance synthesis
234 : *-------------------------------------------------------------------*/
235 297 : void ivas_dirac_dec_output_synthesis_cov_init_fx(
236 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: pointer to the state of the covariance synthesis */
237 : const Word16 nchan_in, /* i : number of input (tranport) channels */
238 : const Word16 nchan_out, /* i : number of output channels */
239 : const Word16 n_param_bands, /* i : number of total parameter bands */
240 : const Word16 n_param_bands_res /* i : number of parameter bands with a residual mixing matrix (i.e. decorrelation */
241 : )
242 : {
243 :
244 : Word16 idx;
245 :
246 : /* initialize buffers */
247 3803 : FOR( idx = 0; idx < n_param_bands; idx++ )
248 : {
249 3506 : set_zero_fx( h_dirac_output_synthesis_state->cx_old_fx[idx], imult1616( nchan_in, nchan_in ) );
250 3506 : set_zero_fx( h_dirac_output_synthesis_state->cy_old_fx[idx], imult1616( nchan_out, nchan_out ) );
251 3506 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx], imult1616( nchan_out, nchan_in ) );
252 3506 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_fx[idx], imult1616( nchan_out, nchan_in ) );
253 : }
254 :
255 3053 : FOR( idx = 0; idx < n_param_bands_res; idx++ )
256 : {
257 2756 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx], imult1616( nchan_out, nchan_out ) );
258 2756 : set_zero_fx( h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx], imult1616( nchan_out, nchan_out ) );
259 : }
260 :
261 :
262 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_old_exp, 0, CLDFB_NO_CHANNELS_MAX );
263 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_exp, 0, CLDFB_NO_CHANNELS_MAX );
264 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_res_old_exp, 0, CLDFB_NO_CHANNELS_MAX );
265 297 : set16_fx( h_dirac_output_synthesis_state->mixing_matrix_res_exp, 0, CLDFB_NO_CHANNELS_MAX );
266 :
267 297 : return;
268 : }
269 :
270 :
271 : /*-------------------------------------------------------------------*
272 : * ivas_dirac_dec_output_synthesis_cov_close()
273 : *
274 : * deallocate dynamic memory in the covariance synthesis state
275 : *-------------------------------------------------------------------*/
276 :
277 297 : void ivas_dirac_dec_output_synthesis_cov_close_fx(
278 : DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i : handle for the covariance synthesis parameters */
279 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state /* i/o: handle for the covariance synthesis state */
280 : )
281 : {
282 : Word16 idx;
283 :
284 : /*-----------------------------------------------------------------*
285 : * memory deallocation
286 : *-----------------------------------------------------------------*/
287 :
288 : /* free interpolator */
289 297 : IF( h_dirac_output_synthesis_params->interpolator_fx != NULL )
290 : {
291 297 : free( h_dirac_output_synthesis_params->interpolator_fx );
292 297 : h_dirac_output_synthesis_params->interpolator_fx = NULL;
293 : }
294 :
295 : /* free alpha */
296 297 : IF( h_dirac_output_synthesis_params->alpha_synthesis_fx != NULL )
297 : {
298 0 : free( h_dirac_output_synthesis_params->alpha_synthesis_fx );
299 0 : h_dirac_output_synthesis_params->alpha_synthesis_fx = NULL;
300 : }
301 :
302 : /* free proto_matrix */
303 297 : IF( h_dirac_output_synthesis_params->proto_matrix_fx != NULL )
304 : {
305 297 : free( h_dirac_output_synthesis_params->proto_matrix_fx );
306 297 : h_dirac_output_synthesis_params->proto_matrix_fx = NULL;
307 : }
308 :
309 :
310 297 : IF( h_dirac_output_synthesis_state->cx_old_e != NULL )
311 : {
312 297 : free( h_dirac_output_synthesis_state->cx_old_e );
313 297 : h_dirac_output_synthesis_state->cx_old_e = NULL;
314 : }
315 297 : IF( h_dirac_output_synthesis_state->cy_old_e != NULL )
316 : {
317 297 : free( h_dirac_output_synthesis_state->cy_old_e );
318 297 : h_dirac_output_synthesis_state->cy_old_e = NULL;
319 : }
320 :
321 : /* free cov buffers */
322 18117 : FOR( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ )
323 : {
324 17820 : IF( h_dirac_output_synthesis_state->cx_old_fx[idx] != NULL )
325 : {
326 3506 : free( h_dirac_output_synthesis_state->cx_old_fx[idx] );
327 3506 : h_dirac_output_synthesis_state->cx_old_fx[idx] = NULL;
328 : }
329 :
330 17820 : IF( h_dirac_output_synthesis_state->cy_old_fx[idx] != NULL )
331 : {
332 3506 : free( h_dirac_output_synthesis_state->cy_old_fx[idx] );
333 3506 : h_dirac_output_synthesis_state->cy_old_fx[idx] = NULL;
334 : }
335 :
336 17820 : IF( h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx] != NULL )
337 : {
338 3506 : free( h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx] );
339 3506 : h_dirac_output_synthesis_state->mixing_matrix_old_fx[idx] = NULL;
340 : }
341 :
342 17820 : IF( h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx] != NULL )
343 : {
344 2756 : free( h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx] );
345 2756 : h_dirac_output_synthesis_state->mixing_matrix_res_old_fx[idx] = NULL;
346 : }
347 :
348 17820 : IF( h_dirac_output_synthesis_state->mixing_matrix_fx[idx] != NULL )
349 : {
350 3506 : free( h_dirac_output_synthesis_state->mixing_matrix_fx[idx] );
351 3506 : h_dirac_output_synthesis_state->mixing_matrix_fx[idx] = NULL;
352 : }
353 :
354 17820 : IF( h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx] != NULL )
355 : {
356 2756 : free( h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx] );
357 2756 : h_dirac_output_synthesis_state->mixing_matrix_res_fx[idx] = NULL;
358 : }
359 : }
360 :
361 297 : IF( h_dirac_output_synthesis_state->mixing_matrix_old_exp != NULL )
362 : {
363 297 : free( h_dirac_output_synthesis_state->mixing_matrix_old_exp );
364 297 : h_dirac_output_synthesis_state->mixing_matrix_old_exp = NULL;
365 : }
366 :
367 297 : IF( h_dirac_output_synthesis_state->mixing_matrix_res_old_exp != NULL )
368 : {
369 297 : free( h_dirac_output_synthesis_state->mixing_matrix_res_old_exp );
370 297 : h_dirac_output_synthesis_state->mixing_matrix_res_old_exp = NULL;
371 : }
372 :
373 297 : IF( h_dirac_output_synthesis_state->mixing_matrix_exp != NULL )
374 : {
375 297 : free( h_dirac_output_synthesis_state->mixing_matrix_exp );
376 297 : h_dirac_output_synthesis_state->mixing_matrix_exp = NULL;
377 : }
378 :
379 297 : IF( h_dirac_output_synthesis_state->mixing_matrix_res_exp != NULL )
380 : {
381 297 : free( h_dirac_output_synthesis_state->mixing_matrix_res_exp );
382 297 : h_dirac_output_synthesis_state->mixing_matrix_res_exp = NULL;
383 : }
384 297 : return;
385 : }
386 :
387 : /*-------------------------------------------------------------------*
388 : * ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot()
389 : *
390 : * collect the multi channel input covariance for one filter bank time slot
391 : *-------------------------------------------------------------------*/
392 :
393 : /*-------------------------------------------------------------------*
394 : * ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot()
395 : *
396 : * collect the multi channel input covariance for one filter bank time slot
397 : *-------------------------------------------------------------------*/
398 1776450 : void ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot_fx(
399 : Word32 *RealBuffer_fx, /* i : input channel filter bank samples (real part) Q(31- RealBuffer_e)*/
400 : Word16 RealBuffer_e, /* i : exponent input channel filter bank samples (real part)*/
401 : Word32 *ImagBuffer_fx, /* i : input channel filter bank samples (imaginary part Q(ImagBuffer_e)*/
402 : Word16 ImagBuffer_e, /* i : exponent input channel filter bank samples (real part)*/
403 : Word32 cx_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (real part) Q(31- cx_e)*/
404 : Word16 *cx_e, /* i : exponent for accumulated input covariance (real part) */
405 : Word32 cx_imag_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* o : accumulated input covariance (imaginary part) Q(31- cx_imag_e)*/
406 : Word16 *cx_imag_e, /* i : exponent accumulated input covariance (imag part) */
407 : PARAM_MC_DEC_HANDLE hParamMC, /* i : handle to Parametric MC state */
408 : const Word16 param_band, /* i : parameter band */
409 : const Word16 nchan_in /* i : number of input channels */
410 : )
411 : {
412 : Word16 band_idx, ch_idx;
413 : Word16 brange[2];
414 : Word32 real_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * MAX_TRANSPORT_CHANNELS];
415 : Word16 real_in_e;
416 : Word32 imag_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * MAX_TRANSPORT_CHANNELS];
417 : Word16 imag_in_e;
418 : Word32 real_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
419 : Word32 imag_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
420 : Word16 output_e;
421 : Word16 tmp1_e, tmp2_e, shift_imag, shift_real;
422 : Word16 band, num_bands;
423 : Word16 cx_fx_norm, cx_imag_fx_norm;
424 : /* estimate input covariance */
425 : /* Already stack here instead of in the process_subframe */
426 :
427 : /* collect input frame */
428 1776450 : brange[0] = hParamMC->band_grouping[param_band];
429 1776450 : move16();
430 1776450 : brange[1] = hParamMC->band_grouping[param_band + 1];
431 1776450 : move16();
432 1776450 : num_bands = sub( brange[1], brange[0] );
433 :
434 9379450 : FOR( band_idx = 0; band_idx < num_bands; band_idx++ )
435 : {
436 7603000 : band = add( brange[0], band_idx );
437 22843320 : FOR( ch_idx = 0; ch_idx < nchan_in; ch_idx++ )
438 : {
439 15240320 : real_in_buffer_fx[band_idx + num_bands * ch_idx] = RealBuffer_fx[band + hParamMC->num_freq_bands * ch_idx];
440 15240320 : move32();
441 15240320 : imag_in_buffer_fx[band_idx + num_bands * ch_idx] = ImagBuffer_fx[band + hParamMC->num_freq_bands * ch_idx];
442 15240320 : move32();
443 : }
444 : }
445 :
446 1776450 : real_in_e = RealBuffer_e;
447 1776450 : move16();
448 1776450 : imag_in_e = ImagBuffer_e;
449 1776450 : move16();
450 :
451 1776450 : Word16 buf_len = imult1616( num_bands, nchan_in );
452 :
453 1776450 : shift_real = sub( L_norm_arr( real_in_buffer_fx, buf_len ), find_guarded_bits_fx( add( num_bands, 1 ) ) );
454 1776450 : shift_imag = sub( L_norm_arr( imag_in_buffer_fx, buf_len ), find_guarded_bits_fx( add( num_bands, 1 ) ) );
455 :
456 1776450 : real_in_e = sub( real_in_e, shift_real );
457 1776450 : imag_in_e = sub( imag_in_e, shift_imag );
458 :
459 :
460 1776450 : output_e = s_max( real_in_e, imag_in_e );
461 :
462 1776450 : scale_sig32( real_in_buffer_fx, buf_len, sub( RealBuffer_e, output_e ) );
463 1776450 : scale_sig32( imag_in_buffer_fx, buf_len, sub( ImagBuffer_e, output_e ) );
464 :
465 1776450 : cmplx_matrix_square_fx( real_in_buffer_fx, imag_in_buffer_fx, num_bands, nchan_in, real_buffer_fx, imag_buffer_fx, output_e, &output_e );
466 1776450 : v_add_fixed_me( cx_fx, *cx_e, real_buffer_fx, output_e, cx_fx, &tmp1_e, imult1616( nchan_in, nchan_in ), 1 );
467 :
468 1776450 : v_add_fixed_me( cx_imag_fx, *cx_imag_e, imag_buffer_fx, output_e, cx_imag_fx, &tmp2_e, imult1616( nchan_in, nchan_in ), 1 );
469 :
470 1776450 : cx_fx_norm = L_norm_arr( cx_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
471 1776450 : cx_imag_fx_norm = L_norm_arr( cx_imag_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
472 :
473 1776450 : scale_sig32( cx_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS, cx_fx_norm );
474 1776450 : scale_sig32( cx_imag_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS, cx_imag_fx_norm );
475 :
476 1776450 : *cx_e = sub( tmp1_e, cx_fx_norm );
477 1776450 : move16();
478 1776450 : *cx_imag_e = sub( tmp2_e, cx_imag_fx_norm );
479 1776450 : move16();
480 :
481 1776450 : return;
482 : }
483 :
484 : /*-------------------------------------------------------------------*
485 : * ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot()
486 : *
487 : * synthesize one filter bank slot of multi channel output filter bank
488 : * samples with the covariance synthesis
489 : *-------------------------------------------------------------------*/
490 :
491 140160 : void ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot_fx(
492 : Word32 *Cldfb_RealBuffer_in_fx, /*Q6*/
493 : Word32 *Cldfb_ImagBuffer_in_fx, /*Q6*/
494 : Word32 Cldfb_RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (real part) Q6*/
495 : Word32 Cldfb_ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : output channel filter bank samples (imaginary part) Q6*/
496 : Word32 *mixing_matrix_fx[], /* i : parameter band wise mixing matrices (direct part) Q(31-mixing_matrix_e)*/
497 : Word16 *mixing_matrix_e, /* i : parameter band wise mixing matrices (direct part) */
498 : Word32 *mixing_matrix_res_fx[], /* i : parameter band wise mixing matrices (residual part) Q(31-mixing_matrix_res_e)*/
499 : Word16 *mixing_matrix_res_e, /* i : parameter band wise mixing matrices (residual part) */
500 : const UWord16 slot_idx_sfr, /* i : time slot index for the current slot within the current subframe */
501 : const UWord16 slot_idx_tot, /* i : time slot index for the current slot within the frame */
502 : const Word16 nX, /* i : number of input channels */
503 : const Word16 nY, /* i : number of output channels */
504 : PARAM_MC_DEC_HANDLE hParamMC /* i : handle to the Parametric MC decoder state */
505 : )
506 : {
507 : Word16 param_band_idx, band, ch_idx;
508 : Word16 have_residual;
509 : Word16 brange[2];
510 : DIRAC_OUTPUT_SYNTHESIS_COV_STATE h_synthesis_state;
511 : Word32 mixing_matrix_smooth_fx[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS];
512 : Word16 mixing_matrix_smooth_e;
513 : Word32 mixing_matrix_res_smooth_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
514 140160 : Word16 mixing_matrix_res_smooth_e = 0;
515 140160 : move16();
516 : Word32 mixing_matrix_buffer_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
517 : Word16 mixing_matrix_buffer_e;
518 : Word32 input_f_real_fx[PARAM_MC_MAX_TRANSPORT_CHANS];
519 : Word32 input_f_imag_fx[PARAM_MC_MAX_TRANSPORT_CHANS];
520 :
521 : Word32 diff_f_real_fx[MAX_CICP_CHANNELS];
522 : Word32 diff_f_imag_fx[MAX_CICP_CHANNELS];
523 :
524 140160 : h_synthesis_state = hParamMC->h_output_synthesis_cov_state;
525 :
526 140160 : set_zero_fx( input_f_real_fx, PARAM_MC_MAX_TRANSPORT_CHANS );
527 140160 : set_zero_fx( input_f_imag_fx, PARAM_MC_MAX_TRANSPORT_CHANS );
528 :
529 140160 : set_zero_fx( diff_f_real_fx, MAX_CICP_CHANNELS );
530 140160 : set_zero_fx( diff_f_imag_fx, MAX_CICP_CHANNELS );
531 :
532 1950080 : FOR( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx++ )
533 : {
534 : /* final mixing */
535 1809920 : have_residual = 0;
536 1809920 : move16();
537 1809920 : brange[0] = hParamMC->band_grouping[param_band_idx];
538 1809920 : move16();
539 1809920 : brange[1] = hParamMC->band_grouping[( param_band_idx + 1 )];
540 1809920 : move16();
541 :
542 1809920 : if ( LT_16( brange[0], hParamMC->h_output_synthesis_params.max_band_decorr ) )
543 : {
544 1454400 : have_residual = 1;
545 1454400 : move16();
546 : }
547 :
548 1809920 : v_multc_fixed( mixing_matrix_fx[param_band_idx], L_deposit_h( hParamMC->h_output_synthesis_params.interpolator_fx[slot_idx_tot] ), mixing_matrix_smooth_fx, imult1616( nY, nX ) );
549 1809920 : mixing_matrix_smooth_e = mixing_matrix_e[param_band_idx]; // interpolator is W16
550 1809920 : move16();
551 :
552 1809920 : v_multc_fixed( h_synthesis_state.mixing_matrix_old_fx[param_band_idx], L_sub( ONE_IN_Q31, L_deposit_h( hParamMC->h_output_synthesis_params.interpolator_fx[slot_idx_tot] ) ), mixing_matrix_buffer_fx, imult1616( nY, nX ) );
553 1809920 : mixing_matrix_buffer_e = h_synthesis_state.mixing_matrix_old_exp[param_band_idx]; // interpolator is W16
554 1809920 : move16();
555 :
556 1809920 : v_add_fixed_me( mixing_matrix_smooth_fx, mixing_matrix_smooth_e, mixing_matrix_buffer_fx, mixing_matrix_buffer_e, mixing_matrix_smooth_fx, &mixing_matrix_smooth_e, imult1616( nY, nX ), 0 );
557 :
558 1809920 : IF( have_residual )
559 : {
560 : /* residual mixing matrix interpolation*/
561 :
562 1454400 : v_multc_fixed( mixing_matrix_res_fx[param_band_idx], L_deposit_h( hParamMC->h_output_synthesis_params.interpolator_fx[slot_idx_tot] ), mixing_matrix_res_smooth_fx, imult1616( nY, nY ) );
563 1454400 : mixing_matrix_res_smooth_e = mixing_matrix_res_e[param_band_idx]; // interpolator is W16
564 1454400 : move16();
565 :
566 1454400 : set_zero_fx( mixing_matrix_buffer_fx, imult1616( nY, nY ) );
567 1454400 : v_multc_fixed( h_synthesis_state.mixing_matrix_res_old_fx[param_band_idx], L_sub( ONE_IN_Q31, L_deposit_h( hParamMC->h_output_synthesis_params.interpolator_fx[slot_idx_tot] ) ), mixing_matrix_buffer_fx, imult1616( nY, nY ) );
568 1454400 : mixing_matrix_buffer_e = h_synthesis_state.mixing_matrix_res_old_exp[param_band_idx]; // interpolator is W16
569 1454400 : move16();
570 :
571 1454400 : v_add_fixed_me( mixing_matrix_res_smooth_fx, mixing_matrix_res_smooth_e, mixing_matrix_buffer_fx, mixing_matrix_buffer_e, mixing_matrix_res_smooth_fx, &mixing_matrix_res_smooth_e, imult1616( nY, nY ), 0 );
572 : }
573 :
574 :
575 9553920 : FOR( band = brange[0]; band < brange[1]; band++ )
576 : {
577 7744000 : assert( band >= 0 );
578 :
579 7744000 : IF( have_residual )
580 : {
581 : /* collect diffuse prototypes */
582 2803200 : assert( LT_16( band, hParamMC->h_output_synthesis_params.max_band_decorr ) );
583 19833600 : FOR( ch_idx = 0; ch_idx < nY; ch_idx++ )
584 : {
585 17030400 : diff_f_real_fx[ch_idx] = Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band];
586 17030400 : move32();
587 17030400 : diff_f_imag_fx[ch_idx] = Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band];
588 17030400 : move32();
589 : }
590 :
591 : /* apply residual mixing */
592 : {
593 : Word16 shifter;
594 : #ifdef OPT_SBA_DEC_V2_NBE
595 2803200 : shifter = sub( mixing_matrix_res_smooth_e, 32 );
596 : #else /* OPT_SBA_DEC_V2_NBE */
597 : #ifdef OPT_SBA_DEC_V2_BE
598 : shifter = sub( mixing_matrix_res_smooth_e, 31 );
599 : #else /* OPT_SBA_DEC_V2_BE */
600 : shifter = 31 - mixing_matrix_res_smooth_e;
601 : #endif /* OPT_SBA_DEC_V2_NBE */
602 : #endif /* OPT_SBA_DEC_V2_BE */
603 19833600 : FOR( ch_idx = 0; ch_idx < nY; ch_idx++ )
604 : {
605 : int i;
606 : Word16 idx;
607 : Word64 temp_real, temp_imag;
608 :
609 :
610 17030400 : idx = ch_idx;
611 17030400 : temp_real = 0;
612 17030400 : temp_imag = 0;
613 17030400 : move64();
614 17030400 : move64();
615 121209600 : for ( i = 0; i < nY; i++ )
616 : {
617 : #ifdef OPT_SBA_DEC_V2_NBE
618 104179200 : temp_real = W_mac_32_32( temp_real, mixing_matrix_res_smooth_fx[idx], diff_f_real_fx[i] );
619 104179200 : temp_imag = W_mac_32_32( temp_imag, mixing_matrix_res_smooth_fx[idx], diff_f_imag_fx[i] );
620 : #else /* OPT_SBA_DEC_V2_NBE */
621 : temp_real = W_add( temp_real, W_mult0_32_32( mixing_matrix_res_smooth_fx[idx], diff_f_real_fx[i] ) );
622 : temp_imag = W_add( temp_imag, W_mult0_32_32( mixing_matrix_res_smooth_fx[idx], diff_f_imag_fx[i] ) );
623 : #endif /* OPT_SBA_DEC_V2_NBE */
624 104179200 : idx += nY;
625 : }
626 : #ifdef OPT_SBA_DEC_V2_BE
627 17030400 : Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band] = W_shl_sat_l( temp_real, shifter );
628 17030400 : Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band] = W_shl_sat_l( temp_imag, shifter );
629 : #else /* OPT_SBA_DEC_V2_BE */
630 : Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band] = W_extract_l( W_shr( temp_real, shifter ) );
631 : Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band] = W_extract_l( W_shr( temp_imag, shifter ) );
632 : #endif /* OPT_SBA_DEC_V2_BE */
633 : }
634 : }
635 : }
636 : ELSE
637 : {
638 34969600 : FOR( ch_idx = 0; ch_idx < nY; ch_idx++ )
639 : {
640 30028800 : Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band] = 0;
641 30028800 : move32();
642 30028800 : Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band] = 0;
643 30028800 : move32();
644 : }
645 : }
646 :
647 : /* collect input signals, still in cldfb buffers */
648 23270400 : FOR( ch_idx = 0; ch_idx < nX; ch_idx++ )
649 : {
650 :
651 15526400 : input_f_real_fx[ch_idx] = Cldfb_RealBuffer_in_fx[ch_idx * hParamMC->num_freq_bands + band]; // Q6
652 15526400 : move32();
653 15526400 : input_f_imag_fx[ch_idx] = Cldfb_ImagBuffer_in_fx[ch_idx * hParamMC->num_freq_bands + band]; // Q6
654 15526400 : move32();
655 : }
656 :
657 : /* apply mixing matrix */
658 : {
659 : Word16 shifter;
660 7744000 : shifter = 31 - mixing_matrix_smooth_e;
661 :
662 54803200 : FOR( ch_idx = 0; ch_idx < nY; ch_idx++ )
663 : {
664 : int i;
665 : Word16 idx;
666 : Word64 temp_real, temp_imag;
667 :
668 :
669 47059200 : idx = ch_idx;
670 47059200 : temp_real = 0;
671 47059200 : temp_imag = 0;
672 47059200 : move64();
673 47059200 : move64();
674 141638400 : for ( i = 0; i < nX; i++ )
675 : {
676 94579200 : temp_real = W_add( temp_real, W_mult0_32_32( mixing_matrix_smooth_fx[idx], input_f_real_fx[i] ) );
677 94579200 : temp_imag = W_add( temp_imag, W_mult0_32_32( mixing_matrix_smooth_fx[idx], input_f_imag_fx[i] ) );
678 94579200 : idx += nY;
679 : }
680 47059200 : Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band] = L_add( Cldfb_RealBuffer_fx[ch_idx][slot_idx_sfr][band], W_extract_l( W_shr( temp_real, shifter ) ) );
681 47059200 : move32();
682 47059200 : Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band] = L_add( Cldfb_ImagBuffer_fx[ch_idx][slot_idx_sfr][band], W_extract_l( W_shr( temp_imag, shifter ) ) );
683 47059200 : move32();
684 : }
685 : }
686 : }
687 : }
688 :
689 140160 : return;
690 : }
691 :
692 : /*-------------------------------------------------------------------*
693 : * computeMixingMatrices()
694 : *
695 : * compute a mixing matrix using the convariance synthesis approach
696 : *-------------------------------------------------------------------*/
697 :
698 113120 : Word16 computeMixingMatrices_fx(
699 : const Word16 num_inputs, /* i : number of input channels */
700 : const Word16 num_outputs, /* i : number of output channels */
701 : const Word32 *Cx, /* i : input channel covariance matrix Q(31-Cx_e) */
702 : Word16 Cx_e,
703 : const Word32 *Cy, /* i : target covariance matrix Q(31-Cy_e) */
704 : Word16 Cy_e,
705 : const Word32 *Q, /* i : prototype matrix (usually a upmix matrix) Q_fx_e */
706 : Word16 Q_fx_e,
707 : const Word16 energy_compensation_flag, /* i : flag indicating that the energy compensation should be performed (i.e. no residual mixing matrix will follow) */
708 : const Word32 reg_Sx_fx, /* i : regularization factor for the input channel singular values */
709 : Word16 reg_Sx_e,
710 : const Word32 reg_ghat_fx, /* i : regularization factor for the normalization matrix Q(31-reg_ghat_e) */
711 : Word16 reg_ghat_e,
712 : Word32 *mixing_matrix_fx, /* o : resulting mixing matrix Q(31-mixing_matrix_out_e) */
713 : Word16 *mixing_matrix_out_e,
714 : Word32 *Cr_fx, /* o : residual covariance matrix Q(31-Cr_e) */
715 : Word16 *Cr_e )
716 : {
717 : Word16 i, j;
718 : Word16 out;
719 : Word16 nL, nC;
720 113120 : Word16 lengthCx = num_inputs;
721 113120 : Word16 lengthCy = num_outputs;
722 : Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
723 : Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
724 : Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
725 : Word32 Cx_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
726 : Word32 Cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
727 : Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; // Q31 out
728 : Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; // Q31 out
729 : Word16 Cx_fx_e;
730 : Word16 Cy_fx_e;
731 :
732 : Word32 svd_s_buffer_fx[MAX_OUTPUT_CHANNELS];
733 : Word16 svd_s_buffer_e[MAX_OUTPUT_CHANNELS];
734 :
735 :
736 : Word32 limit_fx;
737 : Word16 limit_e;
738 :
739 : Word32 L_tmp;
740 : Word16 tmp_e, tmp, exp;
741 :
742 : Word32 Ky_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
743 : Word32 Kx_fx[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
744 :
745 : Word16 Kx_fx_e[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
746 : Word16 Ky_fx_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
747 :
748 : Word32 Kx_reg_inv_fx[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
749 : Word16 Kx_reg_inv_e[MAX_TRANSPORT_CHANNELS * MAX_TRANSPORT_CHANNELS];
750 :
751 : Word32 Q_fx[PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS];
752 : Word16 Q_e;
753 :
754 : Word32 Q_Cx_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
755 : Word16 Q_Cx_e;
756 :
757 : Word32 Cy_hat_diag_fx[MAX_OUTPUT_CHANNELS];
758 : Word16 Cy_hat_diag_e;
759 : Word16 Cy_hat_diag_buff_e[MAX_OUTPUT_CHANNELS];
760 : Word32 G_hat_fx[MAX_OUTPUT_CHANNELS];
761 : Word16 G_hat_buff_e[MAX_OUTPUT_CHANNELS];
762 :
763 : Word16 mat_mult_buffer2_e, mat_mult_buffer3_e;
764 :
765 : Word32 mat_mult_buffer3_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
766 :
767 : Word16 mixing_matrix_e;
768 :
769 : Word16 Cr_fx_e;
770 :
771 :
772 : Word32 adj_fx[MAX_OUTPUT_CHANNELS];
773 : Word16 adj_e[MAX_OUTPUT_CHANNELS];
774 : Word32 *adj_fx_p;
775 : Word16 adj_fx_e;
776 :
777 : Word32 *Cr_p_fx, *Cy_tilde_p_fx, *Cy_p_fx;
778 113120 : push_wmops( "dirac_cov_mix_mat" );
779 :
780 113120 : out = EXIT_SUCCESS;
781 113120 : move16();
782 :
783 113120 : set32_fx( svd_s_buffer_fx, 0, MAX_OUTPUT_CHANNELS );
784 1923040 : FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
785 : {
786 1809920 : set32_fx( svd_in_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
787 1809920 : set32_fx( svd_u_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
788 1809920 : set32_fx( svd_v_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
789 : }
790 :
791 :
792 113120 : Copy32( Q, Q_fx, imult1616( lengthCy, lengthCx ) );
793 113120 : Copy32( Cx, Cx_fx, imult1616( lengthCx, lengthCx ) );
794 113120 : Copy32( Cy, Cy_fx, imult1616( lengthCy, lengthCy ) );
795 :
796 113120 : Q_e = Q_fx_e;
797 113120 : move16();
798 113120 : Cx_fx_e = Cx_e;
799 113120 : move16();
800 113120 : Cy_fx_e = Cy_e;
801 113120 : move16();
802 :
803 :
804 : /*-----------------------------------------------------------------*
805 : * Decomposition of Cy
806 : *-----------------------------------------------------------------*/
807 :
808 : /* Processing the SVD */
809 :
810 113120 : mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 );
811 :
812 113120 : svd_fx( svd_in_buffer_fx, Cy_fx_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, lengthCy, lengthCy );
813 113120 : Word16 max_e = -32;
814 : /* Computing Ky */
815 688444 : FOR( i = 0; i < lengthCy; ++i )
816 : {
817 3533968 : FOR( j = 0; j < lengthCy; ++j )
818 : {
819 2958644 : tmp_e = svd_s_buffer_e[j];
820 2958644 : move16();
821 2958644 : L_tmp = Sqrt32( svd_s_buffer_fx[j], &tmp_e );
822 2958644 : Ky_fx[i + ( j * lengthCy )] = Mpy_32_32( svd_u_buffer_fx[i][j], L_tmp ); // Q(31-tmp_e)
823 2958644 : move32();
824 2958644 : Ky_fx_e[i + ( j * lengthCy )] = tmp_e;
825 2958644 : move16();
826 2958644 : max_e = s_max( max_e, tmp_e );
827 : }
828 : }
829 3071764 : FOR( i = 0; i < lengthCy * lengthCy; ++i )
830 : {
831 2958644 : Ky_fx[i] = L_shr( Ky_fx[i], sub( max_e, Ky_fx_e[i] ) );
832 2958644 : move32();
833 2958644 : Ky_fx_e[i] = max_e;
834 2958644 : move16();
835 : }
836 :
837 : /*-----------------------------------------------------------------*
838 : * Decomposition of Cx
839 : *-----------------------------------------------------------------*/
840 :
841 : /* Processing the SVD */
842 :
843 113120 : mat2svdMat_fx( Cx_fx, svd_in_buffer_fx, lengthCx, lengthCx, 0 );
844 :
845 113120 : svd_fx( svd_in_buffer_fx, Cx_fx_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, lengthCx, lengthCx );
846 113120 : max_e = -32;
847 339920 : FOR( i = 0; i < lengthCx; ++i )
848 : {
849 682080 : FOR( j = 0; j < lengthCx; ++j )
850 : {
851 455280 : tmp_e = svd_s_buffer_e[j];
852 455280 : move16();
853 455280 : L_tmp = Sqrt32( svd_s_buffer_fx[j], &tmp_e );
854 455280 : Kx_fx[( i + ( j * lengthCx ) )] = Mpy_32_32( svd_u_buffer_fx[i][j], L_tmp ); // Q(31-tmp_e)
855 455280 : move32();
856 455280 : Kx_fx_e[( i + ( j * lengthCx ) )] = tmp_e;
857 455280 : move16();
858 455280 : max_e = s_max( max_e, tmp_e );
859 : }
860 : }
861 568400 : FOR( i = 0; i < lengthCx * lengthCx; ++i )
862 : {
863 455280 : Kx_fx[i] = L_shr( Kx_fx[i], sub( max_e, Kx_fx_e[i] ) );
864 455280 : move32();
865 455280 : Kx_fx_e[i] = max_e;
866 455280 : move16();
867 : }
868 :
869 339920 : FOR( i = 0; i < lengthCx; ++i )
870 : {
871 226800 : tmp_e = svd_s_buffer_e[i];
872 226800 : move16();
873 226800 : svd_s_buffer_fx[i] = Sqrt32( svd_s_buffer_fx[i], &tmp_e ); // Q(31-tmp_e)
874 226800 : move32();
875 226800 : svd_s_buffer_e[i] = tmp_e;
876 226800 : move16();
877 : }
878 :
879 : /*-----------------------------------------------------------------*
880 : * Regularization of Sx
881 : *-----------------------------------------------------------------*/
882 :
883 113120 : limit_fx = svd_s_buffer_fx[0];
884 113120 : move32();
885 113120 : limit_e = svd_s_buffer_e[0];
886 113120 : move16();
887 226800 : FOR( i = 1; i < lengthCx; i++ )
888 : {
889 : #ifdef OPT_MCH_DEC_V1_NBE
890 113680 : IF( GT_32( svd_s_buffer_fx[i], L_shl_sat( limit_fx, sub( limit_e, svd_s_buffer_e[i] ) ) ) )
891 : #else /* OPT_MCH_DEC_V1_NBE */
892 : IF( BASOP_Util_Cmp_Mant32Exp( svd_s_buffer_fx[i], svd_s_buffer_e[i], limit_fx, limit_e ) > 0 )
893 : #endif /* OPT_MCH_DEC_V1_NBE */
894 : {
895 0 : limit_fx = svd_s_buffer_fx[i];
896 0 : move32();
897 0 : limit_e = svd_s_buffer_e[i];
898 0 : move16();
899 : }
900 : }
901 :
902 113120 : limit_e = add( limit_e, reg_Sx_e );
903 :
904 : #ifdef OPT_MCH_DEC_V1_BE
905 113120 : limit_fx = Madd_32_32( EPSILON_FX, limit_fx, reg_Sx_fx );
906 : #else /* OPT_MCH_DEC_V1_BE */
907 : L_tmp = Mpy_32_32( limit_fx, reg_Sx_fx );
908 : limit_fx = L_add( L_tmp, EPSILON_FX );
909 : #endif /* OPT_MCH_DEC_V1_BE */
910 :
911 339920 : FOR( i = 0; i < lengthCx; ++i )
912 : {
913 : #ifdef OPT_MCH_DEC_V1_NBE
914 226800 : IF( LT_32( L_shl_sat( svd_s_buffer_fx[i], sub( svd_s_buffer_e[i], limit_e ) ), limit_fx ) )
915 : #else /* OPT_MCH_DEC_V1_NBE */
916 : IF( BASOP_Util_Cmp_Mant32Exp( svd_s_buffer_fx[i], svd_s_buffer_e[i], limit_fx, limit_e ) < 0 )
917 : #endif /* OPT_MCH_DEC_V1_NBE */
918 : {
919 51307 : svd_s_buffer_fx[i] = limit_fx;
920 51307 : move32();
921 51307 : svd_s_buffer_e[i] = limit_e;
922 51307 : move16();
923 : }
924 : }
925 :
926 :
927 113120 : limit_fx = 0;
928 113120 : move32();
929 113120 : limit_e = 0;
930 113120 : move16();
931 :
932 :
933 : /*-----------------------------------------------------------------*
934 : * regularized Kx-1
935 : *-----------------------------------------------------------------*/
936 :
937 339920 : FOR( i = 0; i < lengthCx; ++i )
938 : {
939 : Word16 scale, reg_fac_fx;
940 226800 : reg_fac_fx = BASOP_Util_Divide3232_Scale( 1, svd_s_buffer_fx[i], &scale );
941 226800 : scale = add( scale, sub( Q31, svd_s_buffer_e[i] ) );
942 682080 : FOR( j = 0; j < lengthCx; ++j )
943 : {
944 455280 : Kx_reg_inv_fx[i + j * lengthCx] = Mpy_32_16_1( svd_u_buffer_fx[j][i], reg_fac_fx ); // Q(31-scale)
945 455280 : move32();
946 455280 : Kx_reg_inv_e[i + j * lengthCx] = scale;
947 455280 : move16();
948 : }
949 : }
950 :
951 : /*-----------------------------------------------------------------*
952 : * normalization matrix G hat
953 : *-----------------------------------------------------------------*/
954 :
955 : /* Computing Q*Cx*Q' */
956 :
957 113120 : matrix_product_mant_exp_fx( Q_fx, Q_e, lengthCy, lengthCx, 0, Cx_fx, Cx_fx_e, lengthCx, lengthCx, 0, Q_Cx_fx, &Q_Cx_e );
958 :
959 113120 : matrix_product_diag_fx( Q_Cx_fx, Q_Cx_e, lengthCy, lengthCx, 0, Q_fx, Q_e, lengthCy, lengthCx, 1, Cy_hat_diag_fx, &Cy_hat_diag_e );
960 :
961 :
962 : #ifdef OPT_MCH_DEC_V1_NBE
963 113120 : Word16 com_e = sub( limit_e, Cy_hat_diag_e );
964 : #endif /* OPT_MCH_DEC_V1_NBE */
965 688444 : FOR( i = 0; i < lengthCy; ++i )
966 : {
967 : #ifdef OPT_MCH_DEC_V1_NBE
968 575324 : IF( GT_32( Cy_hat_diag_fx[i], L_shl_sat( limit_fx, com_e ) ) )
969 : #else /* OPT_MCH_DEC_V1_NBE */
970 : IF( BASOP_Util_Cmp_Mant32Exp( Cy_hat_diag_fx[i], Cy_hat_diag_e, limit_fx, limit_e ) > 0 )
971 : #endif /* OPT_MCH_DEC_V1_NBE */
972 : {
973 575324 : limit_fx = Cy_hat_diag_fx[i];
974 575324 : move32();
975 575324 : limit_e = Cy_hat_diag_e;
976 575324 : move16();
977 : }
978 : }
979 : #ifdef OPT_MCH_DEC_V1_BE
980 113120 : limit_fx = Madd_32_32( EPSILON_FX, limit_fx, reg_ghat_fx ); // limit_e+ reg_ghat_e
981 : #else /* OPT_MCH_DEC_V1_BE */
982 : L_tmp = Mpy_32_32( limit_fx, reg_ghat_fx ); // limit_e+ reg_ghat_e
983 : limit_fx = L_add( L_tmp, EPSILON_FX );
984 : #endif /* OPT_MCH_DEC_V1_BE */
985 113120 : limit_e = add( limit_e, reg_ghat_e );
986 :
987 : #ifdef OPT_MCH_DEC_V1_NBE
988 113120 : com_e = sub( Cy_hat_diag_e, limit_e );
989 : #endif /* OPT_MCH_DEC_V1_NBE */
990 688444 : FOR( i = 0; i < lengthCy; ++i )
991 : {
992 575324 : Cy_hat_diag_buff_e[i] = Cy_hat_diag_e;
993 575324 : move16();
994 :
995 : #ifdef OPT_MCH_DEC_V1_NBE
996 575324 : IF( GT_32( limit_fx, L_shl_sat( Cy_hat_diag_fx[i], com_e ) ) )
997 : #else /* OPT_MCH_DEC_V1_NBE */
998 : IF( BASOP_Util_Cmp_Mant32Exp( limit_fx, limit_e, Cy_hat_diag_fx[i], Cy_hat_diag_buff_e[i] ) > 0 ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
999 : #endif /* OPT_MCH_DEC_V1_NBE */
1000 : {
1001 10 : Cy_hat_diag_fx[i] = limit_fx;
1002 10 : move32();
1003 10 : Cy_hat_diag_buff_e[i] = limit_e;
1004 10 : move16();
1005 : }
1006 :
1007 575324 : tmp = BASOP_Util_Divide3232_Scale( Cy_fx[( i + ( i * lengthCy ) )], Cy_hat_diag_fx[i], &exp );
1008 575324 : exp = add( exp, sub( Cy_fx_e, Cy_hat_diag_buff_e[i] ) );
1009 575324 : L_tmp = Sqrt32( L_deposit_h( tmp ), &exp );
1010 575324 : G_hat_fx[i] = L_tmp;
1011 575324 : move32();
1012 575324 : G_hat_buff_e[i] = exp;
1013 575324 : move16();
1014 : }
1015 :
1016 :
1017 : /*-----------------------------------------------------------------*
1018 : * Formulate optimal P
1019 : *-----------------------------------------------------------------*/
1020 :
1021 : /* Computing the input matrix Kx'*Q'*G_hat'*Ky */
1022 :
1023 : Word16 mat_mult_buffer1_fx_e;
1024 :
1025 : Word16 mat_mult_buffer2_fx_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1026 :
1027 113120 : matrix_product_mant_exp_fx( Kx_fx, Kx_fx_e[0], lengthCx, lengthCx, 1, Q_fx, Q_e, lengthCy, lengthCx, 1, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e );
1028 :
1029 113120 : matrix_diag_product_fx_2( mat_mult_buffer1_fx, mat_mult_buffer1_fx_e, lengthCx, lengthCy, 0, G_hat_fx, G_hat_buff_e, lengthCy, mat_mult_buffer2_fx, mat_mult_buffer2_fx_e );
1030 :
1031 113120 : matrix_product_mant_exp_fx( mat_mult_buffer2_fx, mat_mult_buffer2_fx_e[0], lengthCx, lengthCy, 0, Ky_fx, Ky_fx_e[0], lengthCy, lengthCy, 0, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e );
1032 :
1033 113120 : IF( LT_16( lengthCx, lengthCy ) )
1034 : {
1035 113120 : mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 1 );
1036 113120 : nL = lengthCy;
1037 113120 : move16();
1038 113120 : nC = lengthCx;
1039 113120 : move16();
1040 113120 : svd_fx( svd_in_buffer_fx, mat_mult_buffer1_fx_e, svd_v_buffer_fx, svd_s_buffer_fx, svd_u_buffer_fx, svd_s_buffer_e, nL, nC );
1041 : }
1042 : ELSE
1043 : {
1044 0 : mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 );
1045 0 : nL = lengthCx;
1046 0 : move16();
1047 0 : nC = lengthCy;
1048 0 : move16();
1049 0 : svd_fx( svd_in_buffer_fx, mat_mult_buffer1_fx_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, nL, nC );
1050 : }
1051 :
1052 : /* Actually Processing P */
1053 :
1054 : /* can be skipped: lambda is always column-truncated identity matrix, so this operation just
1055 : truncates V to num_input_channel columns */
1056 :
1057 113120 : svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx );
1058 113120 : svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx );
1059 :
1060 113120 : mat_mult_buffer1_fx_e = 0;
1061 113120 : move16();
1062 113120 : mat_mult_buffer2_e = 0;
1063 113120 : move16();
1064 :
1065 113120 : matrix_product_mant_exp_fx( mat_mult_buffer1_fx, mat_mult_buffer1_fx_e, lengthCy, lengthCx, 0,
1066 : mat_mult_buffer2_fx, mat_mult_buffer2_e, lengthCx, lengthCx, 1,
1067 : mat_mult_buffer3_fx, &mat_mult_buffer3_e );
1068 :
1069 : /************************ Formulate M **********************/
1070 :
1071 113120 : matrix_product_mant_exp_fx( Ky_fx, Ky_fx_e[0], lengthCy, lengthCy, 0, mat_mult_buffer3_fx, mat_mult_buffer3_e, lengthCy, lengthCx, 0, mat_mult_buffer1_fx, &mat_mult_buffer1_fx_e );
1072 :
1073 : Word16 mixing_matrix_fx_e[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS];
1074 :
1075 : Word16 mat_mult_buffer1_fx_e1[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1076 113120 : set16_fx( mat_mult_buffer1_fx_e1, mat_mult_buffer1_fx_e, MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS );
1077 :
1078 113120 : matrix_product_mant_exp( mat_mult_buffer1_fx, mat_mult_buffer1_fx_e1, lengthCy, lengthCx, 0, Kx_reg_inv_fx, Kx_reg_inv_e, lengthCx, lengthCx, 0, mixing_matrix_fx, mixing_matrix_fx_e );
1079 :
1080 : /*-----------------------------------------------------------------*
1081 : * Formulate Cr
1082 : *-----------------------------------------------------------------*/
1083 :
1084 : /* Compute Cy_tilde = M*Cx*M' */
1085 :
1086 :
1087 : Word16 Cx_e_arr[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
1088 113120 : set16_fx( Cx_e_arr, Cx_fx_e, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
1089 113120 : matrix_product_mant_exp( mixing_matrix_fx, mixing_matrix_fx_e, lengthCy, lengthCx, 0, Cx_fx, Cx_e_arr, lengthCx, lengthCx, 0, mat_mult_buffer1_fx, mat_mult_buffer1_fx_e1 );
1090 :
1091 113120 : matrix_product_mant_exp( mat_mult_buffer1_fx, mat_mult_buffer1_fx_e1, lengthCy, lengthCx, 0, mixing_matrix_fx, mixing_matrix_fx_e, lengthCy, lengthCx, 1, mat_mult_buffer2_fx, mat_mult_buffer2_fx_e );
1092 :
1093 113120 : exp = mixing_matrix_fx_e[0];
1094 113120 : move16();
1095 1156848 : FOR( i = 1; i < lengthCy * lengthCx; i++ )
1096 : {
1097 1043728 : if ( LT_16( exp, mixing_matrix_fx_e[i] ) )
1098 : {
1099 83145 : exp = mixing_matrix_fx_e[i];
1100 83145 : move16();
1101 : }
1102 : }
1103 :
1104 1269968 : FOR( i = 0; i < lengthCy * lengthCx; i++ )
1105 : {
1106 1156848 : mixing_matrix_fx[i] = L_shr( mixing_matrix_fx[i], sub( exp, mixing_matrix_fx_e[i] ) ); // Q(31-exp)
1107 1156848 : move32();
1108 : }
1109 :
1110 113120 : mixing_matrix_e = exp;
1111 113120 : move16();
1112 :
1113 113120 : Cr_p_fx = Cr_fx;
1114 113120 : Cy_p_fx = Cy_fx;
1115 113120 : Cy_tilde_p_fx = mat_mult_buffer2_fx;
1116 : Word16 Cr_e_arr[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
1117 688444 : FOR( i = 0; i < lengthCy; ++i )
1118 : {
1119 3533968 : FOR( j = 0; j < lengthCy; ++j )
1120 : {
1121 :
1122 2958644 : *( Cr_p_fx ) = BASOP_Util_Add_Mant32Exp( *( Cy_p_fx ), Cy_fx_e, L_negate( *( Cy_tilde_p_fx ) ), mat_mult_buffer2_fx_e[i * lengthCy + j], &Cr_e_arr[i * lengthCy + j] );
1123 2958644 : move32();
1124 2958644 : Cr_p_fx++;
1125 2958644 : Cy_p_fx++;
1126 2958644 : Cy_tilde_p_fx++;
1127 : }
1128 :
1129 : /* Avoid Meaningless negative main diagonal elements */
1130 575324 : IF( Cr_fx[i + ( i * lengthCy )] < 0 )
1131 : {
1132 62377 : Cr_fx[i + ( i * lengthCy )] = 0;
1133 62377 : move32();
1134 62377 : Cr_e_arr[i + ( i * lengthCy )] = 0;
1135 62377 : move16();
1136 : }
1137 : }
1138 :
1139 113120 : exp = Cr_e_arr[0];
1140 113120 : move16();
1141 2958644 : FOR( i = 1; i < lengthCy * lengthCy; i++ )
1142 : {
1143 2845524 : if ( LT_16( exp, Cr_e_arr[i] ) )
1144 : {
1145 107041 : exp = Cr_e_arr[i];
1146 107041 : move16();
1147 : }
1148 : }
1149 :
1150 3071764 : FOR( i = 0; i < lengthCy * lengthCy; i++ )
1151 : {
1152 2958644 : Cr_fx[i] = L_shr( Cr_fx[i], sub( exp, Cr_e_arr[i] ) ); // Q(31-exp)
1153 2958644 : move32();
1154 : }
1155 :
1156 113120 : Cr_fx_e = exp;
1157 113120 : move16();
1158 :
1159 113120 : exp = mat_mult_buffer2_fx_e[0];
1160 113120 : move16();
1161 2958644 : FOR( i = 1; i < lengthCy * lengthCy; i++ )
1162 : {
1163 2845524 : if ( LT_16( exp, mat_mult_buffer2_fx_e[i] ) )
1164 : {
1165 157715 : exp = mat_mult_buffer2_fx_e[i];
1166 157715 : move16();
1167 : }
1168 : }
1169 :
1170 3071764 : FOR( i = 0; i < lengthCy * lengthCy; i++ )
1171 : {
1172 2958644 : mat_mult_buffer2_fx[i] = L_shr( mat_mult_buffer2_fx[i], sub( exp, mat_mult_buffer2_fx_e[i] ) ); // Q(31-exp)
1173 2958644 : move32();
1174 : }
1175 :
1176 113120 : mat_mult_buffer2_e = exp;
1177 113120 : move16();
1178 :
1179 : /*-----------------------------------------------------------------*
1180 : * Energy Compensation
1181 : *-----------------------------------------------------------------*/
1182 :
1183 113120 : IF( EQ_16( energy_compensation_flag, 1 ) )
1184 : {
1185 22220 : adj_fx_p = svd_s_buffer_fx;
1186 22220 : Cy_tilde_p_fx = mat_mult_buffer2_fx;
1187 :
1188 135100 : FOR( i = 0; i < lengthCy; ++i )
1189 : {
1190 : /* Avoid correction for very small energies,
1191 : main diagonal elements of Cy_tilde_p may be negative */
1192 112880 : IF( Cy_tilde_p_fx[i + ( i * lengthCy )] < 0 )
1193 : {
1194 0 : adj_fx_p[i] = 1073741824; // 1.0f in Q30
1195 0 : move32();
1196 0 : adj_e[i] = 1;
1197 0 : move16();
1198 : }
1199 : ELSE
1200 : {
1201 112880 : tmp = BASOP_Util_Divide3232_Scale( Cy_fx[i + ( i * lengthCy )], L_add( Cy_tilde_p_fx[i + ( i * lengthCy )], EPSILON_FX ), &exp );
1202 112880 : exp = add( exp, sub( Cy_fx_e, mat_mult_buffer2_e ) );
1203 112880 : L_tmp = L_deposit_h( tmp );
1204 112880 : L_tmp = Sqrt32( L_tmp, &exp );
1205 112880 : adj_fx_p[i] = L_tmp;
1206 112880 : move32();
1207 112880 : adj_e[i] = exp;
1208 112880 : move16();
1209 : }
1210 :
1211 112880 : Word32 temp = W_shl_sat_l( W_deposit32_l( 4 ), sub( 31, adj_e[i] ) );
1212 112880 : IF( GT_32( adj_fx_p[i], temp ) )
1213 : {
1214 5 : adj_fx_p[i] = 1073741824; // 1.0f in Q30
1215 5 : move32();
1216 5 : adj_e[i] = 3;
1217 5 : move16();
1218 : }
1219 : }
1220 :
1221 22220 : exp = adj_e[0];
1222 22220 : move16();
1223 112880 : FOR( i = 1; i < lengthCy; i++ )
1224 : {
1225 90660 : if ( LT_16( exp, adj_e[i] ) )
1226 : {
1227 1074 : exp = adj_e[i];
1228 1074 : move16();
1229 : }
1230 : }
1231 :
1232 135100 : FOR( i = 0; i < lengthCy; i++ )
1233 : {
1234 112880 : adj_fx[i] = L_shr( adj_fx_p[i], sub( exp, adj_e[i] ) ); // Q(31-exp)
1235 112880 : move32();
1236 : }
1237 22220 : adj_fx_e = exp;
1238 22220 : move16();
1239 :
1240 22220 : diag_matrix_product_fx( adj_fx, adj_fx_e, lengthCy, mixing_matrix_fx, mixing_matrix_e, lengthCy, lengthCx, 0, mat_mult_buffer3_fx, &mat_mult_buffer3_e );
1241 :
1242 22220 : Copy32( mat_mult_buffer3_fx, mixing_matrix_fx, imult1616( lengthCx, lengthCy ) ); // Q(31-mat_mult_buffer3_e)
1243 22220 : mixing_matrix_e = mat_mult_buffer3_e;
1244 22220 : move16();
1245 : }
1246 :
1247 113120 : *mixing_matrix_out_e = mixing_matrix_e;
1248 113120 : move16();
1249 113120 : *Cr_e = Cr_fx_e;
1250 113120 : move16();
1251 113120 : pop_wmops();
1252 :
1253 113120 : return out;
1254 : }
1255 :
1256 : /*-------------------------------------------------------------------*
1257 : * computeMixingMatricesResidual()
1258 : *
1259 : * compute a residual mixing matrix using the covariance synthesis approach
1260 : *-------------------------------------------------------------------*/
1261 :
1262 90900 : Word16 computeMixingMatricesResidual_fx(
1263 : const Word32 num_outputs, /* i : number of output channels */
1264 : const Word32 *Cx_fx, /* i : vector containing the diagonal diffuse prototype covariance Q(31-Cx_e) */
1265 : const Word16 Cx_e,
1266 : const Word32 *Cy_fx, /* i : matrix containing the missing cov (Cr from computeMixingMatrices()) Q(31-Cy_fx_e) */
1267 : const Word16 Cy_fx_e,
1268 : const Word32 reg_Sx_fx, /* i : regularization factor for the input channel singular values Q(31-reg_Sx_e) */
1269 : const Word16 reg_Sx_e,
1270 : const Word32 reg_ghat_fx, /* i : regularization factor for the normalization matrix Q(31-reg_ghat_e) */
1271 : const Word16 reg_ghat_e,
1272 : Word32 *mixing_matrix_fx, /* o : resulting residual mixing matrix Q(31-mixing_matrix_ret_e) */
1273 : Word16 *mixing_matrix_ret_e )
1274 : {
1275 : Word16 i, j;
1276 : Word16 out, lengthCx, lengthCy;
1277 90900 : out = EXIT_SUCCESS;
1278 90900 : move16();
1279 90900 : lengthCx = extract_l( num_outputs );
1280 90900 : lengthCy = extract_l( num_outputs );
1281 :
1282 : Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
1283 : Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1284 : Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; // Q31 out
1285 : Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; // Q31 out
1286 :
1287 : Word16 mat_mult_buffer1_buff_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1288 :
1289 90900 : push_wmops( "dirac_cov_mix_mat_r" );
1290 :
1291 : Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1292 : Word32 adj_fx[MAX_OUTPUT_CHANNELS];
1293 : Word32 mat_mult_buffer3_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1294 90900 : Word16 mixing_matrix_e = 0, mat_mult_buffer1_e, adj_e, mat_mult_buffer3_e, mat_mult_buffer2_e;
1295 90900 : move16();
1296 :
1297 90900 : Word32 svd_s_buffer_fx[MAX_OUTPUT_CHANNELS] = { 0 };
1298 : Word16 svd_s_buffer_e[MAX_OUTPUT_CHANNELS];
1299 : Word32 L_tmp;
1300 : Word16 tmp_e;
1301 : Word16 tmp, scale;
1302 : Word32 div_tmp;
1303 : Word16 exp;
1304 :
1305 : Word32 Kx_fx[MAX_OUTPUT_CHANNELS];
1306 : Word16 Ky_fx_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1307 : Word32 Ky_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1308 : Word16 Kx_fx_e[MAX_OUTPUT_CHANNELS];
1309 :
1310 : Word32 limit_fx;
1311 : Word16 limit_e;
1312 :
1313 : Word32 Kx_reg_inv_fx[MAX_OUTPUT_CHANNELS];
1314 : Word16 Kx_reg_inv_e[MAX_OUTPUT_CHANNELS];
1315 :
1316 : Word32 Cy_hat_diag_fx[MAX_OUTPUT_CHANNELS];
1317 : Word16 Cy_hat_diag_e;
1318 :
1319 : Word16 Cy_hat_diag_fx_e[MAX_OUTPUT_CHANNELS];
1320 : Word32 G_hat_fx[MAX_OUTPUT_CHANNELS];
1321 : Word16 G_hat_e[MAX_OUTPUT_CHANNELS];
1322 :
1323 : Word32 *adj_fx_p;
1324 : Word16 adj_buff_e[MAX_OUTPUT_CHANNELS];
1325 :
1326 : Word32 Cy_tilde_fx[MAX_OUTPUT_CHANNELS];
1327 : Word16 Cy_tilde_e;
1328 :
1329 : /*-----------------------------------------------------------------*
1330 : * Decomposition of Cy
1331 : *-----------------------------------------------------------------*/
1332 :
1333 : /* Processing the SVD */
1334 :
1335 : /* linear array to svd buffer */
1336 90900 : mat2svdMat_fx( Cy_fx, svd_in_buffer_fx, lengthCy, lengthCy, 0 );
1337 :
1338 90900 : svd_fx( svd_in_buffer_fx, Cy_fx_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, lengthCy, lengthCy );
1339 :
1340 : /* Computing Ky */
1341 90900 : Word16 max_e = -32;
1342 553344 : FOR( i = 0; i < lengthCy; ++i )
1343 : {
1344 2841348 : FOR( j = 0; j < lengthCy; ++j )
1345 : {
1346 2378904 : tmp_e = svd_s_buffer_e[j];
1347 2378904 : move16();
1348 2378904 : L_tmp = Sqrt32( svd_s_buffer_fx[j], &tmp_e );
1349 2378904 : Ky_fx[i + j * lengthCy] = Mpy_32_32( svd_u_buffer_fx[i][j], L_tmp ); // Q(31-tmp_e)
1350 2378904 : move32();
1351 2378904 : Ky_fx_e[i + j * lengthCy] = tmp_e;
1352 2378904 : move16();
1353 2378904 : max_e = s_max( max_e, tmp_e );
1354 : }
1355 : }
1356 :
1357 2469804 : FOR( i = 0; i < lengthCy * lengthCy; ++i )
1358 : {
1359 2378904 : Ky_fx[i] = L_shr( Ky_fx[i], sub( max_e, Ky_fx_e[i] ) );
1360 2378904 : move32();
1361 2378904 : Ky_fx_e[i] = max_e;
1362 2378904 : move16();
1363 : }
1364 :
1365 : /*-----------------------------------------------------------------*
1366 : * Decomposition of Cx
1367 : *-----------------------------------------------------------------*/
1368 :
1369 : /* Processing the SVD of Cx*/
1370 : /* Cx is a diagonal matrix, so SVD would lead to the sorted diagonal as S and u
1371 : * would be just indicating the sorting index, so go straight to Kx as the
1372 : * square root of the diagonal of Cx */
1373 :
1374 : /* Computing Kx */
1375 90900 : max_e = -32;
1376 553344 : FOR( i = 0; i < lengthCx; ++i )
1377 : {
1378 462444 : exp = Cx_e;
1379 462444 : move16();
1380 462444 : Kx_fx[i] = Sqrt32( Cx_fx[i], &exp );
1381 462444 : move32();
1382 462444 : Kx_fx_e[i] = exp;
1383 462444 : move16();
1384 462444 : max_e = s_max( max_e, exp );
1385 : }
1386 :
1387 553344 : FOR( i = 0; i < lengthCx; ++i )
1388 : {
1389 462444 : Kx_fx[i] = L_shr( Kx_fx[i], sub( max_e, Kx_fx_e[i] ) );
1390 462444 : move32();
1391 462444 : Kx_fx_e[i] = max_e;
1392 462444 : move16();
1393 : }
1394 :
1395 : /*-----------------------------------------------------------------*
1396 : * Regularization of Sx
1397 : *-----------------------------------------------------------------*/
1398 :
1399 90900 : limit_fx = Kx_fx[0];
1400 90900 : move32();
1401 :
1402 462444 : FOR( i = 1; i < lengthCx; i++ )
1403 : {
1404 371544 : IF( GT_32( Kx_fx[i], limit_fx ) )
1405 : {
1406 142098 : limit_fx = Kx_fx[i];
1407 142098 : move32();
1408 : }
1409 : }
1410 :
1411 90900 : L_tmp = Mpy_32_32( limit_fx, reg_Sx_fx ); // limit_e + reg_Sx_e
1412 90900 : L_tmp = L_add( L_tmp, EPSILLON_FX );
1413 90900 : limit_fx = L_tmp;
1414 90900 : move16();
1415 90900 : limit_e = add( Kx_fx_e[0], reg_Sx_e );
1416 :
1417 553344 : FOR( i = 0; i < lengthCx; ++i )
1418 : {
1419 : #ifdef OPT_MCH_DEC_V1_NBE
1420 462444 : IF( GT_32( Kx_fx[i], L_shl_sat( limit_fx, sub( limit_e, Kx_fx_e[i] ) ) ) )
1421 : #else /* OPT_MCH_DEC_V1_NBE */
1422 : IF( BASOP_Util_Cmp_Mant32Exp( Kx_fx[i], Kx_fx_e[i], limit_fx, limit_e ) > 0 )
1423 : #endif /* OPT_MCH_DEC_V1_NBE */
1424 : {
1425 461587 : div_tmp = Kx_fx[i];
1426 461587 : move32();
1427 461587 : exp = Kx_fx_e[i];
1428 461587 : move16();
1429 : }
1430 : ELSE
1431 : {
1432 857 : div_tmp = limit_fx;
1433 857 : move32();
1434 857 : exp = limit_e;
1435 857 : move16();
1436 : }
1437 462444 : tmp = BASOP_Util_Divide3232_Scale( 1073741824, div_tmp, &scale ); // 1073741824 -> 1.0f in Q30
1438 462444 : scale = add( scale, sub( Q1, exp ) );
1439 :
1440 462444 : Kx_reg_inv_fx[i] = L_deposit_h( tmp );
1441 462444 : move32();
1442 462444 : Kx_reg_inv_e[i] = scale;
1443 462444 : move16();
1444 : }
1445 :
1446 90900 : limit_fx = 0;
1447 90900 : move32();
1448 90900 : limit_e = 0;
1449 90900 : move16();
1450 :
1451 : /*-----------------------------------------------------------------*
1452 : * regularized Kx-1
1453 : *-----------------------------------------------------------------*/
1454 :
1455 : /*-----------------------------------------------------------------*
1456 : * normalization matrix G hat
1457 : *-----------------------------------------------------------------*/
1458 :
1459 : /* Computing Cy_hat_diag */
1460 90900 : Copy32( Cx_fx, Cy_hat_diag_fx, extract_l( num_outputs ) ); // Q(31-Cx_e)
1461 90900 : Cy_hat_diag_e = Cx_e;
1462 90900 : move16();
1463 :
1464 : #ifdef OPT_MCH_DEC_V1_NBE
1465 90900 : Word16 com_e = sub( limit_e, Cy_hat_diag_e );
1466 : #endif /* OPT_MCH_DEC_V1_NBE */
1467 553344 : FOR( i = 0; i < lengthCy; ++i )
1468 : {
1469 : #ifdef OPT_MCH_DEC_V1_NBE
1470 462444 : IF( GT_32( Cy_hat_diag_fx[i], L_shl_sat( limit_fx, com_e ) ) )
1471 : #else /* OPT_MCH_DEC_V1_NBE */
1472 : IF( BASOP_Util_Cmp_Mant32Exp( Cy_hat_diag_fx[i], Cy_hat_diag_e, limit_fx, limit_e ) > 0 )
1473 : #endif /* OPT_MCH_DEC_V1_NBE */
1474 : {
1475 462444 : limit_fx = Cy_hat_diag_fx[i];
1476 462444 : move32();
1477 462444 : limit_e = Cy_hat_diag_e;
1478 462444 : move16();
1479 : }
1480 : }
1481 :
1482 : #ifdef OPT_MCH_DEC_V1_BE
1483 90900 : limit_fx = Madd_32_32( EPSILON_FX, limit_fx, reg_ghat_fx ); // Q(limit_e+reg_ghat_e)
1484 : #else /* OPT_MCH_DEC_V1_BE */
1485 : L_tmp = Mpy_32_32( limit_fx, reg_ghat_fx ); // Q(limit_e+reg_ghat_e)
1486 : limit_fx = L_add( L_tmp, EPSILON_FX );
1487 : #endif /* OPT_MCH_DEC_V1_BE */
1488 90900 : limit_e = add( limit_e, reg_ghat_e );
1489 :
1490 : /* Computing G_hat */
1491 :
1492 : #ifdef OPT_MCH_DEC_V1_NBE
1493 90900 : com_e = sub( Cy_hat_diag_e, limit_e );
1494 : #endif /* OPT_MCH_DEC_V1_NBE */
1495 553344 : FOR( i = 0; i < lengthCy; ++i )
1496 : {
1497 462444 : Cy_hat_diag_fx_e[i] = Cy_hat_diag_e;
1498 462444 : move16();
1499 : #ifdef OPT_MCH_DEC_V1_NBE
1500 462444 : IF( GT_32( limit_fx, L_shl_sat( Cy_hat_diag_fx[i], com_e ) ) ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
1501 : #else /* OPT_MCH_DEC_V1_NBE */
1502 : IF( BASOP_Util_Cmp_Mant32Exp( limit_fx, limit_e, Cy_hat_diag_fx[i], Cy_hat_diag_e ) > 0 ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
1503 : #endif /* OPT_MCH_DEC_V1_NBE */
1504 : {
1505 10 : Cy_hat_diag_fx[i] = limit_fx;
1506 10 : move32();
1507 10 : Cy_hat_diag_fx_e[i] = limit_e;
1508 10 : move16();
1509 : }
1510 462444 : tmp = BASOP_Util_Divide3232_Scale( Cy_fx[i + i * lengthCy], Cy_hat_diag_fx[i], &scale );
1511 462444 : scale = add( scale, sub( Cy_fx_e, Cy_hat_diag_fx_e[i] ) );
1512 462444 : L_tmp = Sqrt32( L_deposit_h( tmp ), &scale );
1513 :
1514 462444 : G_hat_fx[i] = L_tmp;
1515 462444 : move32();
1516 462444 : G_hat_e[i] = scale;
1517 462444 : move16();
1518 : }
1519 :
1520 : /*-----------------------------------------------------------------*
1521 : * Formulate optimal P
1522 : *-----------------------------------------------------------------*/
1523 :
1524 553344 : FOR( i = 0; i < num_outputs; i++ )
1525 : {
1526 : #ifdef OPT_MCH_DEC_V1_BE
1527 462444 : Kx_fx[i] = Mpy_32_32( Kx_fx[i], G_hat_fx[i] ); // Q(31-(Kx_fx_e+G_hag_e))
1528 : #else /* OPT_MCH_DEC_V1_BE */
1529 : L_tmp = Mpy_32_32( Kx_fx[i], G_hat_fx[i] ); // Q(31-(Kx_fx_e+G_hag_e))
1530 : Kx_fx[i] = L_tmp;
1531 : #endif /* OPT_MCH_DEC_V1_BE */
1532 462444 : move32();
1533 462444 : Kx_fx_e[i] = add( Kx_fx_e[i], G_hat_e[i] );
1534 462444 : move16();
1535 : }
1536 :
1537 553344 : FOR( i = 0; i < num_outputs; i++ )
1538 : {
1539 : Word32 fac_fx;
1540 462444 : fac_fx = Kx_fx[i];
1541 462444 : move32();
1542 :
1543 2841348 : FOR( j = 0; j < num_outputs; j++ )
1544 : {
1545 : #ifdef OPT_MCH_DEC_V1_BE
1546 2378904 : mat_mult_buffer1_fx[i + j * num_outputs] = Mpy_32_32( Ky_fx[i + j * num_outputs], fac_fx ); // Q(31-(Ky_fx_e+Kx_fx_e));
1547 2378904 : move32();
1548 2378904 : mat_mult_buffer1_buff_e[i + j * num_outputs] = add( Ky_fx_e[i + j * num_outputs], Kx_fx_e[i] );
1549 2378904 : move16();
1550 : #else /* OPT_MCH_DEC_V1_BE */
1551 : L_tmp = Mpy_32_32( Ky_fx[i + j * num_outputs], fac_fx ); // Q(31-(Ky_fx_e+Kx_fx_e))
1552 : mat_mult_buffer1_fx[i + j * num_outputs] = L_tmp;
1553 : move32();
1554 : mat_mult_buffer1_buff_e[i + j * num_outputs] = extract_l( L_add( Ky_fx_e[i + j * num_outputs], Kx_fx_e[i] ) );
1555 : move16();
1556 : #endif /* OPT_MCH_DEC_V1_BE */
1557 : }
1558 : }
1559 :
1560 90900 : mat_mult_buffer1_e = mat_mult_buffer1_buff_e[0];
1561 90900 : move16();
1562 2378904 : FOR( i = 1; i < num_outputs * num_outputs; i++ )
1563 : {
1564 2288004 : if ( LT_16( mat_mult_buffer1_e, mat_mult_buffer1_buff_e[i] ) )
1565 : {
1566 24811 : mat_mult_buffer1_e = mat_mult_buffer1_buff_e[i];
1567 24811 : move16();
1568 : }
1569 : }
1570 :
1571 2469804 : FOR( i = 0; i < num_outputs * num_outputs; i++ )
1572 : {
1573 2378904 : mat_mult_buffer1_fx[i] = L_shr( mat_mult_buffer1_fx[i], sub( mat_mult_buffer1_e, mat_mult_buffer1_buff_e[i] ) ); // Q(31-mat_mult_buffer1_e)
1574 2378904 : move32();
1575 : }
1576 :
1577 90900 : mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, lengthCy, 0 );
1578 :
1579 90900 : svd_fx( svd_in_buffer_fx, mat_mult_buffer1_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, lengthCx, lengthCy );
1580 :
1581 : /* Actually Processing P */
1582 :
1583 90900 : svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, lengthCy, lengthCx );
1584 90900 : svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx );
1585 90900 : mat_mult_buffer1_e = 0;
1586 90900 : move16();
1587 90900 : mat_mult_buffer2_e = 0;
1588 90900 : move16();
1589 :
1590 90900 : matrix_product_mant_exp_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, lengthCy, lengthCx, 0,
1591 : mat_mult_buffer2_fx, mat_mult_buffer2_e, lengthCx, lengthCx, 1,
1592 : mat_mult_buffer3_fx, &mat_mult_buffer3_e );
1593 :
1594 : /*-----------------------------------------------------------------*
1595 : * Formulate M
1596 : *-----------------------------------------------------------------*/
1597 :
1598 :
1599 90900 : matrix_product_mant_exp_fx( Ky_fx, Ky_fx_e[0], lengthCy, lengthCy, 0, mat_mult_buffer3_fx, mat_mult_buffer3_e, lengthCy, lengthCx, 0, mat_mult_buffer1_fx, mat_mult_buffer1_buff_e );
1600 90900 : set16_fx( mat_mult_buffer1_buff_e, mat_mult_buffer1_buff_e[0], MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS );
1601 :
1602 : Word16 mixing_matrix_fx_e[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
1603 :
1604 553344 : FOR( i = 0; i < num_outputs; i++ )
1605 : {
1606 : Word32 fac_fx;
1607 462444 : fac_fx = Kx_reg_inv_fx[i];
1608 462444 : move32();
1609 :
1610 2841348 : FOR( j = 0; j < num_outputs; j++ )
1611 : {
1612 : #ifdef OPT_MCH_DEC_V1_BE
1613 2378904 : mixing_matrix_fx[j + i * num_outputs] = Mpy_32_32( mat_mult_buffer1_fx[j + i * num_outputs], fac_fx ); // Q(31-mat_mult_buffer1_e+Kx_reg_inv_e);
1614 2378904 : move32();
1615 : #else /* OPT_MCH_DEC_V1_BE */
1616 : L_tmp = Mpy_32_32( mat_mult_buffer1_fx[j + i * num_outputs], fac_fx ); // Q(31-mat_mult_buffer1_e+Kx_reg_inv_e)
1617 : mixing_matrix_fx[j + i * num_outputs] = L_tmp;
1618 : move32();
1619 : #endif /* OPT_MCH_DEC_V1_BE */
1620 2378904 : mixing_matrix_fx_e[j + i * num_outputs] = add( mat_mult_buffer1_buff_e[j + i * num_outputs], Kx_reg_inv_e[i] );
1621 2378904 : move16();
1622 : }
1623 : }
1624 :
1625 : /*-----------------------------------------------------------------*
1626 : * Formulate Cr
1627 : *-----------------------------------------------------------------*/
1628 :
1629 : /* Compute Cy_tilde = M*Cx*M' */
1630 :
1631 : Word16 Cx_e_arr[MAX_CICP_CHANNELS];
1632 90900 : set16_fx( Cx_e_arr, Cx_e, MAX_CICP_CHANNELS );
1633 :
1634 90900 : matrix_diag_product_fx_1( mixing_matrix_fx, mixing_matrix_fx_e, lengthCy, lengthCx, 0, Cx_fx, Cx_e_arr, lengthCx, mat_mult_buffer1_fx, mat_mult_buffer1_buff_e );
1635 :
1636 90900 : exp = mixing_matrix_fx_e[0];
1637 90900 : move16();
1638 2378904 : FOR( i = 1; i < num_outputs * num_outputs; i++ )
1639 : {
1640 2288004 : if ( LT_16( exp, mixing_matrix_fx_e[i] ) )
1641 : {
1642 9746 : exp = mixing_matrix_fx_e[i];
1643 9746 : move16();
1644 : }
1645 : }
1646 :
1647 2469804 : FOR( i = 0; i < num_outputs * num_outputs; i++ )
1648 : {
1649 2378904 : mixing_matrix_fx[i] = L_shr( mixing_matrix_fx[i], sub( exp, mixing_matrix_fx_e[i] ) ); // Q(31-exp)
1650 2378904 : move32();
1651 : }
1652 90900 : mixing_matrix_e = exp;
1653 90900 : move16();
1654 :
1655 90900 : exp = mat_mult_buffer1_buff_e[0];
1656 90900 : move16();
1657 2378904 : FOR( i = 1; i < num_outputs * num_outputs; i++ )
1658 : {
1659 2288004 : if ( LT_16( exp, mat_mult_buffer1_buff_e[i] ) )
1660 : {
1661 9746 : exp = mat_mult_buffer1_buff_e[i];
1662 9746 : move16();
1663 : }
1664 : }
1665 :
1666 2469804 : FOR( i = 0; i < num_outputs * num_outputs; i++ )
1667 : {
1668 2378904 : mat_mult_buffer1_fx[i] = L_shr( mat_mult_buffer1_fx[i], sub( exp, mat_mult_buffer1_buff_e[i] ) ); // Q(31-exp)
1669 2378904 : move32();
1670 : }
1671 90900 : mat_mult_buffer1_e = exp;
1672 90900 : move16();
1673 :
1674 90900 : matrix_product_diag_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, lengthCy, lengthCx, 0, mixing_matrix_fx, mixing_matrix_e, lengthCy, lengthCx, 1, Cy_tilde_fx, &Cy_tilde_e );
1675 :
1676 : /*-----------------------------------------------------------------*
1677 : * Energy Compensation
1678 : *-----------------------------------------------------------------*/
1679 :
1680 90900 : adj_fx_p = svd_s_buffer_fx;
1681 :
1682 553344 : FOR( i = 0; i < lengthCy; ++i )
1683 : {
1684 462444 : tmp = BASOP_Util_Divide3232_Scale( Cy_fx[i + ( lengthCy * i )], L_add( Cy_tilde_fx[i], EPSILON_FX ), &scale );
1685 462444 : scale = add( scale, sub( Cy_fx_e, Cy_tilde_e ) );
1686 462444 : adj_fx_p[i] = Sqrt32( L_deposit_h( tmp ), &scale );
1687 462444 : move32();
1688 462444 : adj_buff_e[i] = scale;
1689 462444 : move16();
1690 462444 : Word32 temp = W_shl_sat_l( W_deposit32_l( 4 ), sub( 31, scale ) );
1691 462444 : IF( GT_32( adj_fx_p[i], temp ) ) // 1073741824 -> 1.0f in Q30
1692 : {
1693 1 : adj_fx_p[i] = 1073741824; // 1.0f in Q30
1694 1 : move32();
1695 1 : adj_buff_e[i] = 3;
1696 1 : move16();
1697 : }
1698 : }
1699 :
1700 90900 : adj_e = adj_buff_e[0];
1701 90900 : move16();
1702 :
1703 462444 : FOR( i = 1; i < lengthCy; i++ )
1704 : {
1705 371544 : if ( LT_16( adj_e, adj_buff_e[i] ) )
1706 : {
1707 36682 : adj_e = adj_buff_e[i];
1708 36682 : move16();
1709 : }
1710 : }
1711 :
1712 :
1713 553344 : FOR( i = 0; i < lengthCy; i++ )
1714 : {
1715 462444 : adj_fx[i] = L_shr( adj_fx_p[i], sub( adj_e, adj_buff_e[i] ) ); // Q(31-adj_e)
1716 462444 : move32();
1717 : }
1718 :
1719 90900 : diag_matrix_product_fx( adj_fx, adj_e, lengthCy, mixing_matrix_fx, mixing_matrix_e, lengthCy, lengthCx, 0, mat_mult_buffer3_fx, &mat_mult_buffer3_e );
1720 90900 : Copy32( mat_mult_buffer3_fx, mixing_matrix_fx, imult1616( lengthCy, lengthCx ) );
1721 90900 : *mixing_matrix_ret_e = mat_mult_buffer3_e;
1722 90900 : move16();
1723 :
1724 90900 : pop_wmops();
1725 :
1726 90900 : return out;
1727 : }
1728 :
1729 :
1730 : /*-------------------------------------------------------------------*
1731 : * computeMixingMatricesISM()
1732 : *
1733 : *
1734 : *-------------------------------------------------------------------*/
1735 315180 : Word16 computeMixingMatricesISM_fx(
1736 : const Word16 num_inputs,
1737 : const Word16 num_responses,
1738 : const Word16 num_outputs,
1739 : const Word32 *responses_fx, /*Q(31-responses_e) */
1740 : const Word16 responses_e,
1741 : const Word32 *ener_fx, /*Q(31-ener_e) */
1742 : const Word16 ener_e,
1743 : const Word32 *Cx_diag_fx, /*Q(31-diag_e) */
1744 : const Word16 Cx_diag_e,
1745 : const Word32 *Cy_diag_fx, /*Q(31-diag_e) */
1746 : const Word16 Cy_diag_e,
1747 : const Word16 *Q_16fx, // Q15
1748 : const Word16 energy_compensation_flag,
1749 : const Word32 reg_Sx_fx, /*Q0*/
1750 : const Word32 reg_ghat_fx, /*Q0*/
1751 : Word32 *mixing_matrix_fx, /*Q(31-mixing_matrix_e) */
1752 : Word16 *mixing_matrix_e )
1753 : {
1754 : Word16 i, out;
1755 : Word16 lengthCx, lengthCy;
1756 : Word16 nL, nC;
1757 :
1758 : Word32 *Cy_tilde_p_fx;
1759 : Word32 *adj_fx;
1760 : Word32 limit_fx;
1761 :
1762 : Word32 Ky_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1763 : Word32 Q_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1764 : Word32 Q_Cx_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1765 : Word32 mat_mult_buffer1_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1766 : Word32 G_hat_fx[MAX_OUTPUT_CHANNELS];
1767 : Word32 mat_mult_buffer2_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1768 : Word32 Kx_reg_inv_fx[MAX_TRANSPORT_CHANNELS];
1769 : Word32 mat_mult_buffer3_fx[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
1770 : Word32 Kx_fx[MAX_TRANSPORT_CHANNELS];
1771 : Word16 Ky_e, Q_e, Q_Cx_e, mat_mult_buffer1_e, G_hat_e, mat_mult_buffer2_e, Kx_reg_inv_e, adj_e, mat_mult_buffer3_e, Kx_e;
1772 :
1773 : Word32 svd_in_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
1774 : Word32 svd_u_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
1775 : Word32 svd_s_buffer_fx[MAX_OUTPUT_CHANNELS];
1776 : Word16 svd_s_buffer_fx_e;
1777 : Word16 svd_s_buffer_e[MAX_OUTPUT_CHANNELS];
1778 : Word32 svd_v_buffer_fx[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
1779 :
1780 : Word16 temp_e[MAX_OUTPUT_CHANNELS];
1781 315180 : push_wmops( "dirac_cov_mix_mat" );
1782 :
1783 315180 : out = EXIT_SUCCESS;
1784 315180 : move16();
1785 315180 : lengthCx = num_inputs;
1786 315180 : move16();
1787 315180 : lengthCy = num_outputs;
1788 315180 : move16();
1789 :
1790 6073020 : FOR( i = 0; i < lengthCy * lengthCx; i++ )
1791 : {
1792 5757840 : IF( EQ_16( Q_16fx[i], MAX_16 ) )
1793 : {
1794 2575200 : Q_fx[i] = MAX_32;
1795 2575200 : move32();
1796 : }
1797 : ELSE
1798 : {
1799 3182640 : Q_fx[i] = L_deposit_h( Q_16fx[i] );
1800 3182640 : move32();
1801 : }
1802 : }
1803 315180 : Q_e = 0;
1804 315180 : move16();
1805 315180 : set32_fx( svd_s_buffer_fx, 0, MAX_OUTPUT_CHANNELS );
1806 5358060 : FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
1807 : {
1808 5042880 : set32_fx( svd_in_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
1809 5042880 : set32_fx( svd_u_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
1810 5042880 : set32_fx( svd_v_buffer_fx[i], 0, MAX_OUTPUT_CHANNELS );
1811 : }
1812 :
1813 : /* Decomposition of Cy = Ky*Ky' */
1814 : /* Ky = responses*diag(ener) */
1815 315180 : matrix_diag_product_fx( responses_fx, responses_e, lengthCy, num_responses, 0, ener_fx, ener_e, num_responses, Ky_fx, &Ky_e );
1816 :
1817 : /* Decomposition of Cx -> Computing Kx */
1818 315180 : set16_fx( temp_e, Cx_diag_e, lengthCx );
1819 315180 : v_sqrt_fx( Cx_diag_fx, temp_e, Kx_fx, lengthCx );
1820 315180 : Kx_e = temp_e[0];
1821 315180 : move16();
1822 630360 : FOR( i = 1; i < lengthCx; i++ )
1823 : {
1824 315180 : Kx_e = s_max( Kx_e, temp_e[i] );
1825 : }
1826 945540 : FOR( i = 0; i < lengthCx; i++ )
1827 : {
1828 630360 : Kx_fx[i] = L_shr_r( Kx_fx[i], sub( Kx_e, temp_e[i] ) ); // Q(31-Kx_e)
1829 630360 : move32();
1830 : }
1831 :
1832 : /* Regularization of Sx */
1833 315180 : maximum_32_fx( Kx_fx, lengthCx, &limit_fx );
1834 315180 : limit_fx = Mpy_32_32( limit_fx, reg_Sx_fx ); // Cy_hat_diag_e + reg_ghat_e
1835 :
1836 945540 : FOR( i = 0; i < lengthCx; ++i )
1837 : {
1838 630360 : IF( GT_32( Kx_fx[i], limit_fx ) )
1839 : {
1840 595915 : svd_s_buffer_fx[i] = Kx_fx[i];
1841 595915 : move32();
1842 : }
1843 : ELSE
1844 : {
1845 34445 : svd_s_buffer_fx[i] = limit_fx;
1846 34445 : move32();
1847 : }
1848 : }
1849 315180 : svd_s_buffer_fx_e = Kx_e;
1850 315180 : move16();
1851 :
1852 315180 : limit_fx = 0;
1853 315180 : move32();
1854 :
1855 : /* regularized Kx-1 */
1856 :
1857 945540 : FOR( i = 0; i < lengthCx; ++i )
1858 : {
1859 630360 : IF( svd_s_buffer_fx[i] )
1860 : {
1861 : Word32 reg_fac;
1862 630358 : reg_fac = BASOP_Util_Divide3232_Scale_newton( MAX_32, svd_s_buffer_fx[i], &temp_e[i] );
1863 630358 : Kx_reg_inv_fx[i] = reg_fac;
1864 630358 : move32();
1865 630358 : temp_e[i] = sub( temp_e[i], svd_s_buffer_fx_e );
1866 630358 : move16();
1867 : }
1868 : ELSE
1869 : {
1870 : Word32 reg_fac;
1871 2 : reg_fac = BASOP_Util_Divide3232_Scale_newton( MAX_32, EPSILON_FX_M, &temp_e[i] );
1872 2 : Kx_reg_inv_fx[i] = reg_fac;
1873 2 : move32();
1874 2 : temp_e[i] = sub( temp_e[i], EPSILON_FX_E );
1875 2 : move16();
1876 : }
1877 : }
1878 315180 : Kx_reg_inv_e = temp_e[0];
1879 315180 : move16();
1880 630360 : FOR( i = 1; i < lengthCx; i++ )
1881 : {
1882 315180 : Kx_reg_inv_e = s_max( Kx_reg_inv_e, temp_e[i] );
1883 : }
1884 945540 : FOR( i = 0; i < lengthCx; i++ )
1885 : {
1886 630360 : Kx_reg_inv_fx[i] = L_shr_r( Kx_reg_inv_fx[i], sub( Kx_reg_inv_e, temp_e[i] ) ); // Q(31- Kx_reg_inv_e)
1887 630360 : move32();
1888 : }
1889 :
1890 : /************************ normalization matrix G hat **********************/
1891 :
1892 : /* Computing Q*Cx*Q' */
1893 : Word32 Cy_hat_diag_fx[MAX_OUTPUT_CHANNELS];
1894 : Word16 Cy_hat_diag_e;
1895 :
1896 315180 : matrix_diag_product_fx( Q_fx, Q_e, lengthCy, lengthCx, 0, Cx_diag_fx, Cx_diag_e, lengthCx, Q_Cx_fx, &Q_Cx_e );
1897 :
1898 315180 : Word16 guard_bits = find_guarded_bits_fx( lengthCx + 1 );
1899 :
1900 6073020 : FOR( i = 0; i < lengthCy * lengthCx; ++i )
1901 : {
1902 5757840 : IF( GT_16( Q_Cx_e, Q_e ) )
1903 : {
1904 5757826 : Q_fx[i] = L_shr( Q_fx[i], guard_bits );
1905 5757826 : move32();
1906 : }
1907 : ELSE
1908 : {
1909 14 : Q_Cx_fx[i] = L_shr( Q_Cx_fx[i], guard_bits );
1910 14 : move32();
1911 : }
1912 : }
1913 :
1914 315180 : IF( GT_16( Q_Cx_e, Q_e ) )
1915 : {
1916 315179 : Q_e = add( Q_e, guard_bits );
1917 : }
1918 : ELSE
1919 : {
1920 1 : Q_Cx_e = add( Q_Cx_e, guard_bits );
1921 : }
1922 315180 : matrix_product_diag_fx( Q_Cx_fx, Q_Cx_e, lengthCy, lengthCx, 0, Q_fx, Q_e, lengthCy, lengthCx, 1, Cy_hat_diag_fx, &Cy_hat_diag_e );
1923 :
1924 : /* Computing Cy_hat_diag */
1925 3194100 : FOR( i = 0; i < lengthCy; ++i )
1926 : {
1927 2878920 : if ( GT_32( Cy_hat_diag_fx[i], limit_fx ) )
1928 : {
1929 469328 : limit_fx = Cy_hat_diag_fx[i];
1930 469328 : move32();
1931 : }
1932 : }
1933 :
1934 315180 : limit_fx = Mpy_32_32( limit_fx, reg_ghat_fx ); // Cy_hat_diag_e + reg_ghat_e
1935 :
1936 : /* Computing G_hat */
1937 3194100 : FOR( i = 0; i < lengthCy; ++i )
1938 : {
1939 2878920 : if ( GT_32( limit_fx, Cy_hat_diag_fx[i] ) ) /* Computing Cy_hat_diag = max(Cy_hat_diag,limit) */
1940 : {
1941 11610 : Cy_hat_diag_fx[i] = limit_fx;
1942 11610 : move32();
1943 : }
1944 2878920 : IF( Cy_diag_fx[i] )
1945 : {
1946 1875175 : IF( Cy_hat_diag_fx[i] )
1947 : {
1948 1875175 : G_hat_fx[i] = BASOP_Util_Divide3232_Scale_newton( Cy_diag_fx[i], Cy_hat_diag_fx[i], &temp_e[i] );
1949 1875175 : move32();
1950 1875175 : temp_e[i] = add( temp_e[i], sub( Cy_diag_e, Cy_hat_diag_e ) );
1951 1875175 : move16();
1952 1875175 : G_hat_fx[i] = Sqrt32( G_hat_fx[i], &temp_e[i] );
1953 1875175 : move32();
1954 : }
1955 : ELSE
1956 : {
1957 0 : G_hat_fx[i] = BASOP_Util_Divide3232_Scale_newton( Cy_diag_fx[i], EPSILON_FX_M, &temp_e[i] );
1958 0 : move32();
1959 0 : temp_e[i] = add( temp_e[i], sub( Cy_diag_e, EPSILON_FX_E ) );
1960 0 : move16();
1961 0 : G_hat_fx[i] = Sqrt32( G_hat_fx[i], &temp_e[i] );
1962 0 : move32();
1963 : }
1964 : }
1965 : ELSE
1966 : {
1967 1003745 : G_hat_fx[i] = 0;
1968 1003745 : move32();
1969 1003745 : temp_e[i] = 0;
1970 1003745 : move16();
1971 : }
1972 : }
1973 315180 : G_hat_e = temp_e[0];
1974 315180 : move16();
1975 2878920 : FOR( i = 1; i < lengthCy; i++ )
1976 : {
1977 2563740 : G_hat_e = s_max( G_hat_e, temp_e[i] );
1978 : }
1979 3194100 : FOR( i = 0; i < lengthCy; i++ )
1980 : {
1981 2878920 : G_hat_fx[i] = L_shr_r( G_hat_fx[i], sub( G_hat_e, temp_e[i] ) ); // Q(31-G_hat_e)
1982 2878920 : move32();
1983 : }
1984 :
1985 : /************************ Formulate optimal P **********************/
1986 :
1987 : /* Computing the input matrix Kx'*Q'*G_hat'*Ky */
1988 315180 : diag_matrix_product_fx( Kx_fx, Kx_e, lengthCx, Q_fx, Q_e, lengthCy, lengthCx, 1, mat_mult_buffer1_fx, &mat_mult_buffer1_e );
1989 :
1990 315180 : matrix_diag_product_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, lengthCx, lengthCy, 0, G_hat_fx, G_hat_e, lengthCy, mat_mult_buffer2_fx, &mat_mult_buffer2_e );
1991 :
1992 315180 : matrix_product_mant_exp_fx( mat_mult_buffer2_fx, mat_mult_buffer2_e, lengthCx, lengthCy, 0, Ky_fx, Ky_e, lengthCy, num_responses, 0, mat_mult_buffer1_fx, &mat_mult_buffer1_e );
1993 :
1994 315180 : IF( LT_16( lengthCx, num_responses ) )
1995 : {
1996 3600 : mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 1 );
1997 :
1998 3600 : nL = num_responses;
1999 3600 : move16();
2000 3600 : nC = lengthCx;
2001 3600 : move16();
2002 3600 : svd_fx( svd_in_buffer_fx, mat_mult_buffer1_e, svd_v_buffer_fx, svd_s_buffer_fx, svd_u_buffer_fx, svd_s_buffer_e, nL, nC );
2003 : }
2004 : ELSE
2005 : {
2006 311580 : mat2svdMat_fx( mat_mult_buffer1_fx, svd_in_buffer_fx, lengthCx, num_responses, 0 );
2007 :
2008 311580 : nL = lengthCx;
2009 311580 : move16();
2010 311580 : nC = num_responses;
2011 311580 : move16();
2012 311580 : svd_fx( svd_in_buffer_fx, mat_mult_buffer1_e, svd_u_buffer_fx, svd_s_buffer_fx, svd_v_buffer_fx, svd_s_buffer_e, nL, nC );
2013 : }
2014 :
2015 : /* Actually Processing P */
2016 :
2017 : /* can be skipped: lambda is always column-truncated identity matrix, so this operation just truncates V to num_input_channel columns */
2018 315180 : svdMat2mat_fx( svd_v_buffer_fx, mat_mult_buffer1_fx, num_responses, lengthCx );
2019 315180 : mat_mult_buffer1_e = 0;
2020 315180 : move16();
2021 315180 : svdMat2mat_fx( svd_u_buffer_fx, mat_mult_buffer2_fx, lengthCx, lengthCx );
2022 315180 : mat_mult_buffer2_e = 0;
2023 315180 : move16();
2024 :
2025 315180 : matrix_product_mant_exp_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, num_responses, lengthCx, 0, mat_mult_buffer2_fx, mat_mult_buffer2_e, lengthCx, lengthCx, 1, mat_mult_buffer3_fx, &mat_mult_buffer3_e );
2026 :
2027 : /************************ Formulate M **********************/
2028 :
2029 315180 : matrix_product_mant_exp_fx( Ky_fx, Ky_e, lengthCy, num_responses, 0, mat_mult_buffer3_fx, mat_mult_buffer3_e, num_responses, lengthCx, 0, mat_mult_buffer1_fx, &mat_mult_buffer1_e );
2030 :
2031 315180 : matrix_diag_product_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, lengthCy, lengthCx, 0, Kx_reg_inv_fx, Kx_reg_inv_e, lengthCx, mixing_matrix_fx, mixing_matrix_e );
2032 :
2033 : /*********************** Energy Compensation ****************/
2034 :
2035 : /* Compute Cy_tilde = M*Cx*M' */
2036 315180 : matrix_diag_product_fx( mixing_matrix_fx, *mixing_matrix_e, lengthCy, lengthCx, 0, Cx_diag_fx, Cx_diag_e, lengthCx, mat_mult_buffer1_fx, &mat_mult_buffer1_e );
2037 :
2038 315180 : matrix_product_mant_exp_fx( mat_mult_buffer1_fx, mat_mult_buffer1_e, lengthCy, lengthCx, 0, mixing_matrix_fx, *mixing_matrix_e, lengthCy, lengthCx, 1, mat_mult_buffer2_fx, &mat_mult_buffer2_e );
2039 :
2040 315180 : IF( EQ_16( energy_compensation_flag, 1 ) )
2041 : {
2042 315180 : adj_fx = svd_s_buffer_fx;
2043 315180 : Cy_tilde_p_fx = mat_mult_buffer2_fx;
2044 3194100 : FOR( i = 0; i < lengthCy; ++i )
2045 : {
2046 : /* Avoid correction for very small energies, main diagonal elements of Cy_tilde_p may be negative */
2047 2878920 : IF( Cy_tilde_p_fx[( i + ( i * lengthCy ) )] < 0 )
2048 : {
2049 0 : adj_fx[i] = MAX_32;
2050 0 : move32();
2051 0 : temp_e[i] = 0;
2052 0 : move16();
2053 : }
2054 : ELSE
2055 : {
2056 2878920 : IF( Cy_diag_fx[i] )
2057 : {
2058 1875175 : IF( Cy_tilde_p_fx[i + ( i * lengthCy )] )
2059 : {
2060 1875155 : adj_fx[i] = BASOP_Util_Divide3232_Scale_newton( Cy_diag_fx[i], Cy_tilde_p_fx[i + ( i * lengthCy )], &temp_e[i] );
2061 1875155 : move32();
2062 1875155 : temp_e[i] = add( temp_e[i], sub( Cy_diag_e, mat_mult_buffer2_e ) );
2063 1875155 : move16();
2064 1875155 : adj_fx[i] = Sqrt32( adj_fx[i], &temp_e[i] );
2065 1875155 : move32();
2066 : }
2067 : ELSE
2068 : {
2069 20 : adj_fx[i] = BASOP_Util_Divide3232_Scale_newton( Cy_diag_fx[i], EPSILON_FX_M, &temp_e[i] );
2070 20 : move32();
2071 20 : temp_e[i] = add( temp_e[i], sub( Cy_diag_e, EPSILON_FX_E ) );
2072 20 : move16();
2073 20 : adj_fx[i] = Sqrt32( adj_fx[i], &temp_e[i] );
2074 20 : move32();
2075 : }
2076 : }
2077 : ELSE
2078 : {
2079 1003745 : adj_fx[i] = 0;
2080 1003745 : move32();
2081 1003745 : temp_e[i] = 0;
2082 1003745 : move16();
2083 : }
2084 : }
2085 :
2086 2878920 : Word32 temp = W_shl_sat_l( W_deposit32_l( 4 ), sub( 31, temp_e[i] ) );
2087 2878920 : IF( GT_32( adj_fx[i], temp ) )
2088 : {
2089 1549 : adj_fx[i] = MAX_32;
2090 1549 : move32();
2091 1549 : temp_e[i] = 2;
2092 1549 : move16();
2093 : }
2094 : }
2095 315180 : adj_e = temp_e[0];
2096 315180 : move16();
2097 2878920 : FOR( i = 1; i < lengthCy; i++ )
2098 : {
2099 2563740 : adj_e = s_max( adj_e, temp_e[i] );
2100 : }
2101 3194100 : FOR( i = 0; i < lengthCy; i++ )
2102 : {
2103 2878920 : adj_fx[i] = L_shr_r( adj_fx[i], sub( adj_e, temp_e[i] ) ); // Q(31-adj_e)
2104 2878920 : move32();
2105 : }
2106 :
2107 315180 : diag_matrix_product_fx( adj_fx, adj_e, lengthCy, mixing_matrix_fx, *mixing_matrix_e, lengthCy, lengthCx, 0, mat_mult_buffer3_fx, &mat_mult_buffer3_e );
2108 :
2109 315180 : Copy32( mat_mult_buffer3_fx, mixing_matrix_fx, imult1616( lengthCy, lengthCx ) );
2110 315180 : *mixing_matrix_e = mat_mult_buffer3_e;
2111 315180 : move16();
2112 : }
2113 :
2114 315180 : pop_wmops();
2115 :
2116 315180 : return out;
2117 : }
|