LCOV - code coverage report
Current view: top level - lib_rend - ivas_mcmasa_ana.c (source / functions) Hit Total Coverage
Test: Coverage on main -- long test vectors @ 9b04ec3cb36f5e8dc438cf854fa3e349998fa1e9 Lines: 414 444 93.2 %
Date: 2025-10-31 05:43:07 Functions: 10 10 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           6 : 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           6 :     error = IVAS_ERR_OK;
     103             : 
     104           6 :     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           6 :     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           6 :     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           6 :     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           6 :     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           6 :         nchan_inp = 12;
     144           6 :         mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
     145           6 :         mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
     146           6 :         hMcMasa->numHorizontalChannels = 7;
     147           6 :         hMcMasa->isHorizontalSetup = 0;
     148             :     }
     149             : 
     150           6 :     numAnalysisChannels = nchan_inp - 1;
     151             : 
     152             :     /* Determine the number of bands */
     153           6 :     hMcMasa->nbands = MASA_FREQUENCY_BANDS;
     154             : 
     155             :     /* Determine band grouping */
     156           6 :     mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
     157             : 
     158           6 :     maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
     159         134 :     for ( i = 1; i < hMcMasa->nbands + 1; i++ )
     160             :     {
     161         134 :         if ( hMcMasa->band_grouping[i] >= maxBin )
     162             :         {
     163           6 :             hMcMasa->band_grouping[i] = maxBin;
     164           6 :             hMcMasa->nbands = i;
     165           6 :             break;
     166             :         }
     167             :     }
     168             : 
     169             :     /* Determine block grouping */
     170           6 :     mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     171             : 
     172             :     /* open/initialize CLDFB */
     173           6 :     hMcMasa->num_Cldfb_instances = numAnalysisChannels;
     174          72 :     for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
     175             :     {
     176          66 :         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          24 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     184             :     {
     185          18 :         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          90 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     191             :         {
     192          72 :             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          72 :             set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
     197             :         }
     198             :     }
     199             : 
     200          24 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     201             :     {
     202         594 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     203             :         {
     204         576 :             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         576 :             set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
     209             :         }
     210             :     }
     211             : 
     212         198 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     213             :     {
     214         192 :         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         192 :         set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
     219             :     }
     220             : 
     221           6 :     set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
     222             : 
     223           6 :     computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
     224             : 
     225           6 :     if ( !hMcMasa->isHorizontalSetup )
     226             :     {
     227           6 :         computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
     228             :     }
     229             : 
     230          72 :     for ( i = 0; i < numAnalysisChannels; i++ )
     231             :     {
     232          66 :         hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
     233          66 :         hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     234          66 :         hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
     235          66 :         hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     236             : 
     237          66 :         hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
     238          66 :         hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
     239          66 :         hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
     240          66 :         hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
     241             :     }
     242             : 
     243           6 :     mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
     244             : 
     245          48 :     for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     246             :     {
     247          42 :         left_min = 360.0f;
     248          42 :         right_min = -360.0f;
     249             : 
     250         336 :         for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
     251             :         {
     252         294 :             azi_diff = ls_azimuth[j] - ls_azimuth[i];
     253             : 
     254         294 :             if ( azi_diff > 180.0f )
     255             :             {
     256          18 :                 azi_diff -= 360.0f;
     257             :             }
     258         276 :             else if ( azi_diff < -180.0f )
     259             :             {
     260          18 :                 azi_diff += 360.0f;
     261             :             }
     262             : 
     263         294 :             if ( azi_diff < left_min && azi_diff > 0.0f )
     264             :             {
     265          72 :                 hMcMasa->leftNearest[i] = j;
     266          72 :                 left_min = azi_diff;
     267             :             }
     268             : 
     269         294 :             if ( azi_diff > right_min && azi_diff < 0.0f )
     270             :             {
     271          66 :                 hMcMasa->rightNearest[i] = j;
     272          66 :                 right_min = azi_diff;
     273             :             }
     274             :         }
     275             :     }
     276             : 
     277           6 :     hMcMasa->prevMultiChEne = 0.0f;
     278           6 :     hMcMasa->prevDownmixEne = 0.0f;
     279           6 :     hMcMasa->prevEQ = 1.0f;
     280           6 :     input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
     281        3846 :     for ( i = 0; i < input_frame; i++ )
     282             :     {
     283        3840 :         hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
     284             :     }
     285             : 
     286           6 :     hMcMasa->index_buffer_intensity = 0;
     287             : 
     288           6 :     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           6 :     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           6 :     generate_gridEq( hMcMasa->sph_grid16 );
     298             : 
     299           6 :     ( *hMcMasaPtr ) = hMcMasa;
     300             : 
     301           6 :     return error;
     302             : }
     303             : 
     304             : 
     305             : /*--------------------------------------------------------------------------*
     306             :  * ivas_mcmasa_ana_close()
     307             :  *
     308             :  *
     309             :  *--------------------------------------------------------------------------*/
     310             : 
     311        4407 : void ivas_mcmasa_ana_close(
     312             :     MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle   */
     313             : )
     314             : {
     315             :     int16_t i, j;
     316             : 
     317        4407 :     if ( hMcMasa == NULL || *hMcMasa == NULL )
     318             :     {
     319        4401 :         return;
     320             :     }
     321             : 
     322          72 :     for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
     323             :     {
     324          66 :         deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
     325             :     }
     326             : 
     327             :     /* intensity 3-dim */
     328          24 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     329             :     {
     330          90 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     331             :         {
     332          72 :             free( ( *hMcMasa )->direction_vector_m[i][j] );
     333          72 :             ( *hMcMasa )->direction_vector_m[i][j] = NULL;
     334             :         }
     335             : 
     336         594 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     337             :         {
     338         576 :             free( ( *hMcMasa )->buffer_intensity_real[i][j] );
     339         576 :             ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
     340             :         }
     341             : 
     342          18 :         free( ( *hMcMasa )->direction_vector_m[i] );
     343          18 :         ( *hMcMasa )->direction_vector_m[i] = NULL;
     344             :     }
     345             : 
     346         198 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     347             :     {
     348         192 :         free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
     349         192 :         ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
     350             :     }
     351             : 
     352           6 :     free( ( *hMcMasa )->hMasaOut );
     353           6 :     ( *hMcMasa )->hMasaOut = NULL;
     354           6 :     free( ( *hMcMasa )->sph_grid16 );
     355           6 :     ( *hMcMasa )->sph_grid16 = NULL;
     356             : 
     357           6 :     free( ( *hMcMasa ) );
     358           6 :     ( *hMcMasa ) = NULL;
     359             : 
     360           6 :     return;
     361             : }
     362             : 
     363             : 
     364             : /*--------------------------------------------------------------------------*
     365             :  * ivas_mcmasa_ana()
     366             :  *
     367             :  * Multichannel MASA analysis
     368             :  *--------------------------------------------------------------------------*/
     369             : 
     370         906 : 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         906 :     v_add( data_f[2], data_f[3], data_f[2], input_frame );
     388        8154 :     for ( i = 4; i < nchan_inp; i++ )
     389             :     {
     390        7248 :         mvr2r( data_f[i], data_f[i - 1], input_frame );
     391             :     }
     392             : 
     393             :     /* Analysis */
     394         906 :     ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp );
     395             : 
     396             :     /* Add zeros to higher bands in case of lower sampling rates */
     397         906 :     if ( hMcMasa->nbands < MASA_FREQUENCY_BANDS )
     398             :     {
     399         604 :         ivas_masa_zero_high_bands( hMcMasa->nbands, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
     400             :     }
     401             : 
     402             :     /* Create MASA metadata buffer from the estimated values */
     403         906 :     ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence );
     404             : 
     405             :     /* Downmix */
     406         906 :     ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
     407             : 
     408         906 :     return;
     409             : }
     410             : 
     411             : 
     412             : /*--------------------------------------------------------------------------*
     413             :  * Local functions
     414             :  *--------------------------------------------------------------------------*/
     415             : 
     416             : /* Estimate metadata parameters for McMASA */
     417         906 : void ivas_mcmasa_param_est_ana(
     418             :     MCMASA_ANA_HANDLE hMcMasa,                                                     /* i  : McMASA analyzer structure       */
     419             :     float data_f[][L_FRAME48k],                                                    /* i  : Audio frame in MC-format        */
     420             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   /* o  : Estimated elevation             */
     421             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* o  : Estimated azimuth               */
     422             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],          /* o  : Estimated direct-to-total ratio */
     423             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],      /* o  : Estimated spread coherence      */
     424             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o  : Estimated surround coherence    */
     425             :     const int16_t input_frame,                                                     /* i  : Input frame size                */
     426             :     const int16_t nchan_inp                                                        /* i  : Number of input channels        */
     427             : )
     428             : {
     429             :     float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
     430             :     int16_t ts, i, j, d;
     431             :     int16_t num_freq_bins, num_freq_bands, index;
     432             :     float dir_v[DIRAC_NUM_DIMS];
     433             :     int16_t l_ts;
     434             :     float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     435             :     float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX];
     436             :     float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     437             :     float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     438             :     float FoaEven_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     439             :     float FoaEven_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     440             :     float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     441             :     float intensity_even_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     442             :     float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     443             :     float diffuseness_vector[MASA_FREQUENCY_BANDS];
     444             :     float vertical_diffuseness_vector[MASA_FREQUENCY_BANDS];
     445             :     float diffuseness_m[MASA_FREQUENCY_BANDS];
     446             :     float coherentEnergyRatio[MASA_FREQUENCY_BANDS];
     447             :     int16_t band_m_idx, block_m_idx;
     448             :     float renormalization_factor_diff[MASA_FREQUENCY_BANDS];
     449             :     float norm_tmp;
     450             :     int16_t mrange[2], brange[2];
     451             :     CovarianceMatrix COVls[MASA_FREQUENCY_BANDS];
     452             :     float absCOVls[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];
     453             :     float lsEnergy[MCMASA_MAX_ANA_CHANS];
     454             :     float lsEnergySum, maxEne;
     455             :     int16_t loudestCh;
     456             :     float surrCoh, tempCoh, tempCoh2;
     457             :     int16_t i1, i2, i3;
     458             :     float angleDist, minAngleDist;
     459             :     float currentAzi;
     460             :     float lsEnergyRelation;
     461             :     float tempLsEnergyRelation;
     462             :     float stereoness, cohwideness, spreadCoh;
     463             :     float stereoRatio, cohPanRatio;
     464             :     float stereoCoh, cohPanCoh, cohRatio;
     465             :     int16_t numAnalysisChannels;
     466             : 
     467         906 :     num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
     468         906 :     num_freq_bands = hMcMasa->nbands;
     469         906 :     l_ts = input_frame / CLDFB_NO_COL_MAX;
     470         906 :     numAnalysisChannels = nchan_inp - 1;
     471             : 
     472             :     /* do processing over all CLDFB time slots */
     473        4530 :     for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     474             :     {
     475        3624 :         mrange[0] = hMcMasa->block_grouping[block_m_idx];
     476        3624 :         mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
     477             : 
     478       84560 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     479             :         {
     480       80936 :             hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
     481       80936 :             hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
     482       80936 :             hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0;
     483             :         }
     484             : 
     485             :         /* Need to initialize renormalization_factors, and variables to be normalized */
     486        3624 :         set_zero( renormalization_factor_diff, hMcMasa->nbands );
     487        3624 :         set_zero( diffuseness_m, hMcMasa->nbands );
     488        3624 :         set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
     489             : 
     490             :         /* Reset variable */
     491       84560 :         for ( i = 0; i < hMcMasa->nbands; i++ )
     492             :         {
     493      971232 :             for ( j = 0; j < numAnalysisChannels; j++ )
     494             :             {
     495      890296 :                 set_zero( COVls[i].xr[j], numAnalysisChannels );
     496      890296 :                 set_zero( COVls[i].xi[j], numAnalysisChannels );
     497             :             }
     498             :         }
     499             : 
     500       18120 :         for ( ts = mrange[0]; ts < mrange[1]; ts++ )
     501             :         {
     502      173952 :             for ( i = 0; i < numAnalysisChannels; i++ )
     503             :             {
     504      159456 :                 cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Chnl_RealBuffer[i], Chnl_ImagBuffer[i], l_ts, hMcMasa->cldfbAnaEnc[i] );
     505             :             }
     506             : 
     507             :             /* Compute channel-based energy for metadata processing */
     508      338240 :             for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
     509             :             {
     510      323744 :                 brange[0] = hMcMasa->band_grouping[band_m_idx];
     511      323744 :                 brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
     512      903584 :                 for ( j = brange[0]; j < brange[1]; j++ )
     513             :                 {
     514     6958080 :                     for ( i = 0; i < numAnalysisChannels; i++ )
     515             :                     {
     516     6378240 :                         hMcMasa->energy[block_m_idx][band_m_idx] += Chnl_RealBuffer[i][j] * Chnl_RealBuffer[i][j] + Chnl_ImagBuffer[i][j] * Chnl_ImagBuffer[i][j];
     517             :                     }
     518             :                 }
     519             :             }
     520             : 
     521             :             /* Compute covariance matrix */
     522      338240 :             for ( i = 0; i < num_freq_bands; i++ )
     523             :             {
     524      323744 :                 brange[0] = hMcMasa->band_grouping[i];
     525      323744 :                 brange[1] = hMcMasa->band_grouping[i + 1];
     526      903584 :                 for ( j = brange[0]; j < brange[1]; j++ )
     527             :                 {
     528      579840 :                     compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
     529             :                 }
     530             :             }
     531             : 
     532             :             /* Compute standard FOA */
     533             :             /* W */
     534       14496 :             v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
     535       14496 :             v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
     536      144960 :             for ( i = 2; i < numAnalysisChannels; i++ )
     537             :             {
     538      130464 :                 v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
     539      130464 :                 v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
     540             :             }
     541             : 
     542             :             /* Y */
     543       14496 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
     544       14496 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
     545      159456 :             for ( i = 1; i < numAnalysisChannels; i++ )
     546             :             {
     547      144960 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
     548      144960 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
     549             :             }
     550             : 
     551             :             /* Z */
     552       14496 :             if ( hMcMasa->isHorizontalSetup )
     553             :             {
     554             :                 /* Set zero for horizontal setups */
     555           0 :                 set_zero( Foa_RealBuffer[2], num_freq_bins );
     556           0 :                 set_zero( Foa_ImagBuffer[2], num_freq_bins );
     557             :             }
     558             :             else
     559             :             {
     560       14496 :                 v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
     561       14496 :                 v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
     562      159456 :                 for ( i = 1; i < numAnalysisChannels; i++ )
     563             :                 {
     564      144960 :                     v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
     565      144960 :                     v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
     566             :                 }
     567             :             }
     568             : 
     569             :             /* X */
     570       14496 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
     571       14496 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
     572      159456 :             for ( i = 1; i < numAnalysisChannels; i++ )
     573             :             {
     574      144960 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
     575      144960 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins );
     576             :             }
     577             : 
     578             :             /* Compute even FOA */
     579             :             /* W */
     580       14496 :             mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
     581       14496 :             mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
     582             : 
     583             :             /* Y */
     584       14496 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
     585       14496 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
     586      159456 :             for ( i = 1; i < numAnalysisChannels; i++ )
     587             :             {
     588      144960 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
     589      144960 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_ImagBuffer[1], num_freq_bins );
     590             :             }
     591             : 
     592             :             /* Z (even setups are handled as horizontal) */
     593       14496 :             set_zero( FoaEven_RealBuffer[2], num_freq_bins );
     594       14496 :             set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
     595             : 
     596             :             /* X */
     597       14496 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
     598       14496 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
     599      159456 :             for ( i = 1; i < numAnalysisChannels; i++ )
     600             :             {
     601      144960 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
     602      144960 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
     603             :             }
     604             : 
     605             :             /* Direction estimation */
     606       14496 :             computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
     607       14496 :             computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] );
     608             : 
     609             :             /* Power and intensity estimation for diffuseness */
     610       14496 :             computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
     611       14496 :             computeReferencePower_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, reference_power[ts], num_freq_bands );
     612             : 
     613             :             /* Fill buffers of length "averaging_length" time slots for intensity and energy */
     614       14496 :             hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
     615       14496 :             index = hMcMasa->index_buffer_intensity;
     616       57984 :             for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     617             :             {
     618             :                 /* only real part needed */
     619       43488 :                 mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
     620             :             }
     621       14496 :             mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
     622             : 
     623       14496 :             computeDiffuseness( hMcMasa->buffer_intensity_real, hMcMasa->buffer_energy, num_freq_bands, diffuseness_vector );
     624             : 
     625             :             /* Compute vertical diffuseness, and tune original diffuseness if needed */
     626       14496 :             if ( !hMcMasa->isHorizontalSetup )
     627             :             {
     628       14496 :                 mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
     629       14496 :                 computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
     630       14496 :                 v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
     631             :             }
     632             : 
     633      338240 :             for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     634             :             {
     635      323744 :                 norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
     636             : 
     637      323744 :                 hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
     638      323744 :                 hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
     639      323744 :                 hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
     640             : 
     641      323744 :                 diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
     642      323744 :                 renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
     643             :             }
     644             :         }
     645             : 
     646       84560 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     647             :         {
     648      323744 :             for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
     649             :             {
     650      242808 :                 dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
     651             :             }
     652       80936 :             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] );
     653             :         }
     654             : 
     655             :         /* Coherence processing */
     656       84560 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     657             :         {
     658             :             /* Compute absolute values */
     659      971232 :             for ( i = 0; i < numAnalysisChannels; i++ )
     660             :             {
     661     6232072 :                 for ( j = i; j < numAnalysisChannels; j++ )
     662             :                 {
     663     5341776 :                     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] ) );
     664             :                 }
     665      890296 :                 lsEnergy[i] = absCOVls[i][i];
     666             :             }
     667             : 
     668             :             /* Find loudest channel */
     669       80936 :             maxEne = lsEnergy[0];
     670       80936 :             loudestCh = 0;
     671      890296 :             for ( i = 1; i < numAnalysisChannels; i++ )
     672             :             {
     673      809360 :                 if ( lsEnergy[i] > maxEne )
     674             :                 {
     675      150610 :                     maxEne = lsEnergy[i];
     676      150610 :                     loudestCh = i;
     677             :                 }
     678             :             }
     679             : 
     680             :             /* Compute surrounding coherence */
     681       80936 :             surrCoh = 1.0f;
     682      971232 :             for ( i = 0; i < numAnalysisChannels; i++ )
     683             :             {
     684      890296 :                 if ( i != loudestCh )
     685             :                 {
     686      809360 :                     if ( i < loudestCh )
     687             :                     {
     688      480772 :                         i1 = i;
     689      480772 :                         i2 = loudestCh;
     690             :                     }
     691             :                     else
     692             :                     {
     693      328588 :                         i1 = loudestCh;
     694      328588 :                         i2 = i;
     695             :                     }
     696      809360 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
     697      809360 :                     surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
     698             :                 }
     699             :             }
     700       80936 :             surrCoh = surrCoh * surrCoh;
     701       80936 :             surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
     702       80936 :             surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
     703             : 
     704             :             /* Compute spread coherence */
     705       80936 :             if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
     706             :             {
     707        6490 :                 minAngleDist = 180.0f;
     708        6490 :                 i1 = 0;
     709        6490 :                 currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
     710       51920 :                 for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     711             :                 {
     712       45430 :                     angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
     713       45430 :                     if ( angleDist > 180.0f )
     714             :                     {
     715        1142 :                         angleDist = fabsf( angleDist - 360.0f );
     716             :                     }
     717       45430 :                     if ( angleDist < minAngleDist )
     718             :                     {
     719       14496 :                         minAngleDist = angleDist;
     720       14496 :                         i1 = i;
     721             :                     }
     722             :                 }
     723        6490 :                 i2 = hMcMasa->leftNearest[i1];
     724        6490 :                 i3 = hMcMasa->rightNearest[i1];
     725             : 
     726        6490 :                 if ( i2 < i3 )
     727             :                 {
     728        5154 :                     stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     729             :                 }
     730             :                 else
     731             :                 {
     732        1336 :                     stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     733             :                 }
     734        6490 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
     735        6490 :                 stereoness = stereoCoh * lsEnergyRelation;
     736             : 
     737        6490 :                 if ( i1 < i2 )
     738             :                 {
     739        2268 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     740             :                 }
     741             :                 else
     742             :                 {
     743        4222 :                     tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     744             :                 }
     745        6490 :                 if ( i1 < i3 )
     746             :                 {
     747        2078 :                     tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     748             :                 }
     749             :                 else
     750             :                 {
     751        4412 :                     tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     752             :                 }
     753        6490 :                 cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
     754        6490 :                 lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
     755        6490 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
     756        6490 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     757        6490 :                 tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
     758        6490 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     759        6490 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
     760        6490 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     761        6490 :                 cohwideness = cohPanCoh * lsEnergyRelation;
     762             : 
     763        6490 :                 spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
     764        6490 :                 if ( spreadCoh > 0.5f )
     765             :                 {
     766        1996 :                     if ( cohwideness > stereoness )
     767             :                     {
     768         630 :                         tempCoh = stereoness - ( cohwideness - 0.5f );
     769         630 :                         spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
     770             :                     }
     771             :                 }
     772        6490 :                 spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
     773        6490 :                 spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
     774             : 
     775             :                 /* Compute energy ratio tuning parameter */
     776        6490 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
     777        6490 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     778        6490 :                 stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
     779             : 
     780        6490 :                 lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     781        6490 :                 cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
     782             : 
     783        6490 :                 cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
     784        6490 :                 cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
     785        6490 :                 cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
     786             :             }
     787             :             else /* Otherwise, set spread coherence to zero */
     788             :             {
     789       74446 :                 spreadCoh = 0.0f;
     790       74446 :                 cohRatio = 0.0f;
     791       74446 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
     792             :             }
     793             : 
     794             :             /* Store values */
     795       80936 :             spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
     796       80936 :             surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
     797       80936 :             coherentEnergyRatio[band_m_idx] = cohRatio;
     798             :         }
     799             : 
     800             :         /* Determine energy ratios */
     801       84560 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     802             :         {
     803       80936 :             if ( renormalization_factor_diff[band_m_idx] > EPSILON )
     804             :             {
     805       80802 :                 diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
     806             :             }
     807             :             else
     808             :             {
     809         134 :                 diffuseness_m[band_m_idx] = 0.0f;
     810             :             }
     811             : 
     812       80936 :             energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
     813       80936 :             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];
     814             :         }
     815             :     }
     816             : 
     817         906 :     return;
     818             : }
     819             : 
     820             : 
     821             : /* Compute downmix */
     822         906 : static void ivas_mcmasa_dmx(
     823             :     MCMASA_ANA_HANDLE hMcMasa,
     824             :     float data_f[][L_FRAME48k],
     825             :     const int16_t input_frame,
     826             :     const int16_t nchan_transport,
     827             :     const int16_t nchan_inp )
     828             : {
     829             :     int16_t i, j;
     830             :     int16_t numAnalysisChannels;
     831             :     float dmx_c;
     832             :     float multiChEne, downmixEne;
     833             :     float prevEQ, currEQ, instEQ;
     834             :     float alpha;
     835             : 
     836         906 :     numAnalysisChannels = nchan_inp - 1;
     837             : 
     838         906 :     multiChEne = 0.0f;
     839       10872 :     for ( j = 0; j < numAnalysisChannels; j++ )
     840             :     {
     841     6388206 :         for ( i = 0; i < input_frame; i++ )
     842             :         {
     843     6378240 :             multiChEne += data_f[j][i] * data_f[j][i];
     844             :         }
     845             :     }
     846             : 
     847         906 :     if ( nchan_transport == 2 )
     848             :     {
     849             :         int16_t numSideChannels; /* Channels other than left, right, center */
     850             :         int16_t leftIndex, rightIndex;
     851             : 
     852         453 :         numSideChannels = numAnalysisChannels / 2 - 1;
     853        2265 :         for ( j = 0; j < numSideChannels; j++ )
     854             :         {
     855        1812 :             leftIndex = j * 2 + 3;
     856        1812 :             rightIndex = j * 2 + 4;
     857             : 
     858     1161492 :             for ( i = 0; i < input_frame; i++ )
     859             :             {
     860     1159680 :                 data_f[0][i] += data_f[leftIndex][i];
     861     1159680 :                 data_f[1][i] += data_f[rightIndex][i];
     862             :             }
     863             :         }
     864             : 
     865      290373 :         for ( i = 0; i < input_frame; i++ )
     866             :         {
     867      289920 :             dmx_c = INV_SQRT2 * data_f[2][i];
     868      289920 :             data_f[0][i] += dmx_c;
     869      289920 :             data_f[1][i] += dmx_c;
     870             :         }
     871             :     }
     872         453 :     else if ( nchan_transport == 1 )
     873             :     {
     874      290373 :         for ( i = 0; i < input_frame; i++ )
     875             :         {
     876     3189120 :             for ( j = 1; j < numAnalysisChannels; j++ )
     877             :             {
     878     2899200 :                 data_f[0][i] += data_f[j][i];
     879             :             }
     880             :         }
     881             :     }
     882             : 
     883         906 :     downmixEne = 0.0f;
     884        2265 :     for ( j = 0; j < nchan_transport; j++ )
     885             :     {
     886      871119 :         for ( i = 0; i < input_frame; i++ )
     887             :         {
     888      869760 :             downmixEne += data_f[j][i] * data_f[j][i];
     889             :         }
     890             :     }
     891             : 
     892         906 :     alpha = 0.1f;
     893         906 :     hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
     894         906 :     hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
     895             : 
     896         906 :     prevEQ = hMcMasa->prevEQ;
     897         906 :     currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
     898         906 :     hMcMasa->prevEQ = currEQ;
     899             : 
     900      580746 :     for ( i = 0; i < input_frame; i++ )
     901             :     {
     902      579840 :         instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
     903     1449600 :         for ( j = 0; j < nchan_transport; j++ )
     904             :         {
     905      869760 :             data_f[j][i] *= instEQ;
     906             :         }
     907             :     }
     908             : 
     909         906 :     return;
     910             : }
     911             : 
     912             : 
     913             : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
     914      579840 : static void compute_cov_mtx(
     915             :     float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, real, s[ch][freq]                         */
     916             :     float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i  : Input matrix, imag, s[ch][freq]                         */
     917             :     const int16_t freq,                                    /* i  : Freq to process                                         */
     918             :     const int16_t N,                                       /* i  : Number of channels                                      */
     919             :     CovarianceMatrix *COVls                                /* o  : Output matrix, contains upper part of cov mtx           */
     920             : )
     921             : {
     922             :     int16_t i, j;
     923             :     float a, b, c, d;
     924             : 
     925     6958080 :     for ( i = 0; i < N; i++ )
     926             :     {
     927     6378240 :         a = sr[i][freq];
     928     6378240 :         b = si[i][freq];
     929    44647680 :         for ( j = i; j < N; j++ )
     930             :         {
     931    38269440 :             c = sr[j][freq];
     932    38269440 :             d = si[j][freq];
     933    38269440 :             COVls->xr[i][j] += a * c + b * d;
     934    38269440 :             COVls->xi[i][j] += b * c - a * d;
     935             :         }
     936             :     }
     937             : 
     938      579840 :     return;
     939             : }
     940             : 
     941             : /*-------------------------------------------------------------------------
     942             :  * computeVerticalDiffuseness()
     943             :  *
     944             :  *
     945             :  *------------------------------------------------------------------------*/
     946             : 
     947       14496 : static void computeVerticalDiffuseness(
     948             :     float **buffer_intensity,     /* i  : Intensity vectors           */
     949             :     const float *buffer_energy,   /* i  : Energy                      */
     950             :     const int16_t num_freq_bands, /* i  : Number of frequency bands   */
     951             :     float *diffuseness            /* o  : Estimated diffuseness       */
     952             : )
     953             : {
     954             :     float intensity_slow[MASA_FREQUENCY_BANDS];
     955             :     float intensity_slow_abs[MASA_FREQUENCY_BANDS];
     956             :     float energy_slow[MASA_FREQUENCY_BANDS];
     957             :     int16_t i, k;
     958       14496 :     float tmp = 0;
     959             :     const float *p_tmp_c;
     960             : 
     961             :     /* Set variables to zero */
     962       14496 :     set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
     963       14496 :     set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
     964             : 
     965      478368 :     for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
     966             :     {
     967             :         /* Energy slow */
     968      463872 :         p_tmp_c = buffer_energy + i * num_freq_bands;
     969    10823680 :         for ( k = 0; k < num_freq_bands; k++ )
     970             :         {
     971    10359808 :             energy_slow[k] += *( p_tmp_c++ );
     972             :         }
     973             : 
     974             :         /* Intensity slow */
     975    10823680 :         for ( k = 0; k < num_freq_bands; k++ )
     976             :         {
     977    10359808 :             intensity_slow[k] += buffer_intensity[i][k];
     978             :         }
     979             :     }
     980             : 
     981             :     /* Compute absolute value */
     982      338240 :     for ( k = 0; k < num_freq_bands; k++ )
     983             :     {
     984      323744 :         intensity_slow_abs[k] = fabsf( intensity_slow[k] );
     985             :     }
     986             : 
     987             :     /* Compute Diffuseness */
     988      338240 :     for ( i = 0; i < num_freq_bands; ++i )
     989             :     {
     990      323744 :         tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
     991      323744 :         tmp = ( tmp - VERTICAL_ENERGY_RATIO_OFFSET ) / ( 1.0f - VERTICAL_ENERGY_RATIO_OFFSET ); /* Tuned to avoid effect due to ambience of vertically un-even setups */
     992      323744 :         tmp = 1.0f - tmp;
     993      323744 :         diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
     994             :     }
     995             : 
     996       14496 :     return;
     997             : }
     998             : 
     999             : 
    1000          12 : static void computeEvenLayout(
    1001             :     const float *ls_azimuth,
    1002             :     float *ls_azimuth_even,
    1003             :     const int16_t numChannels )
    1004             : {
    1005             :     int16_t i;
    1006             :     int16_t j;
    1007             :     float ls_azimuth_temp[MCMASA_MAX_ANA_CHANS];
    1008             :     float ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS];
    1009             :     int16_t ls_azimuth_order[MCMASA_MAX_ANA_CHANS];
    1010             :     float smallestAzimuth;
    1011             :     int16_t smallestAzimuthIndex;
    1012             :     float lsSpacing;
    1013             :     uint8_t oddLayout;
    1014             :     float startAzimuth;
    1015             :     int16_t numChannelsHalf;
    1016             : 
    1017          12 :     lsSpacing = 360.0f / (float) numChannels;
    1018          12 :     oddLayout = numChannels % 2;
    1019          12 :     numChannelsHalf = numChannels / 2;
    1020             : 
    1021          12 :     mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
    1022          78 :     for ( i = 0; i < numChannels; i++ )
    1023             :     {
    1024          66 :         smallestAzimuth = 1000.0f;
    1025          66 :         smallestAzimuthIndex = 0;
    1026         456 :         for ( j = 0; j < numChannels; j++ )
    1027             :         {
    1028         390 :             if ( ls_azimuth_temp[j] < smallestAzimuth )
    1029             :             {
    1030         126 :                 smallestAzimuth = ls_azimuth_temp[j];
    1031         126 :                 smallestAzimuthIndex = j;
    1032             :             }
    1033             :         }
    1034          66 :         ls_azimuth_order[i] = smallestAzimuthIndex;
    1035          66 :         ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
    1036             :     }
    1037             : 
    1038          12 :     if ( oddLayout )
    1039             :     {
    1040           6 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
    1041             :     }
    1042             :     else
    1043             :     {
    1044           6 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
    1045             :     }
    1046             : 
    1047          78 :     for ( i = 0; i < numChannels; i++ )
    1048             :     {
    1049          66 :         ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
    1050             :     }
    1051             : 
    1052          78 :     for ( i = 0; i < numChannels; i++ )
    1053             :     {
    1054          66 :         ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
    1055             :     }
    1056             : 
    1057          12 :     return;
    1058             : }
    1059             : 
    1060             : 
    1061             : /*-------------------------------------------------------------------------
    1062             :  * ivas_create_masa_out_meta()
    1063             :  *
    1064             :  *
    1065             :  *------------------------------------------------------------------------*/
    1066             : 
    1067      290766 : void ivas_create_masa_out_meta(
    1068             :     MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta,                                  /* i/o: MASA metadata handle            */
    1069             :     SPHERICAL_GRID_DATA *Sph_Grid16,                                              /* i  : Spherical grid                  */
    1070             :     const int16_t nchan_transport,                                                /* i  : Number of transport channels    */
    1071             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],  /* i  : Estimated elevation             */
    1072             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],    /* i  : Estimated azimuth               */
    1073             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],         /* i  : Estimated direct-to-total ratio */
    1074             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* i  : Estimated spread coherence      */
    1075             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i  : Estimated surround coherence    */
    1076             : )
    1077             : {
    1078             :     int16_t i, sf, band;
    1079             :     uint8_t numFrequencyBands;
    1080             :     uint8_t numDirections;
    1081             :     uint16_t spherical_index;
    1082             : 
    1083      290766 :     numDirections = 1;
    1084      290766 :     numFrequencyBands = MASA_FREQUENCY_BANDS;
    1085             : 
    1086             :     /* Construct descriptive meta */
    1087     2616894 :     for ( i = 0; i < 8; i++ )
    1088             :     {
    1089     2326128 :         extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
    1090             :     }
    1091      290766 :     extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
    1092      290766 :     extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
    1093             :     /* Following correspond to "unknown" values */
    1094      290766 :     extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
    1095      290766 :     extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
    1096      290766 :     extOutMeta->descriptiveMeta.channelAngle = 0x0u;
    1097      290766 :     extOutMeta->descriptiveMeta.channelDistance = 0x0u;
    1098      290766 :     extOutMeta->descriptiveMeta.channelLayout = 0x0u;
    1099             : 
    1100             :     /* Construct spatial metadata from estimated values */
    1101     1453830 :     for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1102             :     {
    1103             :         /* Spherical index */
    1104    29076600 :         for ( band = 0; band < numFrequencyBands; band++ )
    1105             :         {
    1106    27913536 :             spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
    1107    27913536 :             extOutMeta->directionIndex[0][sf][band] = spherical_index;
    1108    27913536 :             extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
    1109             :         }
    1110             : 
    1111             :         /* Direct-to-total ratio */
    1112    29076600 :         for ( band = 0; band < numFrequencyBands; band++ )
    1113             :         {
    1114    27913536 :             extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1115    27913536 :             extOutMeta->directToTotalRatio[1][sf][band] = 0;
    1116             :         }
    1117             : 
    1118             :         /* Spread coherence */
    1119    29076600 :         for ( band = 0; band < numFrequencyBands; band++ )
    1120             :         {
    1121    27913536 :             extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
    1122    27913536 :             extOutMeta->spreadCoherence[1][sf][band] = 0;
    1123             :         }
    1124             : 
    1125             :         /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
    1126    29076600 :         for ( band = 0; band < numFrequencyBands; band++ )
    1127             :         {
    1128    27913536 :             extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1129             :         }
    1130             : 
    1131             :         /* Surround coherence */
    1132    29076600 :         for ( band = 0; band < numFrequencyBands; band++ )
    1133             :         {
    1134    27913536 :             extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
    1135             :         }
    1136             :     }
    1137             : 
    1138      290766 :     return;
    1139             : }
    1140             : 
    1141             : 
    1142             : /*-------------------------------------------------------------------------
    1143             :  * ivas_masa_zero_high_bands()
    1144             :  *
    1145             :  *
    1146             :  *------------------------------------------------------------------------*/
    1147             : 
    1148      193844 : void ivas_masa_zero_high_bands(
    1149             :     const int16_t nbands,                                                         /* i    : Number of frequency bands with estimated values */
    1150             :     float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],  /* i/o  : Estimated elevation                             */
    1151             :     float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],    /* i/o  : Estimated azimuth                               */
    1152             :     float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],         /* i/o  : Estimated direct-to-total ratio                 */
    1153             :     float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],     /* i/o  : Estimated spread coherence                      */
    1154             :     float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i/o  : Estimated surround coherence                    */
    1155             : )
    1156             : {
    1157             :     int16_t sf, band;
    1158             : 
    1159      969220 :     for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1160             :     {
    1161     2713816 :         for ( band = nbands; band < MASA_FREQUENCY_BANDS; band++ )
    1162             :         {
    1163     1938440 :             elevation_m_values[sf][band] = 0.0f;
    1164     1938440 :             azimuth_m_values[sf][band] = 0.0f;
    1165     1938440 :             energyRatio[sf][band] = 0.0f;
    1166     1938440 :             spreadCoherence[sf][band] = 0.0f;
    1167     1938440 :             surroundingCoherence[sf][band] = 0.0f;
    1168             :         }
    1169             :     }
    1170             : 
    1171      193844 :     return;
    1172             : }

Generated by: LCOV version 1.14