LCOV - code coverage report
Current view: top level - lib_rend - ivas_mcmasa_ana.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 398 433 91.9 %
Date: 2025-05-23 08:37:30 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.h"
      39             : #include "ivas_prot.h"
      40             : #include "prot.h"
      41             : #include "ivas_stat_rend.h"
      42             : #include "ivas_rom_com.h"
      43             : #ifdef DEBUGGING
      44             : #include "debug.h"
      45             : #endif
      46             : #include "wmc_auto.h"
      47             : 
      48             : 
      49             : /*-------------------------------------------------------------------------
      50             :  * Local constants
      51             :  *------------------------------------------------------------------------*/
      52             : 
      53             : #define NEAR_HORIZONTAL_PLANE_ELEVATION 17.5f
      54             : #define VERTICAL_ENERGY_RATIO_OFFSET    0.15f
      55             : 
      56             : 
      57             : /*-------------------------------------------------------------------------
      58             :  * Local function prototypes
      59             :  *------------------------------------------------------------------------*/
      60             : 
      61             : /* Structure for covariance matrix */
      62             : typedef struct
      63             : {
      64             :     float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      65             :     float xi[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
      66             : } CovarianceMatrix;
      67             : 
      68             : void ivas_mcmasa_param_est_ana( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const int16_t input_frame, const int16_t nchan_inp );
      69             : 
      70             : static void ivas_mcmasa_dmx( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_transport, const int16_t nchan_inp );
      71             : 
      72             : static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], const int16_t freq, const int16_t N, CovarianceMatrix *COVls );
      73             : 
      74             : static void computeVerticalDiffuseness( float **buffer_intensity, const float *buffer_energy, const int16_t num_freq_bands, float *diffuseness );
      75             : 
      76             : static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, const int16_t numChannels );
      77             : 
      78             : 
      79             : /*--------------------------------------------------------------------------*
      80             :  * ivas_mcmasa_ana_open()
      81             :  *
      82             :  *
      83             :  *--------------------------------------------------------------------------*/
      84             : 
      85           2 : ivas_error ivas_mcmasa_ana_open(
      86             :     MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */
      87             :     const AUDIO_CONFIG inConfig,   /* i  :   Input config             */
      88             :     int32_t input_Fs               /* i  :   Sampling frequency       */
      89             : )
      90             : {
      91             :     int16_t i, j;
      92             :     MCMASA_ANA_HANDLE hMcMasa;
      93             :     float ls_azimuth[MCMASA_MAX_ANA_CHANS];
      94             :     float ls_elevation[MCMASA_MAX_ANA_CHANS];
      95             :     float ls_azimuth_even[MCMASA_MAX_ANA_CHANS];
      96             :     int16_t nchan_inp;
      97             :     int16_t numAnalysisChannels;
      98             :     float left_min, right_min, azi_diff;
      99             :     int16_t maxBin, input_frame;
     100             :     ivas_error error;
     101             : 
     102           2 :     error = IVAS_ERR_OK;
     103             : 
     104           2 :     if ( ( hMcMasa = (MCMASA_ANA_HANDLE) malloc( sizeof( MCMASA_ANA_DATA ) ) ) == NULL )
     105             :     {
     106           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     107             :     }
     108             : 
     109           2 :     if ( inConfig == IVAS_AUDIO_CONFIG_5_1 )
     110             :     {
     111           0 :         nchan_inp = 6;
     112           0 :         mvr2r( ls_azimuth_CICP6, ls_azimuth, nchan_inp - 1 );
     113           0 :         mvr2r( ls_elevation_CICP6, ls_elevation, nchan_inp - 1 );
     114           0 :         hMcMasa->numHorizontalChannels = 5;
     115           0 :         hMcMasa->isHorizontalSetup = 1;
     116             :     }
     117           2 :     else if ( inConfig == IVAS_AUDIO_CONFIG_7_1 )
     118             :     {
     119           0 :         nchan_inp = 8;
     120           0 :         mvr2r( ls_azimuth_CICP12, ls_azimuth, nchan_inp - 1 );
     121           0 :         mvr2r( ls_elevation_CICP12, ls_elevation, nchan_inp - 1 );
     122           0 :         hMcMasa->numHorizontalChannels = 7;
     123           0 :         hMcMasa->isHorizontalSetup = 1;
     124             :     }
     125           2 :     else if ( inConfig == IVAS_AUDIO_CONFIG_5_1_2 )
     126             :     {
     127           0 :         nchan_inp = 8;
     128           0 :         mvr2r( ls_azimuth_CICP14, ls_azimuth, nchan_inp - 1 );
     129           0 :         mvr2r( ls_elevation_CICP14, ls_elevation, nchan_inp - 1 );
     130           0 :         hMcMasa->numHorizontalChannels = 5;
     131           0 :         hMcMasa->isHorizontalSetup = 0;
     132             :     }
     133           2 :     else if ( inConfig == IVAS_AUDIO_CONFIG_5_1_4 )
     134             :     {
     135           0 :         nchan_inp = 10;
     136           0 :         mvr2r( ls_azimuth_CICP16, ls_azimuth, nchan_inp - 1 );
     137           0 :         mvr2r( ls_elevation_CICP16, ls_elevation, nchan_inp - 1 );
     138           0 :         hMcMasa->numHorizontalChannels = 5;
     139           0 :         hMcMasa->isHorizontalSetup = 0;
     140             :     }
     141             :     else
     142             :     {
     143           2 :         nchan_inp = 12;
     144           2 :         mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
     145           2 :         mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
     146           2 :         hMcMasa->numHorizontalChannels = 7;
     147           2 :         hMcMasa->isHorizontalSetup = 0;
     148             :     }
     149             : 
     150           2 :     numAnalysisChannels = nchan_inp - 1;
     151             : 
     152             :     /* Determine the number of bands */
     153           2 :     hMcMasa->nbands = MASA_FREQUENCY_BANDS;
     154             : 
     155             :     /* Determine band grouping */
     156           2 :     mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
     157             : 
     158           2 :     maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
     159          48 :     for ( i = 1; i < hMcMasa->nbands + 1; i++ )
     160             :     {
     161          48 :         if ( hMcMasa->band_grouping[i] >= maxBin )
     162             :         {
     163           2 :             hMcMasa->band_grouping[i] = maxBin;
     164           2 :             hMcMasa->nbands = i;
     165           2 :             break;
     166             :         }
     167             :     }
     168             : 
     169             :     /* Determine block grouping */
     170           2 :     mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     171             : 
     172             :     /* open/initialize CLDFB */
     173           2 :     hMcMasa->num_Cldfb_instances = numAnalysisChannels;
     174          24 :     for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
     175             :     {
     176          22 :         if ( ( error = openCldfb( &( hMcMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK )
     177             :         {
     178           0 :             return error;
     179             :         }
     180             :     }
     181             : 
     182             :     /* intensity 3-dim */
     183           8 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     184             :     {
     185           6 :         if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL )
     186             :         {
     187           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     188             :         }
     189             : 
     190          30 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     191             :         {
     192          24 :             if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
     193             :             {
     194           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     195             :             }
     196          24 :             set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
     197             :         }
     198             :     }
     199             : 
     200           8 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     201             :     {
     202         198 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     203             :         {
     204         192 :             if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
     205             :             {
     206           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     207             :             }
     208         192 :             set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
     209             :         }
     210             :     }
     211             : 
     212          66 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     213             :     {
     214          64 :         if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL )
     215             :         {
     216           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) );
     217             :         }
     218          64 :         set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
     219             :     }
     220             : 
     221           2 :     set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
     222             : 
     223           2 :     computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
     224             : 
     225           2 :     if ( !hMcMasa->isHorizontalSetup )
     226             :     {
     227           2 :         computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
     228             :     }
     229             : 
     230          24 :     for ( i = 0; i < numAnalysisChannels; i++ )
     231             :     {
     232          22 :         hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
     233          22 :         hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     234          22 :         hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
     235          22 :         hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     236             : 
     237          22 :         hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
     238          22 :         hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
     239          22 :         hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
     240          22 :         hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
     241             :     }
     242             : 
     243           2 :     mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
     244             : 
     245          16 :     for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     246             :     {
     247          14 :         left_min = 360.0f;
     248          14 :         right_min = -360.0f;
     249             : 
     250         112 :         for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
     251             :         {
     252          98 :             azi_diff = ls_azimuth[j] - ls_azimuth[i];
     253             : 
     254          98 :             if ( azi_diff > 180.0f )
     255             :             {
     256           6 :                 azi_diff -= 360.0f;
     257             :             }
     258          92 :             else if ( azi_diff < -180.0f )
     259             :             {
     260           6 :                 azi_diff += 360.0f;
     261             :             }
     262             : 
     263          98 :             if ( azi_diff < left_min && azi_diff > 0.0f )
     264             :             {
     265          24 :                 hMcMasa->leftNearest[i] = j;
     266          24 :                 left_min = azi_diff;
     267             :             }
     268             : 
     269          98 :             if ( azi_diff > right_min && azi_diff < 0.0f )
     270             :             {
     271          22 :                 hMcMasa->rightNearest[i] = j;
     272          22 :                 right_min = azi_diff;
     273             :             }
     274             :         }
     275             :     }
     276             : 
     277           2 :     hMcMasa->prevMultiChEne = 0.0f;
     278           2 :     hMcMasa->prevDownmixEne = 0.0f;
     279           2 :     hMcMasa->prevEQ = 1.0f;
     280           2 :     input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
     281        1922 :     for ( i = 0; i < input_frame; i++ )
     282             :     {
     283        1920 :         hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
     284             :     }
     285             : 
     286           2 :     hMcMasa->index_buffer_intensity = 0;
     287             : 
     288           2 :     if ( ( hMcMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
     289             :     {
     290           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     291             :     }
     292             : 
     293           2 :     if ( ( hMcMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
     294             :     {
     295           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     296             :     }
     297           2 :     generate_gridEq( hMcMasa->sph_grid16 );
     298             : 
     299           2 :     ( *hMcMasaPtr ) = hMcMasa;
     300             : 
     301           2 :     return error;
     302             : }
     303             : 
     304             : 
     305             : /*--------------------------------------------------------------------------*
     306             :  * ivas_mcmasa_ana_close()
     307             :  *
     308             :  *
     309             :  *--------------------------------------------------------------------------*/
     310             : 
     311        1316 : void ivas_mcmasa_ana_close(
     312             :     MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle   */
     313             : )
     314             : {
     315             :     int16_t i, j;
     316             : 
     317        1316 :     if ( hMcMasa == NULL || *hMcMasa == NULL )
     318             :     {
     319        1314 :         return;
     320             :     }
     321             : 
     322          24 :     for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
     323             :     {
     324          22 :         deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
     325             :     }
     326             : 
     327             :     /* intensity 3-dim */
     328           8 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     329             :     {
     330          30 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     331             :         {
     332          24 :             free( ( *hMcMasa )->direction_vector_m[i][j] );
     333          24 :             ( *hMcMasa )->direction_vector_m[i][j] = NULL;
     334             :         }
     335             : 
     336         198 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     337             :         {
     338         192 :             free( ( *hMcMasa )->buffer_intensity_real[i][j] );
     339         192 :             ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
     340             :         }
     341             : 
     342           6 :         free( ( *hMcMasa )->direction_vector_m[i] );
     343           6 :         ( *hMcMasa )->direction_vector_m[i] = NULL;
     344             :     }
     345             : 
     346          66 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     347             :     {
     348          64 :         free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
     349          64 :         ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
     350             :     }
     351             : 
     352           2 :     free( ( *hMcMasa )->hMasaOut );
     353           2 :     ( *hMcMasa )->hMasaOut = NULL;
     354           2 :     free( ( *hMcMasa )->sph_grid16 );
     355           2 :     ( *hMcMasa )->sph_grid16 = NULL;
     356             : 
     357           2 :     free( ( *hMcMasa ) );
     358           2 :     ( *hMcMasa ) = NULL;
     359             : 
     360           2 :     return;
     361             : }
     362             : 
     363             : 
     364             : /*--------------------------------------------------------------------------*
     365             :  * ivas_mcmasa_ana()
     366             :  *
     367             :  * Multichannel MASA analysis
     368             :  *--------------------------------------------------------------------------*/
     369             : 
     370         300 : void ivas_mcmasa_ana(
     371             :     MCMASA_ANA_HANDLE hMcMasa,     /* i/o: McMASA encoder handle           */
     372             :     float data_f[][L_FRAME48k],    /* i/o: Input / transport audio signals */
     373             :     const int16_t input_frame,     /* i  : Input frame size                */
     374             :     const int16_t nchan_transport, /* i  : Number of transport channels    */
     375             :     const int16_t nchan_inp        /* i  : Number of input channels        */
     376             : )
     377             : {
     378             :     int16_t i;
     379             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     380             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     381             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     382             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     383             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     384             : 
     385             : 
     386             :     /* Sum center and LFE, move surround channels */
     387         300 :     v_add( data_f[2], data_f[3], data_f[2], input_frame );
     388        2700 :     for ( i = 4; i < nchan_inp; i++ )
     389             :     {
     390        2400 :         mvr2r( data_f[i], data_f[i - 1], input_frame );
     391             :     }
     392             : 
     393             :     /* Analysis */
     394         300 :     ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp );
     395             : 
     396             :     /* Create MASA metadata buffer from the estimated values */
     397         300 :     ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
     398             : 
     399             :     /* Downmix */
     400         300 :     ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
     401             : 
     402         300 :     return;
     403             : }
     404             : 
     405             : 
     406             : /*--------------------------------------------------------------------------*
     407             :  * Local functions
     408             :  *--------------------------------------------------------------------------*/
     409             : 
     410             : /* Estimate metadata parameters for McMASA */
     411         300 : void ivas_mcmasa_param_est_ana(
     412             :     MCMASA_ANA_HANDLE hMcMasa,                                                     /* i  : McMASA analyzer structure       */
     413             :     float data_f[][L_FRAME48k],                                                    /* i  : Audio frame in MC-format        */
     414             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* o  : Estimated elevation             */
     415             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* o  : Estimated azimuth               */
     416             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],          /* o  : Estimated direct-to-total ratio */
     417             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],      /* o  : Estimated spread coherence      */
     418             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o  : Estimated surround coherence    */
     419             :     const int16_t input_frame,                                                     /* i  : Input frame size                */
     420             :     const int16_t nchan_inp                                                        /* i  : Number of input channels        */
     421             : )
     422             : {
     423             :     float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
     424             :     int16_t ts, i, j, d;
     425             :     int16_t num_freq_bins, num_freq_bands, index;
     426             :     float dir_v[DIRAC_NUM_DIMS];
     427             :     int16_t l_ts;
     428             :     float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     429             :     float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     430             :     float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     431             :     float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     432             :     float FoaEven_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     433             :     float FoaEven_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     434             :     float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     435             :     float intensity_even_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     436             :     float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     437             :     float diffuseness_vector[MASA_FREQUENCY_BANDS];
     438             :     float vertical_diffuseness_vector[MASA_FREQUENCY_BANDS];
     439             :     float diffuseness_m[MASA_FREQUENCY_BANDS];
     440             :     float coherentEnergyRatio[MASA_FREQUENCY_BANDS];
     441             :     int16_t band_m_idx, block_m_idx;
     442             :     float renormalization_factor_diff[MASA_FREQUENCY_BANDS];
     443             :     float norm_tmp;
     444             :     int16_t mrange[2], brange[2];
     445             :     CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
     446             :     float absCOVls[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
     447             :     float lsEnergy[MCMASA_MAX_ANA_CHANS];
     448             :     float lsEnergySum, maxEne;
     449             :     int16_t loudestCh;
     450             :     float surrCoh, tempCoh, tempCoh2;
     451             :     int16_t i1, i2, i3;
     452             :     float angleDist, minAngleDist;
     453             :     float currentAzi;
     454             :     float lsEnergyRelation;
     455             :     float tempLsEnergyRelation;
     456             :     float stereoness, cohwideness, spreadCoh;
     457             :     float stereoRatio, cohPanRatio;
     458             :     float stereoCoh, cohPanCoh, cohRatio;
     459             :     int16_t numAnalysisChannels;
     460             : 
     461         300 :     num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
     462         300 :     num_freq_bands = hMcMasa->nbands;
     463         300 :     l_ts = input_frame / CLDFB_NO_COL_MAX;
     464         300 :     numAnalysisChannels = nchan_inp - 1;
     465             : 
     466             :     /* do processing over all CLDFB time slots */
     467        1500 :     for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     468             :     {
     469        1200 :         mrange[0] = hMcMasa->block_grouping[block_m_idx];
     470        1200 :         mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
     471             : 
     472       30000 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     473             :         {
     474       28800 :             hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
     475       28800 :             hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
     476       28800 :             hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0;
     477             :         }
     478             : 
     479             :         /* Need to initialize renormalization_factors, and variables to be normalized */
     480        1200 :         set_zero( renormalization_factor_diff, hMcMasa->nbands );
     481        1200 :         set_zero( diffuseness_m, hMcMasa->nbands );
     482        1200 :         set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
     483             : 
     484             :         /* Reset variable */
     485       30000 :         for ( i = 0; i < hMcMasa->nbands; i++ )
     486             :         {
     487      345600 :             for ( j = 0; j < numAnalysisChannels; j++ )
     488             :             {
     489      316800 :                 set_zero( COVls[i].xr[j], numAnalysisChannels );
     490      316800 :                 set_zero( COVls[i].xi[j], numAnalysisChannels );
     491             :             }
     492             :         }
     493             : 
     494        6000 :         for ( ts = mrange[0]; ts < mrange[1]; ts++ )
     495             :         {
     496       57600 :             for ( i = 0; i < numAnalysisChannels; i++ )
     497             :             {
     498       52800 :                 cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hMcMasa->cldfbAnaEnc[i] );
     499             :             }
     500             : 
     501             :             /* Compute channel-based energy for metadata processing */
     502      120000 :             for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
     503             :             {
     504      115200 :                 brange[0] = hMcMasa->band_grouping[band_m_idx];
     505      115200 :                 brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
     506      403200 :                 for ( j = brange[0]; j < brange[1]; j++ )
     507             :                 {
     508     3456000 :                     for ( i = 0; i < numAnalysisChannels; i++ )
     509             :                     {
     510     3168000 :                         hMcMasa->energy[block_m_idx][band_m_idx] += Chnl_RealBuffer[i][j] * Chnl_RealBuffer[i][j] + Chnl_ImagBuffer[i][j] * Chnl_ImagBuffer[i][j];
     511             :                     }
     512             :                 }
     513             :             }
     514             : 
     515             :             /* Compute covariance matrix */
     516      120000 :             for ( i = 0; i < num_freq_bands; i++ )
     517             :             {
     518      115200 :                 brange[0] = hMcMasa->band_grouping[i];
     519      115200 :                 brange[1] = hMcMasa->band_grouping[i + 1];
     520      403200 :                 for ( j = brange[0]; j < brange[1]; j++ )
     521             :                 {
     522      288000 :                     compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
     523             :                 }
     524             :             }
     525             : 
     526             :             /* Compute standard FOA */
     527             :             /* W */
     528        4800 :             v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
     529        4800 :             v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
     530       48000 :             for ( i = 2; i < numAnalysisChannels; i++ )
     531             :             {
     532       43200 :                 v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
     533       43200 :                 v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
     534             :             }
     535             : 
     536             :             /* Y */
     537        4800 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
     538        4800 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
     539       52800 :             for ( i = 1; i < numAnalysisChannels; i++ )
     540             :             {
     541       48000 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
     542       48000 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
     543             :             }
     544             : 
     545             :             /* Z */
     546        4800 :             if ( hMcMasa->isHorizontalSetup )
     547             :             {
     548             :                 /* Set zero for horizontal setups */
     549           0 :                 set_zero( Foa_RealBuffer[2], num_freq_bins );
     550           0 :                 set_zero( Foa_ImagBuffer[2], num_freq_bins );
     551             :             }
     552             :             else
     553             :             {
     554        4800 :                 v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
     555        4800 :                 v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
     556       52800 :                 for ( i = 1; i < numAnalysisChannels; i++ )
     557             :                 {
     558       48000 :                     v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
     559       48000 :                     v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
     560             :                 }
     561             :             }
     562             : 
     563             :             /* X */
     564        4800 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
     565        4800 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
     566       52800 :             for ( i = 1; i < numAnalysisChannels; i++ )
     567             :             {
     568       48000 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
     569       48000 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins );
     570             :             }
     571             : 
     572             :             /* Compute even FOA */
     573             :             /* W */
     574        4800 :             mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
     575        4800 :             mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
     576             : 
     577             :             /* Y */
     578        4800 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
     579        4800 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
     580       52800 :             for ( i = 1; i < numAnalysisChannels; i++ )
     581             :             {
     582       48000 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
     583       48000 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_ImagBuffer[1], num_freq_bins );
     584             :             }
     585             : 
     586             :             /* Z (even setups are handled as horizontal) */
     587        4800 :             set_zero( FoaEven_RealBuffer[2], num_freq_bins );
     588        4800 :             set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
     589             : 
     590             :             /* X */
     591        4800 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
     592        4800 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
     593       52800 :             for ( i = 1; i < numAnalysisChannels; i++ )
     594             :             {
     595       48000 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
     596       48000 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
     597             :             }
     598             : 
     599             :             /* Direction estimation */
     600        4800 :             computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
     601        4800 :             computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] );
     602             : 
     603             :             /* Power and intensity estimation for diffuseness */
     604        4800 :             computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
     605        4800 :             computeReferencePower_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, reference_power[ts], num_freq_bands );
     606             : 
     607             :             /* Fill buffers of length "averaging_length" time slots for intensity and energy */
     608        4800 :             hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
     609        4800 :             index = hMcMasa->index_buffer_intensity;
     610       19200 :             for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     611             :             {
     612             :                 /* only real part needed */
     613       14400 :                 mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
     614             :             }
     615        4800 :             mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
     616             : 
     617        4800 :             computeDiffuseness( hMcMasa->buffer_intensity_real, hMcMasa->buffer_energy, num_freq_bands, diffuseness_vector );
     618             : 
     619             :             /* Compute vertical diffuseness, and tune original diffuseness if needed */
     620        4800 :             if ( !hMcMasa->isHorizontalSetup )
     621             :             {
     622        4800 :                 mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
     623        4800 :                 computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
     624        4800 :                 v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
     625             :             }
     626             : 
     627      120000 :             for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     628             :             {
     629      115200 :                 norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
     630             : 
     631      115200 :                 hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
     632      115200 :                 hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
     633      115200 :                 hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
     634             : 
     635      115200 :                 diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
     636      115200 :                 renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
     637             :             }
     638             :         }
     639             : 
     640       30000 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     641             :         {
     642      115200 :             for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
     643             :             {
     644       86400 :                 dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
     645             :             }
     646       28800 :             ivas_qmetadata_direction_vector_to_azimuth_elevation( dir_v, &azimuth_m_values[block_m_idx][band_m_idx], &elevation_m_values[block_m_idx][band_m_idx] );
     647             :         }
     648             : 
     649             :         /* Coherence processing */
     650       30000 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     651             :         {
     652             :             /* Compute absolute values */
     653      345600 :             for ( i = 0; i < numAnalysisChannels; i++ )
     654             :             {
     655     2217600 :                 for ( j = i; j < numAnalysisChannels; j++ )
     656             :                 {
     657     1900800 :                     absCOVls[i][j] = sqrtf( ( COVls[band_m_idx].xr[i][j] * COVls[band_m_idx].xr[i][j] + COVls[band_m_idx].xi[i][j] * COVls[band_m_idx].xi[i][j] ) );
     658             :                 }
     659      316800 :                 lsEnergy[i] = absCOVls[i][i];
     660             :             }
     661             : 
     662             :             /* Find loudest channel */
     663       28800 :             maxEne = lsEnergy[0];
     664       28800 :             loudestCh = 0;
     665      316800 :             for ( i = 1; i < numAnalysisChannels; i++ )
     666             :             {
     667      288000 :                 if ( lsEnergy[i] > maxEne )
     668             :                 {
     669       54980 :                     maxEne = lsEnergy[i];
     670       54980 :                     loudestCh = i;
     671             :                 }
     672             :             }
     673             : 
     674             :             /* Compute surrounding coherence */
     675       28800 :             surrCoh = 1.0f;
     676      345600 :             for ( i = 0; i < numAnalysisChannels; i++ )
     677             :             {
     678      316800 :                 if ( i != loudestCh )
     679             :                 {
     680      288000 :                     if ( i < loudestCh )
     681             :                     {
     682      175770 :                         i1 = i;
     683      175770 :                         i2 = loudestCh;
     684             :                     }
     685             :                     else
     686             :                     {
     687      112230 :                         i1 = loudestCh;
     688      112230 :                         i2 = i;
     689             :                     }
     690      288000 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
     691      288000 :                     surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
     692             :                 }
     693             :             }
     694       28800 :             surrCoh = surrCoh * surrCoh;
     695       28800 :             surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
     696       28800 :             surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
     697             : 
     698             :             /* Compute spread coherence */
     699       28800 :             if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
     700             :             {
     701        2130 :                 minAngleDist = 180.0f;
     702        2130 :                 i1 = 0;
     703        2130 :                 currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
     704       17040 :                 for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     705             :                 {
     706       14910 :                     angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
     707       14910 :                     if ( angleDist > 180.0f )
     708             :                     {
     709         384 :                         angleDist = fabsf( angleDist - 360.0f );
     710             :                     }
     711       14910 :                     if ( angleDist < minAngleDist )
     712             :                     {
     713        4768 :                         minAngleDist = angleDist;
     714        4768 :                         i1 = i;
     715             :                     }
     716             :                 }
     717        2130 :                 i2 = hMcMasa->leftNearest[i1];
     718        2130 :                 i3 = hMcMasa->rightNearest[i1];
     719             : 
     720        2130 :                 if ( i2 < i3 )
     721             :                 {
     722        1688 :                     stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     723             :                 }
     724             :                 else
     725             :                 {
     726         442 :                     stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     727             :                 }
     728        2130 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
     729        2130 :                 stereoness = stereoCoh * lsEnergyRelation;
     730             : 
     731        2130 :                 if ( i1 < i2 )
     732             :                 {
     733         744 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     734             :                 }
     735             :                 else
     736             :                 {
     737        1386 :                     tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     738             :                 }
     739        2130 :                 if ( i1 < i3 )
     740             :                 {
     741         680 :                     tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     742             :                 }
     743             :                 else
     744             :                 {
     745        1450 :                     tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     746             :                 }
     747        2130 :                 cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
     748        2130 :                 lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
     749        2130 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
     750        2130 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     751        2130 :                 tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
     752        2130 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     753        2130 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
     754        2130 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     755        2130 :                 cohwideness = cohPanCoh * lsEnergyRelation;
     756             : 
     757        2130 :                 spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
     758        2130 :                 if ( spreadCoh > 0.5f )
     759             :                 {
     760         688 :                     if ( cohwideness > stereoness )
     761             :                     {
     762         218 :                         tempCoh = stereoness - ( cohwideness - 0.5f );
     763         218 :                         spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
     764             :                     }
     765             :                 }
     766        2130 :                 spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
     767        2130 :                 spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
     768             : 
     769             :                 /* Compute energy ratio tuning parameter */
     770        2130 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
     771        2130 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     772        2130 :                 stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
     773             : 
     774        2130 :                 lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     775        2130 :                 cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
     776             : 
     777        2130 :                 cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
     778        2130 :                 cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
     779        2130 :                 cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
     780             :             }
     781             :             else /* Otherwise, set spread coherence to zero */
     782             :             {
     783       26670 :                 spreadCoh = 0.0f;
     784       26670 :                 cohRatio = 0.0f;
     785       26670 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
     786             :             }
     787             : 
     788             :             /* Store values */
     789       28800 :             spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
     790       28800 :             surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
     791       28800 :             coherentEnergyRatio[band_m_idx] = cohRatio;
     792             :         }
     793             : 
     794             :         /* Determine energy ratios */
     795       30000 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     796             :         {
     797       28800 :             if ( renormalization_factor_diff[band_m_idx] > EPSILON )
     798             :             {
     799       28800 :                 diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
     800             :             }
     801             :             else
     802             :             {
     803           0 :                 diffuseness_m[band_m_idx] = 0.0f;
     804             :             }
     805             : 
     806       28800 :             energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
     807       28800 :             energyRatio[block_m_idx][band_m_idx] = ( energyRatio[block_m_idx][band_m_idx] > coherentEnergyRatio[band_m_idx] ) ? energyRatio[block_m_idx][band_m_idx] : coherentEnergyRatio[band_m_idx];
     808             :         }
     809             :     }
     810             : 
     811         300 :     return;
     812             : }
     813             : 
     814             : 
     815             : /* Compute downmix */
     816         300 : static void ivas_mcmasa_dmx(
     817             :     MCMASA_ANA_HANDLE hMcMasa,
     818             :     float data_f[][L_FRAME48k],
     819             :     const int16_t input_frame,
     820             :     const int16_t nchan_transport,
     821             :     const int16_t nchan_inp )
     822             : {
     823             :     int16_t i, j;
     824             :     int16_t numAnalysisChannels;
     825             :     float dmx_c;
     826             :     float multiChEne, downmixEne;
     827             :     float prevEQ, currEQ, instEQ;
     828             :     float alpha;
     829             : 
     830         300 :     numAnalysisChannels = nchan_inp - 1;
     831             : 
     832         300 :     multiChEne = 0.0f;
     833        3600 :     for ( j = 0; j < numAnalysisChannels; j++ )
     834             :     {
     835     3171300 :         for ( i = 0; i < input_frame; i++ )
     836             :         {
     837     3168000 :             multiChEne += data_f[j][i] * data_f[j][i];
     838             :         }
     839             :     }
     840             : 
     841         300 :     if ( nchan_transport == 2 )
     842             :     {
     843             :         int16_t numSideChannels; /* Channels other than left, right, center */
     844             :         int16_t leftIndex, rightIndex;
     845             : 
     846         300 :         numSideChannels = numAnalysisChannels / 2 - 1;
     847        1500 :         for ( j = 0; j < numSideChannels; j++ )
     848             :         {
     849        1200 :             leftIndex = j * 2 + 3;
     850        1200 :             rightIndex = j * 2 + 4;
     851             : 
     852     1153200 :             for ( i = 0; i < input_frame; i++ )
     853             :             {
     854     1152000 :                 data_f[0][i] += data_f[leftIndex][i];
     855     1152000 :                 data_f[1][i] += data_f[rightIndex][i];
     856             :             }
     857             :         }
     858             : 
     859      288300 :         for ( i = 0; i < input_frame; i++ )
     860             :         {
     861      288000 :             dmx_c = INV_SQRT2 * data_f[2][i];
     862      288000 :             data_f[0][i] += dmx_c;
     863      288000 :             data_f[1][i] += dmx_c;
     864             :         }
     865             :     }
     866           0 :     else if ( nchan_transport == 1 )
     867             :     {
     868           0 :         for ( i = 0; i < input_frame; i++ )
     869             :         {
     870           0 :             for ( j = 1; j < numAnalysisChannels; j++ )
     871             :             {
     872           0 :                 data_f[0][i] += data_f[j][i];
     873             :             }
     874             :         }
     875             :     }
     876             : 
     877         300 :     downmixEne = 0.0f;
     878         900 :     for ( j = 0; j < nchan_transport; j++ )
     879             :     {
     880      576600 :         for ( i = 0; i < input_frame; i++ )
     881             :         {
     882      576000 :             downmixEne += data_f[j][i] * data_f[j][i];
     883             :         }
     884             :     }
     885             : 
     886         300 :     alpha = 0.1f;
     887         300 :     hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
     888         300 :     hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
     889             : 
     890         300 :     prevEQ = hMcMasa->prevEQ;
     891         300 :     currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
     892         300 :     hMcMasa->prevEQ = currEQ;
     893             : 
     894      288300 :     for ( i = 0; i < input_frame; i++ )
     895             :     {
     896      288000 :         instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
     897      864000 :         for ( j = 0; j < nchan_transport; j++ )
     898             :         {
     899      576000 :             data_f[j][i] *= instEQ;
     900             :         }
     901             :     }
     902             : 
     903         300 :     return;
     904             : }
     905             : 
     906             : 
     907             : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
     908      288000 : static void compute_cov_mtx(
     909             :     float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, real, s[ch][freq]                         */
     910             :     float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, imag, s[ch][freq]                         */
     911             :     const int16_t freq,                                    /* i  : Freq to process                                         */
     912             :     const int16_t N,                                       /* i  : Number of channels                                      */
     913             :     CovarianceMatrix *COVls                                /* o  : Output matrix, contains upper part of cov mtx           */
     914             : )
     915             : {
     916             :     int16_t i, j;
     917             :     float a, b, c, d;
     918             : 
     919     3456000 :     for ( i = 0; i < N; i++ )
     920             :     {
     921     3168000 :         a = sr[i][freq];
     922     3168000 :         b = si[i][freq];
     923    22176000 :         for ( j = i; j < N; j++ )
     924             :         {
     925    19008000 :             c = sr[j][freq];
     926    19008000 :             d = si[j][freq];
     927    19008000 :             COVls->xr[i][j] += a * c + b * d;
     928    19008000 :             COVls->xi[i][j] += b * c - a * d;
     929             :         }
     930             :     }
     931             : 
     932      288000 :     return;
     933             : }
     934             : 
     935             : /*-------------------------------------------------------------------------
     936             :  * computeVerticalDiffuseness()
     937             :  *
     938             :  *
     939             :  *------------------------------------------------------------------------*/
     940             : 
     941        4800 : static void computeVerticalDiffuseness(
     942             :     float **buffer_intensity,     /* i  : Intensity vectors           */
     943             :     const float *buffer_energy,   /* i  : Energy                      */
     944             :     const int16_t num_freq_bands, /* i  : Number of frequency bands   */
     945             :     float *diffuseness            /* o  : Estimated diffuseness       */
     946             : )
     947             : {
     948             :     float intensity_slow[MASA_FREQUENCY_BANDS];
     949             :     float intensity_slow_abs[MASA_FREQUENCY_BANDS];
     950             :     float energy_slow[MASA_FREQUENCY_BANDS];
     951             :     int16_t i, k;
     952        4800 :     float tmp = 0;
     953             :     const float *p_tmp_c;
     954             : 
     955             :     /* Set variables to zero */
     956        4800 :     set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
     957        4800 :     set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
     958             : 
     959      158400 :     for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
     960             :     {
     961             :         /* Energy slow */
     962      153600 :         p_tmp_c = buffer_energy + i * num_freq_bands;
     963     3840000 :         for ( k = 0; k < num_freq_bands; k++ )
     964             :         {
     965     3686400 :             energy_slow[k] += *( p_tmp_c++ );
     966             :         }
     967             : 
     968             :         /* Intensity slow */
     969     3840000 :         for ( k = 0; k < num_freq_bands; k++ )
     970             :         {
     971     3686400 :             intensity_slow[k] += buffer_intensity[i][k];
     972             :         }
     973             :     }
     974             : 
     975             :     /* Compute absolute value */
     976      120000 :     for ( k = 0; k < num_freq_bands; k++ )
     977             :     {
     978      115200 :         intensity_slow_abs[k] = fabsf( intensity_slow[k] );
     979             :     }
     980             : 
     981             :     /* Compute Diffuseness */
     982      120000 :     for ( i = 0; i < num_freq_bands; ++i )
     983             :     {
     984      115200 :         tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
     985      115200 :         tmp = ( tmp - VERTICAL_ENERGY_RATIO_OFFSET ) / ( 1.0f - VERTICAL_ENERGY_RATIO_OFFSET ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
     986      115200 :         tmp = 1.0f - tmp;
     987      115200 :         diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
     988             :     }
     989             : 
     990        4800 :     return;
     991             : }
     992             : 
     993             : 
     994           4 : static void computeEvenLayout(
     995             :     const float *ls_azimuth,
     996             :     float *ls_azimuth_even,
     997             :     const int16_t numChannels )
     998             : {
     999             :     int16_t i;
    1000             :     int16_t j;
    1001             :     float ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
    1002             :     float ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
    1003             :     int16_t ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
    1004             :     float smallestAzimuth;
    1005             :     int16_t smallestAzimuthIndex;
    1006             :     float lsSpacing;
    1007             :     uint8_t oddLayout;
    1008             :     float startAzimuth;
    1009             :     int16_t numChannelsHalf;
    1010             : 
    1011           4 :     lsSpacing = 360.0f / (float) numChannels;
    1012           4 :     oddLayout = numChannels % 2;
    1013           4 :     numChannelsHalf = numChannels / 2;
    1014             : 
    1015           4 :     mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
    1016          26 :     for ( i = 0; i < numChannels; i++ )
    1017             :     {
    1018          22 :         smallestAzimuth = 1000.0f;
    1019          22 :         smallestAzimuthIndex = 0;
    1020         152 :         for ( j = 0; j < numChannels; j++ )
    1021             :         {
    1022         130 :             if ( ls_azimuth_temp[j] < smallestAzimuth )
    1023             :             {
    1024          42 :                 smallestAzimuth = ls_azimuth_temp[j];
    1025          42 :                 smallestAzimuthIndex = j;
    1026             :             }
    1027             :         }
    1028          22 :         ls_azimuth_order[i] = smallestAzimuthIndex;
    1029          22 :         ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
    1030             :     }
    1031             : 
    1032           4 :     if ( oddLayout )
    1033             :     {
    1034           2 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
    1035             :     }
    1036             :     else
    1037             :     {
    1038           2 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
    1039             :     }
    1040             : 
    1041          26 :     for ( i = 0; i < numChannels; i++ )
    1042             :     {
    1043          22 :         ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
    1044             :     }
    1045             : 
    1046          26 :     for ( i = 0; i < numChannels; i++ )
    1047             :     {
    1048          22 :         ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
    1049             :     }
    1050             : 
    1051           4 :     return;
    1052             : }
    1053             : 
    1054             : 
    1055             : /*-------------------------------------------------------------------------
    1056             :  * ivas_create_masa_out_meta()
    1057             :  *
    1058             :  *
    1059             :  *------------------------------------------------------------------------*/
    1060             : 
    1061         900 : void ivas_create_masa_out_meta(
    1062             :     MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta,                                  /* i/o: MASA metadata handle            */
    1063             :     SPHERICAL_GRID_DATA *Sph_Grid16,                                              /* i  : Spherical grid                  */
    1064             :     const int16_t nchan_transport,                                                /* i  : Number of transport channels    */
    1065             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],  /* i  : Estimated elevation             */
    1066             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],    /* i  : Estimated azimuth               */
    1067             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],         /* i  : Estimated direct-to-total ratio */
    1068             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* i  : Estimated spread coherence      */
    1069             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i  : Estimated surround coherence    */
    1070             : )
    1071             : {
    1072             :     int16_t i, sf, band;
    1073             :     uint8_t numFrequencyBands;
    1074             :     uint8_t numDirections;
    1075             :     uint16_t spherical_index;
    1076             : 
    1077         900 :     numDirections = 1;
    1078         900 :     numFrequencyBands = MASA_FREQUENCY_BANDS;
    1079             : 
    1080             :     /* Construct descriptive meta */
    1081        8100 :     for ( i = 0; i < 8; i++ )
    1082             :     {
    1083        7200 :         extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
    1084             :     }
    1085         900 :     extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
    1086         900 :     extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
    1087             :     /* Following correspond to "unknown" values */
    1088         900 :     extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
    1089         900 :     extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
    1090         900 :     extOutMeta->descriptiveMeta.channelAngle = 0x0u;
    1091         900 :     extOutMeta->descriptiveMeta.channelDistance = 0x0u;
    1092         900 :     extOutMeta->descriptiveMeta.channelLayout = 0x0u;
    1093             : 
    1094             :     /* Construct spatial metadata from estimated values */
    1095        4500 :     for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1096             :     {
    1097             :         /* Spherical index */
    1098       90000 :         for ( band = 0; band < numFrequencyBands; band++ )
    1099             :         {
    1100       86400 :             spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
    1101       86400 :             extOutMeta->directionIndex[0][sf][band] = spherical_index;
    1102       86400 :             extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
    1103             :         }
    1104             : 
    1105             :         /* Direct-to-total ratio */
    1106       90000 :         for ( band = 0; band < numFrequencyBands; band++ )
    1107             :         {
    1108       86400 :             extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1109       86400 :             extOutMeta->directToTotalRatio[1][sf][band] = 0;
    1110             :         }
    1111             : 
    1112             :         /* Spread coherence */
    1113       90000 :         for ( band = 0; band < numFrequencyBands; band++ )
    1114             :         {
    1115       86400 :             extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
    1116       86400 :             extOutMeta->spreadCoherence[1][sf][band] = 0;
    1117             :         }
    1118             : 
    1119             :         /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
    1120       90000 :         for ( band = 0; band < numFrequencyBands; band++ )
    1121             :         {
    1122       86400 :             extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1123             :         }
    1124             : 
    1125             :         /* Surround coherence */
    1126       90000 :         for ( band = 0; band < numFrequencyBands; band++ )
    1127             :         {
    1128       86400 :             extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
    1129             :         }
    1130             :     }
    1131             : 
    1132         900 :     return;
    1133             : }

Generated by: LCOV version 1.14