LCOV - code coverage report
Current view: top level - lib_dec - ivas_dirac_output_synthesis_cov.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 322 338 95.3 %
Date: 2025-11-01 08:50:45 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.14