LCOV - code coverage report
Current view: top level - lib_rend - ivas_mcmasa_ana_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 743 807 92.1 %
Date: 2025-05-03 01:55:50 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 <math.h>
      34             : #include <stdlib.h>
      35             : #include <stdio.h>
      36             : #include "ivas_cnst.h"
      37             : #include "options.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "prot_fx.h"
      40             : #include "ivas_stat_rend.h"
      41             : #include "ivas_rom_com.h"
      42             : #include "wmc_auto.h"
      43             : #include "ivas_prot_fx.h"
      44             : #include "ivas_rom_com_fx.h"
      45             : 
      46             : /*-------------------------------------------------------------------------
      47             :  * Local constants
      48             :  *------------------------------------------------------------------------*/
      49             : 
      50             : #define NEAR_HORIZONTAL_PLANE_ELEVATION    17.5f
      51             : #define NEAR_HORIZONTAL_PLANE_ELEVATION_FX 73400320 /*Q22*/
      52             : #define VERTICAL_ENERGY_RATIO_OFFSET       0.15f
      53             : #define VERTICAL_ENERGY_RATIO_OFFSET_FX    4915 /*Q15*/
      54             : 
      55             : 
      56             : /*-------------------------------------------------------------------------
      57             :  * Local function prototypes
      58             :  *------------------------------------------------------------------------*/
      59             : 
      60             : /* Structure for covariance matrix */
      61             : typedef struct
      62             : {
      63             :     float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      64             :     float xi[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      65             :     Word32 xr_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      66             :     Word32 xi_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      67             :     Word16 xr_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xr_fx*/
      68             :     Word16 xi_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xi_fx*/
      69             : } CovarianceMatrix;
      70             : void ivas_mcmasa_param_est_ana_fx(
      71             :     MCMASA_ANA_HANDLE hMcMasa,                                                         /* i  : McMASA analyzer structure           */
      72             :     Word32 data_fx[][L_FRAME48k],                                                      /* i  : Audio frame in MC-format            */
      73             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* o  : Estimated elevation             Q22 */
      74             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* o  : Estimated azimuth               Q22 */
      75             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],          /* o  : Estimated direct-to-total ratio Q31 */
      76             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],      /* o  : Estimated spread coherence      Q31 */
      77             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o  : Estimated surround coherence    Q31 */
      78             :     Word16 q_data,
      79             :     const Word16 input_frame, /* i  : Input frame size                    */
      80             :     const Word16 nchan_inp    /* i  : Number of input channels            */
      81             : );
      82             : 
      83             : 
      84             : static void computeVerticalDiffuseness_fx(
      85             :     Word32 **buffer_intensity,   /* i  : Intensity vectors           */
      86             :     const Word32 *buffer_energy, /* i  : Energy                      */
      87             :     const Word16 num_freq_bands, /* i  : Number of frequency bands   */
      88             :     Word32 *diffuseness,         /* o  : Estimated diffuseness   Q31 */
      89             :     Word16 *buffer_intensity_q,
      90             :     Word16 *buffer_energy_q );
      91             : static void compute_cov_mtx_fx(
      92             :     Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, real, s[ch][freq]                         */
      93             :     Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, imag, s[ch][freq]                         */
      94             :     const Word16 freq,                                      /* i  : Freq to process                                         */
      95             :     const Word16 N,                                         /* i  : Number of channels                                      */
      96             :     CovarianceMatrix *COVls,                                /* o  : Output matrix, contains upper part of cov mtx           */
      97             :     Word16 inp_exp                                          /* i  : Stores exponent for sr and si                           */
      98             : );
      99             : static void computeEvenLayout_fx(
     100             :     const Word32 *ls_azimuth, /* i: Q22 */
     101             :     Word32 *ls_azimuth_even,  /* o: Q22 */
     102             :     const Word16 numChannels );
     103             : 
     104             : static void ivas_mcmasa_dmx_fx(
     105             :     MCMASA_ANA_HANDLE hMcMasa,
     106             :     Word32 data_f_fx[][L_FRAME48k],
     107             :     Word16 data_e,
     108             :     const Word16 input_frame,
     109             :     const Word16 nchan_transport,
     110             :     const Word16 nchan_inp );
     111             : 
     112             : 
     113             : /*--------------------------------------------------------------------------*
     114             :  * ivas_mcmasa_ana_open()
     115             :  *
     116             :  *
     117             :  *--------------------------------------------------------------------------*/
     118             : 
     119           1 : ivas_error ivas_mcmasa_ana_open(
     120             :     MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */
     121             :     const AUDIO_CONFIG inConfig,   /* i  :   Input config             */
     122             :     Word32 input_Fs                /* i  :   Sampling frequency       */
     123             : )
     124             : {
     125             :     Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS];
     126             :     Word32 ls_elevation_fx[MCMASA_MAX_ANA_CHANS];
     127             :     Word32 ls_azimuth_even_fx[MCMASA_MAX_ANA_CHANS];
     128             :     Word32 left_min_fx, right_min_fx, azi_diff_fx;
     129             :     Word16 i, j;
     130             :     MCMASA_ANA_HANDLE hMcMasa;
     131             :     Word16 nchan_inp;
     132             :     Word16 numAnalysisChannels;
     133             :     Word16 maxBin, input_frame;
     134             :     ivas_error error;
     135             : 
     136           1 :     error = IVAS_ERR_OK;
     137             : 
     138           1 :     IF( ( hMcMasa = (MCMASA_ANA_HANDLE) malloc( sizeof( MCMASA_ANA_DATA ) ) ) == NULL )
     139             :     {
     140           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     141             :     }
     142             : 
     143           1 :     IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1 ) )
     144             :     {
     145           0 :         nchan_inp = 6;
     146           0 :         move16();
     147           0 :         Copy32( ls_azimuth_CICP6_fx, ls_azimuth_fx, 5 );     /* nchan_inp - 1 */
     148           0 :         Copy32( ls_elevation_CICP6_fx, ls_elevation_fx, 5 ); /* nchan_inp - 1 */
     149           0 :         hMcMasa->numHorizontalChannels = 5;
     150           0 :         move16();
     151           0 :         hMcMasa->isHorizontalSetup = 1;
     152           0 :         move16();
     153             :     }
     154           1 :     ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
     155             :     {
     156           0 :         nchan_inp = 8;
     157           0 :         move16();
     158           0 :         Copy32( ls_azimuth_CICP12_fx, ls_azimuth_fx, 7 );     /* nchan_inp - 1 */
     159           0 :         Copy32( ls_elevation_CICP12_fx, ls_elevation_fx, 7 ); /* nchan_inp - 1 */
     160           0 :         hMcMasa->numHorizontalChannels = 7;
     161           0 :         move16();
     162           0 :         hMcMasa->isHorizontalSetup = 1;
     163           0 :         move16();
     164             :     }
     165           1 :     ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1_2 ) )
     166             :     {
     167           0 :         nchan_inp = 8;
     168           0 :         move16();
     169           0 :         Copy32( ls_azimuth_CICP14_fx, ls_azimuth_fx, 7 );     /* nchan_inp - 1 */
     170           0 :         Copy32( ls_elevation_CICP14_fx, ls_elevation_fx, 7 ); /* nchan_inp - 1 */
     171           0 :         hMcMasa->numHorizontalChannels = 5;
     172           0 :         move16();
     173           0 :         hMcMasa->isHorizontalSetup = 0;
     174           0 :         move16();
     175             :     }
     176           1 :     ELSE IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1_4 ) )
     177             :     {
     178           0 :         nchan_inp = 10;
     179           0 :         Copy32( ls_azimuth_CICP16_fx, ls_azimuth_fx, 9 );     /* nchan_inp - 1 */
     180           0 :         Copy32( ls_elevation_CICP16_fx, ls_elevation_fx, 9 ); /* nchan_inp - 1 */
     181           0 :         hMcMasa->numHorizontalChannels = 5;
     182           0 :         move16();
     183           0 :         hMcMasa->isHorizontalSetup = 0;
     184           0 :         move16();
     185             :     }
     186             :     ELSE
     187             :     {
     188           1 :         nchan_inp = 12;
     189           1 :         move16();
     190           1 :         Copy32( ls_azimuth_CICP19_fx, ls_azimuth_fx, 11 );     /* nchan_inp - 1 */
     191           1 :         Copy32( ls_elevation_CICP19_fx, ls_elevation_fx, 11 ); /* nchan_inp - 1 */
     192           1 :         hMcMasa->numHorizontalChannels = 7;
     193           1 :         move16();
     194           1 :         hMcMasa->isHorizontalSetup = 0;
     195           1 :         move16();
     196             :     }
     197             : 
     198           1 :     numAnalysisChannels = sub( nchan_inp, 1 );
     199             : 
     200             :     /* Determine the number of bands */
     201           1 :     hMcMasa->nbands = MASA_FREQUENCY_BANDS;
     202           1 :     move16();
     203             :     /* Determine band grouping */
     204           1 :     Copy( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
     205             : 
     206           1 :     maxBin = extract_l( W_extract_h( W_add( W_mult_32_32( input_Fs, INV_CLDFB_BANDWIDTH_Q31 ), ONE_IN_Q31 /*0.5f in Q32*/ ) ) ); // Q0
     207          24 :     FOR( i = 1; i < add( hMcMasa->nbands, 1 ); i++ )
     208             :     {
     209          24 :         IF( GE_16( hMcMasa->band_grouping[i], maxBin ) )
     210             :         {
     211           1 :             hMcMasa->band_grouping[i] = maxBin;
     212           1 :             move16();
     213           1 :             hMcMasa->nbands = i;
     214           1 :             move16();
     215           1 :             break;
     216             :         }
     217             :     }
     218             : 
     219             :     /* Determine block grouping */
     220           1 :     Copy( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     221             : 
     222             :     /* open/initialize CLDFB */
     223           1 :     hMcMasa->num_Cldfb_instances = numAnalysisChannels;
     224           1 :     move16();
     225          12 :     FOR( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
     226             :     {
     227          11 :         IF( NE_32( ( error = openCldfb_ivas_fx( &( hMcMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
     228             :         {
     229           0 :             return error;
     230             :         }
     231             :     }
     232             : 
     233             :     /* intensity 3-dim */
     234           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     235             :     {
     236           3 :         IF( ( hMcMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL )
     237             :         {
     238           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     239             :         }
     240             : 
     241          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     242             :         {
     243          12 :             IF( ( hMcMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
     244             :             {
     245           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     246             :             }
     247          12 :             set_zero_fx( hMcMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS );
     248             :         }
     249           3 :         IF( ( hMcMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL )
     250             :         {
     251           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     252             :         }
     253             : 
     254          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     255             :         {
     256          12 :             IF( ( hMcMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL )
     257             :             {
     258           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     259             :             }
     260          12 :             set16_fx( hMcMasa->direction_vector_e[i][j], 0, MASA_FREQUENCY_BANDS );
     261             :         }
     262             :     }
     263           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     264             :     {
     265          99 :         FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     266             :         {
     267          96 :             IF( ( hMcMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
     268             :             {
     269           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     270             :             }
     271          96 :             set_zero_fx( hMcMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS );
     272             :         }
     273             :     }
     274           1 :     set16_fx( hMcMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF );
     275             : 
     276          33 :     FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     277             :     {
     278          32 :         IF( ( hMcMasa->buffer_intensity_real_vert_fx[j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
     279             :         {
     280           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     281             :         }
     282          32 :         set_zero_fx( hMcMasa->buffer_intensity_real_vert_fx[j], MASA_FREQUENCY_BANDS );
     283             :     }
     284             : 
     285           1 :     set16_fx( hMcMasa->buffer_intensity_real_vert_q, 31, DIRAC_NO_COL_AVG_DIFF );
     286           1 :     set_zero_fx( hMcMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
     287           1 :     set16_fx( hMcMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF );
     288             : 
     289           1 :     computeEvenLayout_fx( ls_azimuth_fx, ls_azimuth_even_fx, hMcMasa->numHorizontalChannels );
     290             : 
     291           1 :     IF( !hMcMasa->isHorizontalSetup )
     292             :     {
     293           1 :         computeEvenLayout_fx( &ls_azimuth_fx[hMcMasa->numHorizontalChannels], &ls_azimuth_even_fx[hMcMasa->numHorizontalChannels], sub( numAnalysisChannels, hMcMasa->numHorizontalChannels ) );
     294             :     }
     295             : 
     296          12 :     FOR( i = 0; i < numAnalysisChannels; i++ )
     297             :     {
     298          11 :         hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; // Q31
     299          11 :         move32();
     300          11 :         hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31
     301          11 :         move32();
     302          11 :         hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
     303          11 :         move32();
     304          11 :         hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31
     305          11 :         move32();
     306             : 
     307          11 :         hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; // Q31
     308          11 :         move32();
     309          11 :         hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
     310          11 :         move32();
     311          11 :         hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; // Q31
     312          11 :         move32();
     313          11 :         hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31
     314          11 :         move32();
     315             :     }
     316             : 
     317           1 :     Copy32( ls_azimuth_fx, hMcMasa->ls_azimuth_fx, numAnalysisChannels );
     318             : 
     319           8 :     FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     320             :     {
     321           7 :         left_min_fx = 360 << 22; // Q22
     322           7 :         move32();
     323           7 :         right_min_fx = -( 360 << 22 ); // Q22
     324           7 :         move32();
     325             : 
     326          56 :         FOR( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
     327             :         {
     328          49 :             azi_diff_fx = L_sub( ls_azimuth_fx[j], ls_azimuth_fx[i] ); // Q22
     329             : 
     330          49 :             IF( GT_32( azi_diff_fx, ( 180 << 22 ) ) )
     331             :             {
     332           3 :                 azi_diff_fx = L_sub( azi_diff_fx, 360 << 22 ); // Q22
     333             :             }
     334          46 :             ELSE IF( LT_32( azi_diff_fx, -( 180 << 22 ) ) )
     335             :             {
     336           3 :                 azi_diff_fx = L_add( azi_diff_fx, 360 << 22 ); // Q22
     337             :             }
     338          49 :             test();
     339          49 :             IF( LT_32( azi_diff_fx, left_min_fx ) && GT_32( azi_diff_fx, 0 ) )
     340             :             {
     341          12 :                 hMcMasa->leftNearest[i] = j;
     342          12 :                 move16();
     343          12 :                 left_min_fx = azi_diff_fx; // Q22
     344          12 :                 move32();
     345             :             }
     346          49 :             test();
     347          49 :             IF( GT_32( azi_diff_fx, right_min_fx ) && LT_32( azi_diff_fx, 0 ) )
     348             :             {
     349          11 :                 hMcMasa->rightNearest[i] = j;
     350          11 :                 move16();
     351          11 :                 right_min_fx = azi_diff_fx; // Q22
     352          11 :                 move32();
     353             :             }
     354             :         }
     355             :     }
     356             : 
     357           1 :     hMcMasa->prevMultiChEne_fx = 0;
     358           1 :     move32();
     359           1 :     hMcMasa->prevDownmixEne_fx = 0;
     360           1 :     move32();
     361           1 :     hMcMasa->prevMultiChEne_e = 0;
     362           1 :     move16();
     363           1 :     hMcMasa->prevDownmixEne_e = 0;
     364           1 :     move16();
     365           1 :     hMcMasa->prevEQ_e = 1;
     366           1 :     move16();
     367           1 :     hMcMasa->prevEQ_fx = 1073741824;
     368           1 :     move32();
     369           1 :     input_frame = (Word16) Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 );
     370           1 :     move16();
     371         961 :     FOR( i = 0; i < input_frame; i++ )
     372             :     {
     373         960 :         hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); // Q15
     374         960 :         move16();
     375             :     }
     376             : 
     377           1 :     hMcMasa->index_buffer_intensity = 0;
     378           1 :     move16();
     379             : 
     380           1 :     IF( ( hMcMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
     381             :     {
     382           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     383             :     }
     384             : 
     385           1 :     IF( ( hMcMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
     386             :     {
     387           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     388             :     }
     389           1 :     generate_gridEq_fx( hMcMasa->sph_grid16 );
     390             : 
     391           1 :     ( *hMcMasaPtr ) = hMcMasa;
     392             : 
     393           1 :     return error;
     394             : }
     395             : 
     396             : 
     397             : /*--------------------------------------------------------------------------*
     398             :  * ivas_mcmasa_ana_close()
     399             :  *
     400             :  *
     401             :  *--------------------------------------------------------------------------*/
     402             : 
     403         658 : void ivas_mcmasa_ana_close(
     404             :     MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle   */
     405             : )
     406             : {
     407             :     Word16 i, j;
     408             : 
     409         658 :     test();
     410         658 :     IF( hMcMasa == NULL || *hMcMasa == NULL )
     411             :     {
     412         657 :         return;
     413             :     }
     414             : 
     415          12 :     FOR( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
     416             :     {
     417          11 :         deleteCldfb_ivas_fx( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
     418             :     }
     419             : 
     420             :     /* intensity 3-dim */
     421           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     422             :     {
     423          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     424             :         {
     425          12 :             free( ( *hMcMasa )->direction_vector_m_fx[i][j] );
     426          12 :             ( *hMcMasa )->direction_vector_m_fx[i][j] = NULL;
     427             :         }
     428             : 
     429          99 :         FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     430             :         {
     431          96 :             free( ( *hMcMasa )->buffer_intensity_real_fx[i][j] );
     432          96 :             ( *hMcMasa )->buffer_intensity_real_fx[i][j] = NULL;
     433             :         }
     434             : 
     435           3 :         free( ( *hMcMasa )->direction_vector_m_fx[i] );
     436           3 :         ( *hMcMasa )->direction_vector_m_fx[i] = NULL;
     437             :     }
     438             : 
     439          33 :     FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     440             :     {
     441          32 :         free( ( *hMcMasa )->buffer_intensity_real_vert_fx[j] );
     442          32 :         ( *hMcMasa )->buffer_intensity_real_vert_fx[j] = NULL;
     443             :     }
     444             : 
     445           1 :     free( ( *hMcMasa )->hMasaOut );
     446           1 :     ( *hMcMasa )->hMasaOut = NULL;
     447           1 :     free( ( *hMcMasa )->sph_grid16 );
     448           1 :     ( *hMcMasa )->sph_grid16 = NULL;
     449             : 
     450           1 :     free( ( *hMcMasa ) );
     451           1 :     ( *hMcMasa ) = NULL;
     452             : 
     453           1 :     return;
     454             : }
     455             : 
     456             : 
     457             : /*--------------------------------------------------------------------------*
     458             :  * ivas_mcmasa_ana()
     459             :  *
     460             :  * Multichannel MASA analysis
     461             :  *--------------------------------------------------------------------------*/
     462             : 
     463         150 : void ivas_mcmasa_ana_fx(
     464             :     MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle           */
     465             :     Word32 data[][L_FRAME48k], /* i/o: Input / transport audio signals */
     466             :     Word16 q_data,
     467             :     const Word16 input_frame,     /* i  : Input frame size                */
     468             :     const Word16 nchan_transport, /* i  : Number of transport channels    */
     469             :     const Word16 nchan_inp        /* i  : Number of input channels        */
     470             : )
     471             : {
     472             :     Word16 i;
     473             : 
     474             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     475             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     476             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     477             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     478             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     479             :     /* Sum center and LFE, move surround channels */
     480         150 :     v_add_32( data[2], data[3], data[2], input_frame );
     481        1350 :     FOR( i = 4; i < nchan_inp; i++ )
     482             :     {
     483        1200 :         Copy32( data[i], data[i - 1], input_frame );
     484             :     }
     485             : 
     486             :     /* Analysis */
     487         150 :     ivas_mcmasa_param_est_ana_fx( hMcMasa, data, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, q_data, input_frame, nchan_inp );
     488             : 
     489             :     /* Create MASA metadata buffer from the estimated values */
     490         150 :     ivas_create_masa_out_meta_fx( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, Q31, Q31, Q31 );
     491             : 
     492             :     /* Downmix */
     493             : 
     494         150 :     ivas_mcmasa_dmx_fx( hMcMasa, data, sub( 31, q_data ), input_frame, nchan_transport, nchan_inp );
     495             : 
     496             : 
     497         150 :     return;
     498             : }
     499             : 
     500             : 
     501             : /*--------------------------------------------------------------------------*
     502             :  * Local functions
     503             :  *--------------------------------------------------------------------------*/
     504             : 
     505             : /* Estimate metadata parameters for McMASA */
     506         150 : void ivas_mcmasa_param_est_ana_fx(
     507             :     MCMASA_ANA_HANDLE hMcMasa,                                                         /* i  : McMASA analyzer structure           */
     508             :     Word32 data_fx[][L_FRAME48k],                                                      /* i  : Audio frame in MC-format            */
     509             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* o  : Estimated elevation             Q22 */
     510             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* o  : Estimated azimuth               Q22 */
     511             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],          /* o  : Estimated direct-to-total ratio Q31 */
     512             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],      /* o  : Estimated spread coherence      Q31 */
     513             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o  : Estimated surround coherence    Q31 */
     514             :     Word16 q_data,
     515             :     const Word16 input_frame, /* i  : Input frame size                    */
     516             :     const Word16 nchan_inp    /* i  : Number of input channels            */
     517             : )
     518             : {
     519             :     Word16 cohPanCoh_e;
     520             :     Word16 tempLsEnergyRelation_e;
     521             :     Word16 q_vdv[MASA_FREQUENCY_BANDS];
     522             :     Word16 out_exp[MASA_FREQUENCY_BANDS];
     523             :     Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
     524             :     Word32 dir_v_fx[DIRAC_NUM_DIMS];
     525             :     Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     526             :     Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     527             :     Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     528             :     Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     529             :     Word32 FoaEven_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     530             :     Word32 FoaEven_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     531             :     Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     532             :     Word32 intensity_even_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     533             :     Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     534             :     Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
     535             :     Word32 vertical_diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
     536             :     Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS];
     537             :     Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
     538             :     Word32 coherentEnergyRatio_fx[MASA_FREQUENCY_BANDS];
     539             :     Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
     540             :     Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
     541             :     Word32 norm_tmp_fx;
     542             :     Word32 absCOVls_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
     543             :     Word16 absCOVls_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
     544             :     Word32 lsEnergy_fx[MCMASA_MAX_ANA_CHANS];
     545             :     Word16 lsEnergy_e[MCMASA_MAX_ANA_CHANS];
     546             :     Word32 lsEnergySum_fx, maxEne_fx;
     547         150 :     Word16 lsEnergySum_e = 0;
     548         150 :     move16();
     549             :     Word16 maxEne_e;
     550             :     Word32 angleDist_fx, minAngleDist_fx;
     551             :     Word32 currentAzi_fx;
     552             :     Word32 lsEnergyRelation_fx;
     553             :     Word16 lsEnergyRelation_e;
     554             :     Word32 tempLsEnergyRelation_fx;
     555             :     Word32 stereoness_fx, cohwideness_fx, spreadCoh_fx;
     556             :     Word32 stereoRatio_fx, cohPanRatio_fx;
     557             :     Word16 stereoness_e;
     558             :     Word32 stereoCoh_fx, cohPanCoh_fx, cohRatio_fx;
     559             :     Word32 surrCoh_fx, tempCoh_fx, tempCoh2_fx;
     560             :     Word16 surrCoh_e;
     561             :     Word16 stereoCoh_e;
     562             :     Word16 tempCoh_e;
     563             :     Word16 tempCoh2_e;
     564             :     Word16 ts, i, j, d;
     565             :     Word16 num_freq_bins, num_freq_bands, index;
     566             :     Word16 l_ts;
     567             :     Word16 band_m_idx, block_m_idx;
     568             :     Word16 mrange[2], brange[2];
     569             :     CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
     570             :     Word16 loudestCh;
     571             :     Word16 i1, i2, i3;
     572             :     Word16 numAnalysisChannels;
     573             :     Word16 spreadCoh_e;
     574         150 :     num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
     575         150 :     move16();
     576         150 :     num_freq_bands = hMcMasa->nbands;
     577         150 :     move16();
     578         150 :     l_ts = idiv1616( input_frame, CLDFB_NO_COL_MAX );
     579         150 :     numAnalysisChannels = sub( nchan_inp, 1 );
     580             : 
     581         150 :     set16_fx( q_vdv, 31, MASA_FREQUENCY_BANDS );
     582         150 :     set16_fx( out_exp, 30, MASA_FREQUENCY_BANDS );
     583             :     /* do processing over all CLDFB time slots */
     584         750 :     FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     585             :     {
     586         600 :         mrange[0] = hMcMasa->block_grouping[block_m_idx];
     587         600 :         move16();
     588         600 :         mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
     589         600 :         move16();
     590             : 
     591       15000 :         FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     592             :         {
     593       14400 :             hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
     594       14400 :             move16();
     595       14400 :             hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
     596       14400 :             move16();
     597       14400 :             hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
     598       14400 :             move16();
     599       14400 :             hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
     600       14400 :             move16();
     601       14400 :             hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
     602       14400 :             move16();
     603       14400 :             hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
     604       14400 :             move16();
     605             :         }
     606             : 
     607             :         /* Need to initialize renormalization_factors, and variables to be normalized */
     608         600 :         set_zero_fx( renormalization_factor_diff_fx, hMcMasa->nbands );
     609         600 :         set16_fx( renormalization_factor_diff_e, 0, hMcMasa->nbands );
     610         600 :         set_zero_fx( diffuseness_m_fx, hMcMasa->nbands );
     611         600 :         set16_fx( diffuseness_e, 0, hMcMasa->nbands );
     612         600 :         set_zero_fx( hMcMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
     613         600 :         set16_fx( hMcMasa->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
     614             :         /* Reset variable */
     615       15000 :         FOR( i = 0; i < hMcMasa->nbands; i++ )
     616             :         {
     617      172800 :             FOR( j = 0; j < numAnalysisChannels; j++ )
     618             :             {
     619      158400 :                 set_zero_fx( COVls[i].xr_fx[j], numAnalysisChannels );
     620      158400 :                 set_zero_fx( COVls[i].xi_fx[j], numAnalysisChannels );
     621      158400 :                 set16_fx( COVls[i].xr_e[j], 0, numAnalysisChannels );
     622      158400 :                 set16_fx( COVls[i].xi_e[j], 0, numAnalysisChannels );
     623             :             }
     624             :         }
     625             : 
     626        3000 :         FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
     627             :         {
     628        2400 :             Word16 cr_q = MAX_16, ci_q = MAX_16, sf, c_e;
     629        2400 :             move16();
     630        2400 :             move16();
     631        2400 :             Word16 inp_q = q_data;
     632        2400 :             move16();
     633       28800 :             FOR( i = 0; i < numAnalysisChannels; i++ )
     634             :             {
     635       26400 :                 inp_q = q_data;
     636       26400 :                 move16();
     637       26400 :                 cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][i_mult( l_ts, ts )] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hMcMasa->cldfbAnaEnc[i], &inp_q );
     638       26400 :                 cr_q = s_min( cr_q, getScaleFactor32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) );
     639       26400 :                 ci_q = s_min( ci_q, getScaleFactor32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) );
     640             :             }
     641        2400 :             sf = sub( s_min( cr_q, ci_q ), 4 );
     642       28800 :             FOR( i = 0; i < numAnalysisChannels; i++ )
     643             :             {
     644       26400 :                 scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf
     645       26400 :                 scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf
     646             :             }
     647        2400 :             inp_q = add( inp_q, sf );
     648        2400 :             c_e = sub( 31, inp_q );
     649        2400 :             hMcMasa->chnlToFoaMtx_e = c_e;
     650        2400 :             move16();
     651             :             /* Compute channel-based energy for metadata processing */
     652       60000 :             FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
     653             :             {
     654       57600 :                 brange[0] = hMcMasa->band_grouping[band_m_idx];
     655       57600 :                 move16();
     656       57600 :                 brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
     657       57600 :                 move16();
     658      201600 :                 FOR( j = brange[0]; j < brange[1]; j++ )
     659             :                 {
     660     1728000 :                     FOR( i = 0; i < numAnalysisChannels; i++ )
     661             :                     {
     662     1584000 :                         Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); // Q-> 2*inp_q - 31, e = 31 - (2*inp_q - 31) = 62 - 2*inp_q = 2*(31 - inp_q) = 2*c_e
     663     1584000 :                         hMcMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->energy_fx[block_m_idx][band_m_idx], hMcMasa->energy_e[block_m_idx][band_m_idx], temp, shl( c_e, 1 ), &hMcMasa->energy_e[block_m_idx][band_m_idx] );
     664     1584000 :                         move32();
     665             :                     }
     666             :                 }
     667             :             }
     668             : 
     669             :             /* Compute covariance matrix */
     670       60000 :             FOR( i = 0; i < num_freq_bands; i++ )
     671             :             {
     672       57600 :                 brange[0] = hMcMasa->band_grouping[i];
     673       57600 :                 move16();
     674       57600 :                 brange[1] = hMcMasa->band_grouping[i + 1];
     675       57600 :                 move16();
     676      201600 :                 FOR( j = brange[0]; j < brange[1]; j++ )
     677             :                 {
     678      144000 :                     compute_cov_mtx_fx( Chnl_RealBuffer_fx, Chnl_ImagBuffer_fx, j, numAnalysisChannels, &( COVls[i] ), c_e );
     679             :                 }
     680             :             }
     681             : 
     682             :             /* Compute standard FOA */
     683             :             /* W */
     684        2400 :             v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
     685        2400 :             v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
     686       24000 :             FOR( i = 2; i < numAnalysisChannels; i++ )
     687             :             {
     688       21600 :                 v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
     689       21600 :                 v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
     690             :             }
     691             : 
     692             :             /* Y */
     693        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
     694        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
     695       26400 :             FOR( i = 1; i < numAnalysisChannels; i++ )
     696             :             {
     697       24000 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
     698       24000 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
     699             :             }
     700             :             /* Z */
     701        2400 :             IF( hMcMasa->isHorizontalSetup )
     702             :             {
     703             :                 /* Set zero for horizontal setups */
     704           0 :                 set_zero_fx( Foa_RealBuffer_fx[2], num_freq_bins );
     705           0 :                 set_zero_fx( Foa_ImagBuffer_fx[2], num_freq_bins );
     706             :             }
     707             :             ELSE
     708             :             {
     709        2400 :                 v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
     710        2400 :                 v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
     711       26400 :                 FOR( i = 1; i < numAnalysisChannels; i++ )
     712             :                 {
     713       24000 :                     v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/
     714       24000 :                     v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/
     715             :                 }
     716             :             }
     717             :             /* X */
     718        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
     719        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
     720       26400 :             FOR( i = 1; i < numAnalysisChannels; i++ )
     721             :             {
     722       24000 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
     723       24000 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
     724             :             }
     725             : 
     726             :             /* Compute even FOA */
     727             :             /* W */
     728        2400 :             Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/
     729        2400 :             Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/
     730             : 
     731             :             /* Y */
     732        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
     733        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
     734       26400 :             FOR( i = 1; i < numAnalysisChannels; i++ )
     735             :             {
     736       24000 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/
     737       24000 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/
     738             :             }
     739             : 
     740             :             /* Z (even setups are handled as horizontal) */
     741        2400 :             set_zero_fx( FoaEven_RealBuffer_fx[2], num_freq_bins );
     742        2400 :             set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins );
     743             : 
     744             :             /* X */
     745        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
     746        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
     747       26400 :             FOR( i = 1; i < numAnalysisChannels; i++ )
     748             :             {
     749       24000 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/
     750       24000 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/
     751             :             }
     752             : 
     753             :             /* Direction estimation */
     754        2400 :             computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); /* Q intensity_real_fx = 2*inp_q-31, e = 31 - 2*inp_q + 31 = 62 - 2*inp_q = 2*(31-inp_q)=2*c_e */
     755             : 
     756        2400 :             computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], shl( c_e, 1 ),
     757             :                                            NULL ); /* Q direction_vector_fx = Q30*/
     758             : 
     759             :             /* Power and intensity estimation for diffuseness */
     760        2400 :             computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx ); /*2*inp_q-31*/
     761        2400 :             computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands );  /*2*inp_q-30*/
     762             : 
     763             :             /* Fill buffers of length "averaging_length" time slots for intensity and energy */
     764        2400 :             hMcMasa->index_buffer_intensity = add( ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
     765        2400 :             index = hMcMasa->index_buffer_intensity;
     766        2400 :             move16();
     767        9600 :             FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     768             :             {
     769             :                 /* only real part needed */
     770        7200 :                 Copy32( intensity_even_real_fx[i], &( hMcMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands );
     771             :             }
     772        2400 :             hMcMasa->buffer_intensity_real_q[index - 1] = sub( shl( inp_q, 1 ), 31 );
     773        2400 :             move16();
     774        2400 :             Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[i_mult( index - 1, num_freq_bands )] ), num_freq_bands );
     775        2400 :             hMcMasa->buffer_energy_q[index - 1] = sub( shl( inp_q, 1 ), 30 );
     776        2400 :             move16();
     777        2400 :             computeDiffuseness_fixed( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q, out_exp ); // out_exp = Q30
     778             :             /* Compute vertical diffuseness, and tune original diffuseness if needed */
     779        2400 :             IF( !hMcMasa->isHorizontalSetup )
     780             :             {
     781        2400 :                 Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands );
     782        2400 :                 hMcMasa->buffer_intensity_real_vert_q[index - 1] = sub( shl( inp_q, 1 ), 31 );
     783        2400 :                 move16();
     784        2400 :                 computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, num_freq_bands, vertical_diffuseness_vector_fx, hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q ); // Q vertical_diffuseness_vector_fx = 31
     785        2400 :                 v_min_fx( diffuseness_vector_fx, out_exp, vertical_diffuseness_vector_fx, q_vdv, diffuseness_vector_fx, out_exp, num_freq_bands );
     786             :             }
     787       60000 :             FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     788             :             {
     789       57600 :                 norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*2*inp_q-30*/
     790       57600 :                 hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] );
     791       57600 :                 hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] );
     792       57600 :                 hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] );
     793       57600 :                 diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), 1 ), sub( shl( c_e, 1 ), 1 ), &diffuseness_e[band_m_idx] );
     794       57600 :                 renormalization_factor_diff_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], reference_power_fx[ts][band_m_idx], sub( shl( c_e, 1 ), 1 ), &renormalization_factor_diff_e[band_m_idx] );
     795       57600 :                 move32();
     796       57600 :                 move32();
     797       57600 :                 move32();
     798       57600 :                 move32();
     799       57600 :                 move32();
     800             :             }
     801             :         }
     802       15000 :         FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     803             :         {
     804       14400 :             Word16 max_e = MIN_16;
     805       14400 :             move16();
     806       57600 :             FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
     807             :             {
     808       43200 :                 max_e = s_max( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] );
     809             :             }
     810       14400 :             max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/
     811       57600 :             FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
     812             :             {
     813       43200 :                 dir_v_fx[d] = L_shr( hMcMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) );
     814       43200 :                 move32();
     815             :             }
     816       14400 :             Word16 div_q = sub( 31, max_e );
     817       14400 :             ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, div_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] );
     818       14400 :             elevation_m_values_fx[block_m_idx][band_m_idx] = L_add( elevation_m_values_fx[block_m_idx][band_m_idx], L_shr( elevation_m_values_fx[block_m_idx][band_m_idx], 5 ) );
     819       14400 :             move32();
     820             :         }
     821             : 
     822             :         /* Coherence processing */
     823       15000 :         FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     824             :         {
     825             :             /* Compute absolute values */
     826      172800 :             FOR( i = 0; i < numAnalysisChannels; i++ )
     827             :             {
     828     1108800 :                 FOR( j = i; j < numAnalysisChannels; j++ )
     829             :                 {
     830      950400 :                     Word32 temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( COVls[band_m_idx].xr_fx[i][j], COVls[band_m_idx].xr_fx[i][j] ), shl( COVls[band_m_idx].xr_e[i][j], 1 ), Mult_32_32( COVls[band_m_idx].xi_fx[i][j], COVls[band_m_idx].xi_fx[i][j] ), shl( COVls[band_m_idx].xi_e[i][j], 1 ), &absCOVls_e[i][j] );
     831      950400 :                     absCOVls_fx[i][j] = Sqrt32( temp, &absCOVls_e[i][j] );
     832      950400 :                     move32();
     833             :                 }
     834      158400 :                 lsEnergy_fx[i] = absCOVls_fx[i][i];
     835      158400 :                 move32();
     836      158400 :                 lsEnergy_e[i] = absCOVls_e[i][i];
     837      158400 :                 move16();
     838             :             }
     839             : 
     840             :             /* Find loudest channel */
     841       14400 :             maxEne_fx = lsEnergy_fx[0];
     842       14400 :             move32();
     843       14400 :             maxEne_e = lsEnergy_e[0];
     844       14400 :             move16();
     845       14400 :             loudestCh = 0;
     846      158400 :             FOR( i = 1; i < numAnalysisChannels; i++ )
     847             :             {
     848      144000 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], maxEne_fx, maxEne_e ), 1 ) )
     849             :                 {
     850       27487 :                     maxEne_fx = lsEnergy_fx[i];
     851       27487 :                     move32();
     852       27487 :                     maxEne_e = lsEnergy_e[i];
     853       27487 :                     move16();
     854       27487 :                     loudestCh = i;
     855       27487 :                     move16();
     856             :                 }
     857             :             }
     858             : 
     859             :             /* Compute surrounding coherence */
     860       14400 :             surrCoh_fx = ONE_IN_Q31;
     861       14400 :             move32();
     862       14400 :             surrCoh_e = 0;
     863       14400 :             move16();
     864      172800 :             FOR( i = 0; i < numAnalysisChannels; i++ )
     865             :             {
     866      158400 :                 IF( NE_16( i, loudestCh ) )
     867             :                 {
     868      144000 :                     IF( LT_16( i, loudestCh ) )
     869             :                     {
     870       87891 :                         i1 = i;
     871       87891 :                         move16();
     872       87891 :                         i2 = loudestCh;
     873       87891 :                         move16();
     874             :                     }
     875             :                     ELSE
     876             :                     {
     877       56109 :                         i1 = loudestCh;
     878       56109 :                         move16();
     879       56109 :                         i2 = i;
     880       56109 :                         move16();
     881             :                     }
     882      144000 :                     Word16 temp_exp = add( lsEnergy_e[i1], lsEnergy_e[i2] );
     883      144000 :                     Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_exp );
     884      144000 :                     tempCoh_e = 0;
     885      144000 :                     move16();
     886      144000 :                     tempCoh_fx = L_shl( BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], temp, &tempCoh_e ), 16 );
     887      144000 :                     tempCoh_e = add( sub( absCOVls_e[i1][i2], temp_exp ), tempCoh_e );
     888      144000 :                     IF( NE_16( BASOP_Util_Cmp_Mant32Exp( surrCoh_fx, surrCoh_e, tempCoh_fx, tempCoh_e ), -1 ) )
     889             :                     {
     890       39805 :                         surrCoh_fx = tempCoh_fx;
     891       39805 :                         move32();
     892       39805 :                         surrCoh_e = tempCoh_e;
     893       39805 :                         move16();
     894             :                     }
     895             :                 }
     896             :             }
     897       14400 :             surrCoh_fx = L_shl( surrCoh_fx, surrCoh_e );
     898       14400 :             surrCoh_e = 0;
     899       14400 :             move16();
     900       14400 :             surrCoh_fx = Mult_32_32( surrCoh_fx, surrCoh_fx );
     901       14400 :             IF( GE_32( surrCoh_fx, ONE_IN_Q31 ) )
     902             :             {
     903           0 :                 surrCoh_fx = ONE_IN_Q31;
     904           0 :                 move32();
     905             :             }
     906       14400 :             surrCoh_fx = L_max( surrCoh_fx, 0 );
     907             :             /* Compute spread coherence */
     908       14400 :             IF( LT_32( elevation_m_values_fx[block_m_idx][band_m_idx], NEAR_HORIZONTAL_PLANE_ELEVATION_FX ) ) /* Computed only near horizontal plane */
     909             :             {
     910        2042 :                 minAngleDist_fx = 754974720; /*Q22*/
     911        2042 :                 move32();
     912        2042 :                 i1 = 0;
     913        2042 :                 move16();
     914        2042 :                 currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; /*Q22*/
     915        2042 :                 move32();
     916       16336 :                 FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     917             :                 {
     918       14294 :                     angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); /*Q22*/
     919       14294 :                     IF( GT_32( angleDist_fx, 754974720 /*180.0f Q.22*/ ) )
     920             :                     {
     921         881 :                         angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); /*Q22*/
     922             :                     }
     923       14294 :                     IF( LT_32( angleDist_fx, minAngleDist_fx ) )
     924             :                     {
     925        4611 :                         minAngleDist_fx = angleDist_fx; /*Q22*/
     926        4611 :                         move32();
     927        4611 :                         i1 = i;
     928        4611 :                         move16();
     929             :                     }
     930             :                 }
     931        2042 :                 i2 = hMcMasa->leftNearest[i1];
     932        2042 :                 move16();
     933        2042 :                 i3 = hMcMasa->rightNearest[i1];
     934        2042 :                 move16();
     935        2042 :                 Word16 temp_e = add( lsEnergy_e[i2], lsEnergy_e[i3] );
     936        2042 :                 Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i2], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e );
     937        2042 :                 IF( LT_16( i2, i3 ) )
     938             :                 {
     939        1631 :                     stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i3], temp, &stereoCoh_e );
     940        1631 :                     stereoCoh_e = add( sub( absCOVls_e[i2][i3], temp_e ), stereoCoh_e );
     941             :                 }
     942             :                 ELSE
     943             :                 {
     944         411 :                     stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i2], temp, &stereoCoh_e );
     945         411 :                     stereoCoh_e = add( sub( absCOVls_e[i3][i2], temp_e ), stereoCoh_e );
     946             :                 }
     947        2042 :                 stereoCoh_fx = L_shl( stereoCoh_fx, 16 );
     948             :                 Word32 temp1, temp2;
     949             :                 Word16 temp1_e, temp2_e;
     950        2042 :                 temp1 = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i2], lsEnergy_e[i2], lsEnergy_fx[i3], lsEnergy_e[i3], &temp1_e );
     951        2042 :                 temp2 = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, lsEnergy_fx[i1], lsEnergy_e[i1], &temp2_e );
     952        2042 :                 temp2 = L_add( temp2, EPSILON_FX );
     953        2042 :                 lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e );
     954        2042 :                 lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, temp2_e ) );
     955        2042 :                 lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31
     956        2042 :                 stereoness_fx = Mult_32_32( stereoCoh_fx, lsEnergyRelation_fx );
     957        2042 :                 stereoness_e = stereoCoh_e;
     958        2042 :                 move16();
     959        2042 :                 IF( LT_16( i1, i2 ) )
     960             :                 {
     961         638 :                     temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
     962         638 :                     tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
     963         638 :                     tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i1][i2], temp_e ) );
     964             :                 }
     965             :                 ELSE
     966             :                 {
     967        1404 :                     temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] );
     968        1404 :                     tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e );
     969        1404 :                     tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i2][i1], temp_e ) );
     970             :                 }
     971        2042 :                 tempCoh_fx = L_shl( tempCoh_fx, 16 );
     972        2042 :                 IF( LT_16( i1, i3 ) )
     973             :                 {
     974         498 :                     temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
     975         498 :                     tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i3], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
     976         498 :                     tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i1][i3], temp_e ) );
     977             :                 }
     978             :                 ELSE
     979             :                 {
     980        1544 :                     temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] );
     981        1544 :                     tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e );
     982        1544 :                     tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i3][i1], temp_e ) );
     983             :                 }
     984        2042 :                 tempCoh2_fx = L_shl( tempCoh2_fx, 16 );
     985        2042 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tempCoh_fx, tempCoh_e, tempCoh2_fx, tempCoh2_e ), -1 ) )
     986             :                 {
     987        1326 :                     cohPanCoh_fx = tempCoh_fx;
     988        1326 :                     move32();
     989        1326 :                     cohPanCoh_e = tempCoh_e;
     990        1326 :                     move16();
     991             :                 }
     992             :                 ELSE
     993             :                 {
     994         716 :                     cohPanCoh_fx = tempCoh2_fx;
     995         716 :                     move32();
     996         716 :                     cohPanCoh_e = tempCoh2_e;
     997         716 :                     move16();
     998             :                 }
     999        2042 :                 cohPanCoh_fx = L_shl( cohPanCoh_fx, cohPanCoh_e ); /*Q31*/
    1000        2042 :                 cohPanCoh_e = 0;
    1001        2042 :                 move16();
    1002        2042 :                 lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i2], L_add( lsEnergy_fx[i1], EPSILON_FX ), &lsEnergyRelation_e );
    1003        2042 :                 lsEnergyRelation_e = add( lsEnergyRelation_e, sub( lsEnergy_e[i2], lsEnergy_e[i1] ) );
    1004        2042 :                 tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i2], EPSILON_FX ), &tempLsEnergyRelation_e );
    1005        2042 :                 tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i2] ) );
    1006        2042 :                 IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
    1007             :                 {
    1008         597 :                     lsEnergyRelation_fx = tempLsEnergyRelation_fx;
    1009         597 :                     move32();
    1010         597 :                     lsEnergyRelation_e = tempLsEnergyRelation_e;
    1011         597 :                     move16();
    1012             :                 }
    1013        2042 :                 tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i3], L_add( lsEnergy_fx[i1], EPSILON_FX ), &tempLsEnergyRelation_e );
    1014        2042 :                 tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i3], lsEnergy_e[i1] ) );
    1015        2042 :                 IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
    1016             :                 {
    1017         459 :                     lsEnergyRelation_fx = tempLsEnergyRelation_fx;
    1018         459 :                     move32();
    1019         459 :                     lsEnergyRelation_e = tempLsEnergyRelation_e;
    1020         459 :                     move16();
    1021             :                 }
    1022        2042 :                 tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i3], EPSILON_FX ), &tempLsEnergyRelation_e );
    1023        2042 :                 tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i3] ) );
    1024        2042 :                 IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) )
    1025             :                 {
    1026         304 :                     lsEnergyRelation_fx = tempLsEnergyRelation_fx;
    1027         304 :                     move32();
    1028         304 :                     lsEnergyRelation_e = tempLsEnergyRelation_e;
    1029         304 :                     move16();
    1030             :                 }
    1031        2042 :                 lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); /*Q31*/
    1032        2042 :                 cohwideness_fx = Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx );                  /*cohPanCoh_e*/
    1033             : 
    1034        2042 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
    1035             :                 {
    1036         344 :                     spreadCoh_fx = cohwideness_fx;
    1037         344 :                     move32();
    1038         344 :                     spreadCoh_e = cohPanCoh_e;
    1039         344 :                     move16();
    1040             :                 }
    1041             :                 ELSE
    1042             :                 {
    1043        1698 :                     spreadCoh_fx = stereoness_fx;
    1044        1698 :                     move32();
    1045        1698 :                     spreadCoh_e = stereoness_e;
    1046        1698 :                     move16();
    1047             :                 }
    1048        2042 :                 IF( ( spreadCoh_e < 0 ) )
    1049             :                 {
    1050         161 :                     spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
    1051         161 :                     spreadCoh_e = 0;
    1052         161 :                     move16();
    1053             :                 }
    1054        2042 :                 IF( GT_32( spreadCoh_fx, L_shl_sat( 1, sub( 30, spreadCoh_e ) /*0.5f with exp=spreadCoh_e*/ ) ) )
    1055             :                 {
    1056         629 :                     IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) )
    1057             :                     {
    1058             : 
    1059         159 :                         tempCoh_fx = BASOP_Util_Add_Mant32Exp( stereoness_fx, stereoness_e, L_negate( L_sub( cohwideness_fx, L_shl( 1, sub( 30, cohPanCoh_e ) ) ) ), cohPanCoh_e, &tempCoh_e );
    1060         159 :                         IF( ( tempCoh_e < 0 ) )
    1061             :                         {
    1062         159 :                             tempCoh_fx = L_shl( tempCoh_fx, tempCoh_e );
    1063         159 :                             tempCoh_e = 0;
    1064         159 :                             move16();
    1065             :                         }
    1066         159 :                         IF( GT_32( tempCoh_fx, L_shl_sat( 1, sub( 30, tempCoh_e ) ) ) )
    1067             :                         {
    1068           0 :                             spreadCoh_fx = tempCoh_fx;
    1069           0 :                             move32();
    1070             :                         }
    1071             :                         ELSE
    1072             :                         {
    1073         159 :                             spreadCoh_fx = L_shl_sat( 1, sub( 30, tempCoh_e ) );
    1074             :                         }
    1075         159 :                         spreadCoh_e = tempCoh_e;
    1076         159 :                         move16();
    1077             :                     }
    1078             :                 }
    1079        2042 :                 IF( ( spreadCoh_e < 0 ) )
    1080             :                 {
    1081           0 :                     spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );
    1082           0 :                     spreadCoh_e = 0;
    1083           0 :                     move16();
    1084             :                 }
    1085             : 
    1086        2042 :                 IF( GE_32( spreadCoh_fx, L_shl_sat( 1, sub( 31, spreadCoh_e ) ) ) )
    1087             :                 {
    1088           0 :                     spreadCoh_fx = L_shl_sat( 1, sub( 31, spreadCoh_e ) );
    1089             :                 }
    1090        2042 :                 IF( ( spreadCoh_fx <= 0 ) )
    1091             :                 {
    1092           0 :                     spreadCoh_fx = 0;
    1093           0 :                     move32();
    1094             :                 }
    1095        2042 :                 spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); /*Q31*/
    1096             :                 /* Compute energy ratio tuning parameter */
    1097        2042 :                 lsEnergySum_fx = 0;
    1098        2042 :                 move32();
    1099        2042 :                 lsEnergySum_e = 0;
    1100        2042 :                 move16();
    1101       24504 :                 FOR( i = 0; i < numAnalysisChannels; i++ )
    1102             :                 {
    1103       22462 :                     lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
    1104             :                 }
    1105        2042 :                 lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
    1106        2042 :                 lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, lsEnergySum_fx, &lsEnergyRelation_e );
    1107        2042 :                 lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, lsEnergySum_e ) );
    1108        2042 :                 lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) );                               // Q31
    1109        2042 :                 stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); // Q31
    1110             : 
    1111        2042 :                 lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e );
    1112        2042 :                 lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp2_e, lsEnergySum_e ) );
    1113        2042 :                 lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) );     // Q31
    1114        2042 :                 cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); // Q31
    1115             : 
    1116        2042 :                 IF( GT_32( stereoRatio_fx, cohPanRatio_fx ) )
    1117             :                 {
    1118         104 :                     cohRatio_fx = stereoRatio_fx;
    1119         104 :                     move32();
    1120             :                 }
    1121             :                 ELSE
    1122             :                 {
    1123        1938 :                     cohRatio_fx = cohPanRatio_fx;
    1124        1938 :                     move32();
    1125             :                 }
    1126             : 
    1127        2042 :                 IF( GE_32( cohRatio_fx, ONE_IN_Q31 ) )
    1128             :                 {
    1129           0 :                     cohRatio_fx = ONE_IN_Q31;
    1130           0 :                     move32();
    1131             :                 }
    1132             : 
    1133        2042 :                 IF( cohRatio_fx <= 0 )
    1134             :                 {
    1135         595 :                     cohRatio_fx = 0;
    1136         595 :                     move32();
    1137             :                 }
    1138             :             }
    1139             :             ELSE /* Otherwise, set spread coherence to zero */
    1140             :             {
    1141       12358 :                 spreadCoh_fx = 0;
    1142       12358 :                 move32();
    1143       12358 :                 cohRatio_fx = 0;
    1144       12358 :                 move32();
    1145       12358 :                 lsEnergySum_fx = 0;
    1146       12358 :                 move32();
    1147      148296 :                 FOR( i = 0; i < numAnalysisChannels; i++ )
    1148             :                 {
    1149      135938 :                     lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e );
    1150             :                 }
    1151       12358 :                 lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX );
    1152             :             }
    1153             : 
    1154             :             /* Store values */
    1155       14400 :             spreadCoherence_fx[block_m_idx][band_m_idx] = spreadCoh_fx; /*Q31*/
    1156       14400 :             move32();
    1157       14400 :             surroundingCoherence_fx[block_m_idx][band_m_idx] = surrCoh_fx; /*Q31*/
    1158       14400 :             move32();
    1159       14400 :             coherentEnergyRatio_fx[band_m_idx] = cohRatio_fx; /*Q31*/
    1160       14400 :             move32();
    1161             :         }
    1162             : 
    1163             :         /* Determine energy ratios */
    1164       15000 :         FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
    1165             :         {
    1166             :             Word16 diffuseness_m_e;
    1167       14400 :             IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) )
    1168             :             {
    1169       14400 :                 diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e );
    1170       14400 :                 move32();
    1171       14400 :                 diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
    1172       14400 :                 diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31
    1173       14400 :                 move32();
    1174             :             }
    1175             :             ELSE
    1176             :             {
    1177           0 :                 diffuseness_m_fx[band_m_idx] = 0;
    1178           0 :                 move32();
    1179             :             }
    1180             : 
    1181       14400 :             energyRatio_fx[block_m_idx][band_m_idx] = L_sub( ONE_IN_Q31, diffuseness_m_fx[band_m_idx] );
    1182       14400 :             move32();
    1183       14400 :             IF( GT_32( energyRatio_fx[block_m_idx][band_m_idx], coherentEnergyRatio_fx[band_m_idx] ) )
    1184             :             {
    1185       13165 :                 energyRatio_fx[block_m_idx][band_m_idx] = energyRatio_fx[block_m_idx][band_m_idx];
    1186       13165 :                 move32();
    1187             :             }
    1188             :             ELSE
    1189             :             {
    1190        1235 :                 energyRatio_fx[block_m_idx][band_m_idx] = coherentEnergyRatio_fx[band_m_idx];
    1191        1235 :                 move32();
    1192             :             }
    1193             :         }
    1194             :     }
    1195         150 :     return;
    1196             : }
    1197             : 
    1198         150 : static void ivas_mcmasa_dmx_fx(
    1199             :     MCMASA_ANA_HANDLE hMcMasa,
    1200             :     Word32 data_f_fx[][L_FRAME48k],
    1201             :     Word16 data_e,
    1202             :     const Word16 input_frame,
    1203             :     const Word16 nchan_transport,
    1204             :     const Word16 nchan_inp )
    1205             : {
    1206             :     Word16 i, j;
    1207             :     Word16 numAnalysisChannels;
    1208             : 
    1209             :     Word32 dmx_c_fx;
    1210             :     Word32 multiChEne_fx, downmixEne_fx;
    1211             :     Word32 prevEQ_fx, currEQ_fx, instEQ_fx;
    1212             :     Word32 alpha_fx, L_tmp, L_tmp1;
    1213         150 :     Word16 multiChEne_e, scale, downmixEne_e = 0, prevEQ_e, tmp, currEQ_e, instEQ_e;
    1214         150 :     move16();
    1215             : 
    1216         150 :     numAnalysisChannels = sub( nchan_inp, 1 );
    1217             : 
    1218         150 :     multiChEne_fx = 0;
    1219         150 :     move32();
    1220         150 :     multiChEne_e = 0;
    1221         150 :     move16();
    1222             : 
    1223        1800 :     FOR( j = 0; j < numAnalysisChannels; j++ )
    1224             :     {
    1225     1585650 :         FOR( i = 0; i < input_frame; i++ )
    1226             :         {
    1227     1584000 :             L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
    1228     1584000 :             L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
    1229     1584000 :             multiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, multiChEne_fx, multiChEne_e, &scale );
    1230     1584000 :             multiChEne_e = scale;
    1231     1584000 :             move16();
    1232             :         }
    1233             :     }
    1234             : 
    1235         150 :     IF( EQ_16( nchan_transport, 2 ) )
    1236             :     {
    1237             :         Word16 numSideChannels; /* Channels other than left, right, center */
    1238             :         Word16 leftIndex, rightIndex;
    1239             : 
    1240         150 :         numSideChannels = sub( shr( numAnalysisChannels, 1 ), 1 );
    1241         750 :         FOR( j = 0; j < numSideChannels; j++ )
    1242             :         {
    1243         600 :             leftIndex = add( shl( j, 1 ), 3 );
    1244         600 :             rightIndex = add( shl( j, 1 ), 4 );
    1245             : 
    1246      576600 :             FOR( i = 0; i < input_frame; i++ )
    1247             :             {
    1248      576000 :                 data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[leftIndex][i] );
    1249      576000 :                 move32();
    1250      576000 :                 data_f_fx[1][i] = L_add( data_f_fx[1][i], data_f_fx[rightIndex][i] );
    1251      576000 :                 move32();
    1252             :             }
    1253             :         }
    1254             : 
    1255      144150 :         FOR( i = 0; i < input_frame; i++ )
    1256             :         {
    1257      144000 :             dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_f_fx[2][i] ) ); // data_e
    1258      144000 :             move32();
    1259      144000 :             data_f_fx[0][i] = L_add( dmx_c_fx, data_f_fx[0][i] );
    1260      144000 :             move32();
    1261      144000 :             data_f_fx[1][i] = L_add( dmx_c_fx, data_f_fx[1][i] );
    1262      144000 :             move32();
    1263             :         }
    1264             :     }
    1265           0 :     ELSE IF( EQ_16( nchan_transport, 1 ) )
    1266             :     {
    1267           0 :         FOR( i = 0; i < input_frame; i++ )
    1268             :         {
    1269           0 :             FOR( j = 1; j < numAnalysisChannels; j++ )
    1270             :             {
    1271           0 :                 data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[j][i] );
    1272           0 :                 move32();
    1273             :             }
    1274             :         }
    1275             :     }
    1276             : 
    1277         150 :     downmixEne_fx = 0;
    1278         150 :     move32();
    1279             : 
    1280         450 :     FOR( j = 0; j < nchan_transport; j++ )
    1281             :     {
    1282      288300 :         FOR( i = 0; i < input_frame; i++ )
    1283             :         {
    1284      288000 :             L_tmp1 = BASOP_Util_Add_Mant32Exp( data_f_fx[j][i], data_e, 0, 0, &scale );
    1285      288000 :             L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e
    1286      288000 :             downmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, downmixEne_fx, downmixEne_e, &downmixEne_e );
    1287             :         }
    1288             :     }
    1289             : 
    1290         150 :     alpha_fx = 214748364; // 0.1 in Q31
    1291         150 :     move32();
    1292             : 
    1293         150 :     L_tmp = Mpy_32_32( alpha_fx, multiChEne_fx );
    1294         150 :     L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevMultiChEne_fx );
    1295         150 :     hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e );
    1296             : 
    1297             : 
    1298         150 :     L_tmp = Mpy_32_32( alpha_fx, downmixEne_fx );
    1299         150 :     L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevDownmixEne_fx );
    1300         150 :     hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e );
    1301             : 
    1302         150 :     prevEQ_fx = hMcMasa->prevEQ_fx;
    1303         150 :     move32();
    1304         150 :     prevEQ_e = hMcMasa->prevEQ_e;
    1305         150 :     move16();
    1306             : 
    1307         150 :     tmp = BASOP_Util_Divide3232_Scale( hMcMasa->prevMultiChEne_fx, L_add( hMcMasa->prevDownmixEne_fx, EPSILON_FX ), &scale );
    1308         150 :     currEQ_e = add( scale, sub( hMcMasa->prevMultiChEne_e, hMcMasa->prevDownmixEne_e ) );
    1309         150 :     currEQ_fx = Sqrt32( L_deposit_h( tmp ), &currEQ_e );
    1310             : 
    1311         150 :     hMcMasa->prevEQ_fx = currEQ_fx;
    1312         150 :     move32();
    1313         150 :     hMcMasa->prevEQ_e = currEQ_e;
    1314         150 :     move16();
    1315             : 
    1316      144150 :     FOR( i = 0; i < input_frame; i++ )
    1317             :     {
    1318      144000 :         L_tmp = Mpy_32_32( L_deposit_h( hMcMasa->interpolator_fx[i] ), currEQ_fx );
    1319      144000 :         L_tmp1 = L_sub( 1073741824 /* 1.0 in Q30*/, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); // Q30
    1320      144000 :         L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx );                                                               // e = prevEQ_e + 1
    1321      144000 :         instEQ_fx = BASOP_Util_Add_Mant32Exp( L_tmp, currEQ_e, L_tmp1, add( prevEQ_e, 1 ), &instEQ_e );
    1322             : 
    1323      432000 :         FOR( j = 0; j < nchan_transport; j++ )
    1324             :         {
    1325      288000 :             data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); // e = data_e + instEQ_e
    1326      288000 :             move32();
    1327      288000 :             move32();
    1328      288000 :             data_f_fx[j][i] = L_shl( data_f_fx[j][i], instEQ_e ); // data_e
    1329             :         }
    1330             :     }
    1331             : 
    1332         150 :     return;
    1333             : }
    1334             : 
    1335             : 
    1336             : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
    1337      144000 : static void compute_cov_mtx_fx(
    1338             :     Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, real, s[ch][freq]                         */
    1339             :     Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, imag, s[ch][freq]                         */
    1340             :     const Word16 freq,                                      /* i  : Freq to process                                         */
    1341             :     const Word16 N,                                         /* i  : Number of channels                                      */
    1342             :     CovarianceMatrix *COVls,                                /* o  : Output matrix, contains upper part of cov mtx           */
    1343             :     Word16 inp_exp                                          /* i  : Stores exponent for sr and si                           */
    1344             : )
    1345             : {
    1346             :     Word16 i, j;
    1347             :     Word32 a, b, c, d;
    1348             :     Word32 temp;
    1349             :     Word16 norm_a, norm_b, norm_c, norm_d;
    1350             :     Word16 shift;
    1351     1728000 :     FOR( i = 0; i < N; i++ )
    1352             :     {
    1353     1584000 :         a = sr[i][freq];
    1354     1584000 :         b = si[i][freq];
    1355     1584000 :         norm_a = norm_l( a );
    1356     1584000 :         norm_b = norm_l( b );
    1357     1584000 :         a = L_shl( a, norm_a ); /*inp_exp-norm_a*/
    1358     1584000 :         b = L_shl( b, norm_b ); /*inp_exp-norm_b*/
    1359    11088000 :         FOR( j = i; j < N; j++ )
    1360             :         {
    1361     9504000 :             c = sr[j][freq];
    1362     9504000 :             d = si[j][freq];
    1363     9504000 :             norm_c = norm_l( c );
    1364     9504000 :             norm_d = norm_l( d );
    1365     9504000 :             c = L_shl( c, norm_c ); /*inp_exp-norm_c*/
    1366     9504000 :             d = L_shl( d, norm_d ); /*inp_exp-norm_d*/
    1367     9504000 :             temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), sub( shl( inp_exp, 1 ), add( norm_a, norm_c ) ), Mult_32_32( b, d ), sub( shl( inp_exp, 1 ), add( norm_b, norm_d ) ), &shift );
    1368     9504000 :             COVls->xr_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xr_fx[i][j], COVls->xr_e[i][j], temp, shift, &COVls->xr_e[i][j] );
    1369     9504000 :             move32();
    1370     9504000 :             temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( b, c ), sub( shl( inp_exp, 1 ), add( norm_b, norm_c ) ), L_negate( Mult_32_32( a, d ) ), sub( shl( inp_exp, 1 ), add( norm_a, norm_d ) ), &shift );
    1371     9504000 :             COVls->xi_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xi_fx[i][j], COVls->xi_e[i][j], temp, shift, &COVls->xi_e[i][j] );
    1372     9504000 :             move32();
    1373             :         }
    1374             :     }
    1375             : 
    1376      144000 :     return;
    1377             : }
    1378             : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
    1379             : 
    1380             : /*-------------------------------------------------------------------------
    1381             :  * computeVerticalDiffuseness()
    1382             :  *
    1383             :  *
    1384             :  *------------------------------------------------------------------------*/
    1385        2400 : static void computeVerticalDiffuseness_fx(
    1386             :     Word32 **buffer_intensity,   /* i  : Intensity vectors           */
    1387             :     const Word32 *buffer_energy, /* i  : Energy                      */
    1388             :     const Word16 num_freq_bands, /* i  : Number of frequency bands   */
    1389             :     Word32 *diffuseness,         /* o  : Estimated diffuseness   Q31 */
    1390             :     Word16 *buffer_intensity_q,
    1391             :     Word16 *buffer_energy_q )
    1392             : {
    1393             :     Word32 intensity_slow[MASA_FREQUENCY_BANDS];
    1394             :     Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS];
    1395             :     Word32 energy_slow[MASA_FREQUENCY_BANDS];
    1396             :     Word16 i, k;
    1397        2400 :     Word32 tmp = 0;
    1398        2400 :     move32();
    1399             :     const Word32 *p_tmp_c;
    1400             :     Word16 intensity_slow_e[MASA_FREQUENCY_BANDS], energy_slow_e[MASA_FREQUENCY_BANDS];
    1401             : 
    1402             :     /* Set variables to zero */
    1403        2400 :     set32_fx( intensity_slow, 0, MASA_FREQUENCY_BANDS );
    1404        2400 :     set32_fx( energy_slow, 0, MASA_FREQUENCY_BANDS );
    1405        2400 :     set16_fx( intensity_slow_e, 0, MASA_FREQUENCY_BANDS );
    1406        2400 :     set16_fx( energy_slow_e, 0, MASA_FREQUENCY_BANDS );
    1407             : 
    1408       79200 :     FOR( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
    1409             :     {
    1410             :         /* Energy slow */
    1411       76800 :         p_tmp_c = buffer_energy + i_mult( i, num_freq_bands );
    1412     1920000 :         FOR( k = 0; k < num_freq_bands; k++ )
    1413             :         {
    1414     1843200 :             energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], *( p_tmp_c ), sub( 31, buffer_energy_q[i] ), &energy_slow_e[k] );
    1415     1843200 :             move32();
    1416     1843200 :             p_tmp_c++;
    1417             :         }
    1418             : 
    1419             :         /* Intensity slow */
    1420     1920000 :         FOR( k = 0; k < num_freq_bands; k++ )
    1421             :         {
    1422     1843200 :             intensity_slow[k] = BASOP_Util_Add_Mant32Exp( intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k], sub( 31, buffer_intensity_q[i] ), &intensity_slow_e[k] );
    1423     1843200 :             move32();
    1424             :         }
    1425             :     }
    1426             : 
    1427             :     /* Compute absolute value */
    1428       60000 :     FOR( k = 0; k < num_freq_bands; k++ )
    1429             :     {
    1430       57600 :         intensity_slow_abs[k] = L_abs( intensity_slow[k] );
    1431       57600 :         move32();
    1432             :     }
    1433             : 
    1434             :     /* Compute Diffuseness */
    1435       60000 :     FOR( i = 0; i < num_freq_bands; ++i )
    1436             :     {
    1437             :         Word16 tmp_e1, tmp_e2;
    1438       57600 :         tmp = BASOP_Util_Divide3232_Scale( intensity_slow_abs[i], L_add( energy_slow[i], EPSILON_FX_SMALL ), &tmp_e1 );
    1439       57600 :         tmp_e1 = add( tmp_e1, sub( intensity_slow_e[i], energy_slow_e[i] ) );
    1440       57600 :         tmp = BASOP_Util_Divide3232_Scale( L_sub( tmp, L_shr( VERTICAL_ENERGY_RATIO_OFFSET_FX, tmp_e1 ) ), L_sub( ONE_IN_Q15, VERTICAL_ENERGY_RATIO_OFFSET_FX ), &tmp_e2 ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
    1441       57600 :         tmp_e2 = add( tmp_e2, tmp_e1 );
    1442       57600 :         tmp = L_sub( L_shl( 1, sub( 15, tmp_e2 ) ), tmp );
    1443       57600 :         IF( tmp < 0 )
    1444             :         {
    1445           0 :             tmp = 0;
    1446           0 :             move32();
    1447             :         }
    1448       57600 :         ELSE IF( GE_32( tmp, L_shl( 1, sub( 15, tmp_e2 ) ) ) )
    1449             :         {
    1450        1406 :             tmp = ONE_IN_Q31; // Q31
    1451        1406 :             move32();
    1452             :         }
    1453             :         ELSE
    1454             :         {
    1455       56194 :             tmp = L_shl( tmp, add( 16, tmp_e2 ) ); // Q31
    1456             :         }
    1457       57600 :         diffuseness[i] = tmp; // Q31
    1458       57600 :         move32();
    1459             :     }
    1460             : 
    1461        2400 :     return;
    1462             : }
    1463             : 
    1464             : 
    1465           2 : static void computeEvenLayout_fx(
    1466             :     const Word32 *ls_azimuth, /* i: Q22 */
    1467             :     Word32 *ls_azimuth_even,  /* o: Q22 */
    1468             :     const Word16 numChannels )
    1469             : {
    1470             :     Word16 i;
    1471             :     Word16 j;
    1472             :     Word32 ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
    1473             :     Word32 ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
    1474             :     Word16 ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
    1475             :     Word32 smallestAzimuth;
    1476             :     Word16 smallestAzimuthIndex;
    1477             :     Word32 lsSpacing;
    1478             :     UWord8 oddLayout;
    1479             :     Word32 startAzimuth;
    1480             :     Word16 numChannelsHalf;
    1481             : 
    1482           2 :     lsSpacing = L_shl( L_mult0( 360, div_s( 1, numChannels ) ), 6 ); /*Q.21*/
    1483           2 :     oddLayout = (UWord8) s_and( numChannels, 1 );
    1484           2 :     move16();
    1485           2 :     numChannelsHalf = shr( numChannels, 1 );
    1486             : 
    1487           2 :     Copy32( ls_azimuth, ls_azimuth_temp, numChannels );
    1488           2 :     Scale_sig32( ls_azimuth_temp, numChannels, -1 ); /*Q.21*/
    1489          13 :     FOR( i = 0; i < numChannels; i++ )
    1490             :     {
    1491          11 :         smallestAzimuth = 1000 << 21; /*Q21*/
    1492          11 :         move32();
    1493          11 :         smallestAzimuthIndex = 0;
    1494          11 :         move16();
    1495          76 :         FOR( j = 0; j < numChannels; j++ )
    1496             :         {
    1497          65 :             IF( LT_32( ls_azimuth_temp[j], smallestAzimuth ) )
    1498             :             {
    1499          21 :                 smallestAzimuth = ls_azimuth_temp[j]; /*Q21*/
    1500          21 :                 move32();
    1501          21 :                 smallestAzimuthIndex = j;
    1502          21 :                 move16();
    1503             :             }
    1504             :         }
    1505          11 :         ls_azimuth_order[i] = smallestAzimuthIndex;
    1506          11 :         move32();
    1507          11 :         ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); /*Q21*/
    1508          11 :         move32();
    1509             :     }
    1510             : 
    1511           2 :     IF( oddLayout )
    1512             :     {
    1513           1 :         startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, shl( numChannelsHalf, 1 ) ) ); /*Q.22*/
    1514             :     }
    1515             :     ELSE
    1516             :     {
    1517           1 :         startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, sub( shl( numChannelsHalf, 1 ), 1 ) ) ); /*Q.22*/
    1518             :     }
    1519             : 
    1520          13 :     FOR( i = 0; i < numChannels; i++ )
    1521             :     {
    1522          11 :         ls_azimuth_even_ordered[i] = W_extract_l( W_add( W_mult_32_16( lsSpacing, i ), startAzimuth ) ); /*Q.22*/
    1523          11 :         move32();
    1524             :     }
    1525             : 
    1526          13 :     FOR( i = 0; i < numChannels; i++ )
    1527             :     {
    1528          11 :         ls_azimuth_even[ls_azimuth_order[i]] = L_shl( L_shr( L_add( ls_azimuth_even_ordered[i], ONE_IN_Q21 /* 0.5 in Q22 */ ), 22 ), 22 ); /*Q22*/
    1529          11 :         move32();
    1530             :     }
    1531             : 
    1532           2 :     return;
    1533             : }
    1534             : 
    1535             : 
    1536             : /*-------------------------------------------------------------------------
    1537             :  * ivas_create_masa_out_meta()
    1538             :  *
    1539             :  *
    1540             :  *------------------------------------------------------------------------*/
    1541             : 
    1542         450 : void ivas_create_masa_out_meta_fx(
    1543             :     MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta,                                    /* i/o: MASA metadata handle               */
    1544             :     SPHERICAL_GRID_DATA *Sph_Grid16,                                                /* i  : Spherical grid                     */
    1545             :     const Word16 nchan_transport,                                                   /* i  : Number of transport channels       */
    1546             :     Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* i  : Estimated elevation            Q22 */
    1547             :     Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* i  : Estimated azimuth              Q22 */
    1548             :     Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],          /* i  : Estimated direct-to-total ratio    */
    1549             :     Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],      /* i  : Estimated spread coherence         */
    1550             :     Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i  : Estimated surround coherence       */
    1551             :     Word16 energyRatio_q,
    1552             :     Word16 spreadCoherence_q,
    1553             :     Word16 surroundingCoherence_q
    1554             : 
    1555             : )
    1556             : {
    1557         450 :     const UWord8 ivasmasaFormatDescriptor[8] = { 0x49, 0x56, 0x41, 0x53, 0x4D, 0x41, 0x53, 0x41 }; /* "IVASMASA" */
    1558             :     Word16 i, sf, band;
    1559             :     UWord8 numFrequencyBands;
    1560             :     UWord8 numDirections;
    1561             :     UWord16 spherical_index;
    1562             : 
    1563         450 :     numDirections = 1;
    1564         450 :     move16();
    1565         450 :     numFrequencyBands = MASA_FREQUENCY_BANDS;
    1566         450 :     move16();
    1567             : 
    1568             :     /* Construct descriptive meta */
    1569        4050 :     FOR( i = 0; i < 8; i++ )
    1570             :     {
    1571        3600 :         extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
    1572        3600 :         move16();
    1573             :     }
    1574         450 :     extOutMeta->descriptiveMeta.numberOfDirections = (UWord8) sub( numDirections, 1 );
    1575         450 :     move16();
    1576         450 :     extOutMeta->descriptiveMeta.numberOfChannels = (UWord8) sub( nchan_transport, 1 );
    1577         450 :     move16();
    1578             :     /* Following correspond to "unknown" values */
    1579         450 :     extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
    1580         450 :     move16();
    1581         450 :     extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
    1582         450 :     move16();
    1583         450 :     extOutMeta->descriptiveMeta.channelAngle = 0x0u;
    1584         450 :     move16();
    1585         450 :     extOutMeta->descriptiveMeta.channelDistance = 0x0u;
    1586         450 :     move16();
    1587         450 :     extOutMeta->descriptiveMeta.channelLayout = 0x0u;
    1588         450 :     move16();
    1589             : 
    1590             :     /* Construct spatial metadata from estimated values */
    1591        2250 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1592             :     {
    1593             :         /* Spherical index */
    1594       45000 :         FOR( band = 0; band < numFrequencyBands; band++ )
    1595             :         {
    1596       43200 :             spherical_index = index_theta_phi_16_fx( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
    1597       43200 :             move16();
    1598       43200 :             extOutMeta->directionIndex[0][sf][band] = spherical_index;
    1599       43200 :             move16();
    1600       43200 :             extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
    1601       43200 :             move16();
    1602             :         }
    1603             : 
    1604             :         /* Direct-to-total ratio */
    1605       45000 :         FOR( band = 0; band < numFrequencyBands; band++ )
    1606             :         {
    1607       43200 :             extOutMeta->directToTotalRatio[0][sf][band] = (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ); // Q8
    1608       43200 :             move16();
    1609       43200 :             extOutMeta->directToTotalRatio[1][sf][band] = 0;
    1610       43200 :             move16();
    1611             :         }
    1612             : 
    1613             :         /* Spread coherence */
    1614       45000 :         FOR( band = 0; band < numFrequencyBands; band++ )
    1615             :         {
    1616       43200 :             extOutMeta->spreadCoherence[0][sf][band] = (UWord8) L_shr( spreadCoherence[sf][band], sub( spreadCoherence_q, 8 ) ); // Q8
    1617       43200 :             move16();
    1618       43200 :             extOutMeta->spreadCoherence[1][sf][band] = 0;
    1619       43200 :             move16();
    1620             :         }
    1621             : 
    1622             :         /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
    1623       45000 :         FOR( band = 0; band < numFrequencyBands; band++ )
    1624             :         {
    1625       43200 :             extOutMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( UINT8_MAX, (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ) ); // Q8
    1626       43200 :             move16();
    1627             :         }
    1628             : 
    1629             :         /* Surround coherence */
    1630       45000 :         FOR( band = 0; band < numFrequencyBands; band++ )
    1631             :         {
    1632       43200 :             extOutMeta->surroundCoherence[sf][band] = (UWord8) L_shr( surroundingCoherence[sf][band], sub( surroundingCoherence_q, 8 ) ); // Q8
    1633       43200 :             move16();
    1634             :         }
    1635             :     }
    1636             : 
    1637         450 :     return;
    1638             : }

Generated by: LCOV version 1.14