LCOV - code coverage report
Current view: top level - lib_rend - ivas_mcmasa_ana.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ 9b04ec3cb36f5e8dc438cf854fa3e349998fa1e9 Lines: 414 444 93.2 %
Date: 2025-10-31 05:45:46 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          19 : 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          19 :     error = IVAS_ERR_OK;
     103             : 
     104          19 :     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          19 :     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          19 :     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          19 :     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          19 :     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          19 :         nchan_inp = 12;
     144          19 :         mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 );
     145          19 :         mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 );
     146          19 :         hMcMasa->numHorizontalChannels = 7;
     147          19 :         hMcMasa->isHorizontalSetup = 0;
     148             :     }
     149             : 
     150          19 :     numAnalysisChannels = nchan_inp - 1;
     151             : 
     152             :     /* Determine the number of bands */
     153          19 :     hMcMasa->nbands = MASA_FREQUENCY_BANDS;
     154             : 
     155             :     /* Determine band grouping */
     156          19 :     mvs2s( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 );
     157             : 
     158          19 :     maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f );
     159         426 :     for ( i = 1; i < hMcMasa->nbands + 1; i++ )
     160             :     {
     161         426 :         if ( hMcMasa->band_grouping[i] >= maxBin )
     162             :         {
     163          19 :             hMcMasa->band_grouping[i] = maxBin;
     164          19 :             hMcMasa->nbands = i;
     165          19 :             break;
     166             :         }
     167             :     }
     168             : 
     169             :     /* Determine block grouping */
     170          19 :     mvs2s( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     171             : 
     172             :     /* open/initialize CLDFB */
     173          19 :     hMcMasa->num_Cldfb_instances = numAnalysisChannels;
     174         228 :     for ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ )
     175             :     {
     176         209 :         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          76 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     184             :     {
     185          57 :         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         285 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     191             :         {
     192         228 :             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         228 :             set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS );
     197             :         }
     198             :     }
     199             : 
     200          76 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     201             :     {
     202        1881 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     203             :         {
     204        1824 :             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        1824 :             set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS );
     209             :         }
     210             :     }
     211             : 
     212         627 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     213             :     {
     214         608 :         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         608 :         set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS );
     219             :     }
     220             : 
     221          19 :     set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
     222             : 
     223          19 :     computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels );
     224             : 
     225          19 :     if ( !hMcMasa->isHorizontalSetup )
     226             :     {
     227          19 :         computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels );
     228             :     }
     229             : 
     230         228 :     for ( i = 0; i < numAnalysisChannels; i++ )
     231             :     {
     232         209 :         hMcMasa->chnlToFoaMtx[0][i] = 1.0f;
     233         209 :         hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     234         209 :         hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 );
     235         209 :         hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 );
     236             : 
     237         209 :         hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f;
     238         209 :         hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 );
     239         209 :         hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f;
     240         209 :         hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 );
     241             :     }
     242             : 
     243          19 :     mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels );
     244             : 
     245         152 :     for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     246             :     {
     247         133 :         left_min = 360.0f;
     248         133 :         right_min = -360.0f;
     249             : 
     250        1064 :         for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ )
     251             :         {
     252         931 :             azi_diff = ls_azimuth[j] - ls_azimuth[i];
     253             : 
     254         931 :             if ( azi_diff > 180.0f )
     255             :             {
     256          57 :                 azi_diff -= 360.0f;
     257             :             }
     258         874 :             else if ( azi_diff < -180.0f )
     259             :             {
     260          57 :                 azi_diff += 360.0f;
     261             :             }
     262             : 
     263         931 :             if ( azi_diff < left_min && azi_diff > 0.0f )
     264             :             {
     265         228 :                 hMcMasa->leftNearest[i] = j;
     266         228 :                 left_min = azi_diff;
     267             :             }
     268             : 
     269         931 :             if ( azi_diff > right_min && azi_diff < 0.0f )
     270             :             {
     271         209 :                 hMcMasa->rightNearest[i] = j;
     272         209 :                 right_min = azi_diff;
     273             :             }
     274             :         }
     275             :     }
     276             : 
     277          19 :     hMcMasa->prevMultiChEne = 0.0f;
     278          19 :     hMcMasa->prevDownmixEne = 0.0f;
     279          19 :     hMcMasa->prevEQ = 1.0f;
     280          19 :     input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC );
     281       12499 :     for ( i = 0; i < input_frame; i++ )
     282             :     {
     283       12480 :         hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame );
     284             :     }
     285             : 
     286          19 :     hMcMasa->index_buffer_intensity = 0;
     287             : 
     288          19 :     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          19 :     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          19 :     generate_gridEq( hMcMasa->sph_grid16 );
     298             : 
     299          19 :     ( *hMcMasaPtr ) = hMcMasa;
     300             : 
     301          19 :     return error;
     302             : }
     303             : 
     304             : 
     305             : /*--------------------------------------------------------------------------*
     306             :  * ivas_mcmasa_ana_close()
     307             :  *
     308             :  *
     309             :  *--------------------------------------------------------------------------*/
     310             : 
     311       14179 : void ivas_mcmasa_ana_close(
     312             :     MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle   */
     313             : )
     314             : {
     315             :     int16_t i, j;
     316             : 
     317       14179 :     if ( hMcMasa == NULL || *hMcMasa == NULL )
     318             :     {
     319       14160 :         return;
     320             :     }
     321             : 
     322         228 :     for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ )
     323             :     {
     324         209 :         deleteCldfb( &( ( *hMcMasa )->cldfbAnaEnc[i] ) );
     325             :     }
     326             : 
     327             :     /* intensity 3-dim */
     328          76 :     for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     329             :     {
     330         285 :         for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     331             :         {
     332         228 :             free( ( *hMcMasa )->direction_vector_m[i][j] );
     333         228 :             ( *hMcMasa )->direction_vector_m[i][j] = NULL;
     334             :         }
     335             : 
     336        1881 :         for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     337             :         {
     338        1824 :             free( ( *hMcMasa )->buffer_intensity_real[i][j] );
     339        1824 :             ( *hMcMasa )->buffer_intensity_real[i][j] = NULL;
     340             :         }
     341             : 
     342          57 :         free( ( *hMcMasa )->direction_vector_m[i] );
     343          57 :         ( *hMcMasa )->direction_vector_m[i] = NULL;
     344             :     }
     345             : 
     346         627 :     for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     347             :     {
     348         608 :         free( ( *hMcMasa )->buffer_intensity_real_vert[j] );
     349         608 :         ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL;
     350             :     }
     351             : 
     352          19 :     free( ( *hMcMasa )->hMasaOut );
     353          19 :     ( *hMcMasa )->hMasaOut = NULL;
     354          19 :     free( ( *hMcMasa )->sph_grid16 );
     355          19 :     ( *hMcMasa )->sph_grid16 = NULL;
     356             : 
     357          19 :     free( ( *hMcMasa ) );
     358          19 :     ( *hMcMasa ) = NULL;
     359             : 
     360          19 :     return;
     361             : }
     362             : 
     363             : 
     364             : /*--------------------------------------------------------------------------*
     365             :  * ivas_mcmasa_ana()
     366             :  *
     367             :  * Multichannel MASA analysis
     368             :  *--------------------------------------------------------------------------*/
     369             : 
     370        2869 : 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        2869 :     v_add( data_f[2], data_f[3], data_f[2], input_frame );
     388       25821 :     for ( i = 4; i < nchan_inp; i++ )
     389             :     {
     390       22952 :         mvr2r( data_f[i], data_f[i - 1], input_frame );
     391             :     }
     392             : 
     393             :     /* Analysis */
     394        2869 :     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        2869 :     if ( hMcMasa->nbands < MASA_FREQUENCY_BANDS )
     398             :     {
     399        1812 :         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        2869 :     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        2869 :     ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp );
     407             : 
     408        2869 :     return;
     409             : }
     410             : 
     411             : 
     412             : /*--------------------------------------------------------------------------*
     413             :  * Local functions
     414             :  *--------------------------------------------------------------------------*/
     415             : 
     416             : /* Estimate metadata parameters for McMASA */
     417        2869 : 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        2869 :     num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels;
     468        2869 :     num_freq_bands = hMcMasa->nbands;
     469        2869 :     l_ts = input_frame / CLDFB_NO_COL_MAX;
     470        2869 :     numAnalysisChannels = nchan_inp - 1;
     471             : 
     472             :     /* do processing over all CLDFB time slots */
     473       14345 :     for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     474             :     {
     475       11476 :         mrange[0] = hMcMasa->block_grouping[block_m_idx];
     476       11476 :         mrange[1] = hMcMasa->block_grouping[block_m_idx + 1];
     477             : 
     478      268780 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     479             :         {
     480      257304 :             hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0;
     481      257304 :             hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0;
     482      257304 :             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       11476 :         set_zero( renormalization_factor_diff, hMcMasa->nbands );
     487       11476 :         set_zero( diffuseness_m, hMcMasa->nbands );
     488       11476 :         set_zero( hMcMasa->energy[block_m_idx], MASA_FREQUENCY_BANDS );
     489             : 
     490             :         /* Reset variable */
     491      268780 :         for ( i = 0; i < hMcMasa->nbands; i++ )
     492             :         {
     493     3087648 :             for ( j = 0; j < numAnalysisChannels; j++ )
     494             :             {
     495     2830344 :                 set_zero( COVls[i].xr[j], numAnalysisChannels );
     496     2830344 :                 set_zero( COVls[i].xi[j], numAnalysisChannels );
     497             :             }
     498             :         }
     499             : 
     500       57380 :         for ( ts = mrange[0]; ts < mrange[1]; ts++ )
     501             :         {
     502      550848 :             for ( i = 0; i < numAnalysisChannels; i++ )
     503             :             {
     504      504944 :                 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     1075120 :             for ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
     509             :             {
     510     1029216 :                 brange[0] = hMcMasa->band_grouping[band_m_idx];
     511     1029216 :                 brange[1] = hMcMasa->band_grouping[band_m_idx + 1];
     512     2913696 :                 for ( j = brange[0]; j < brange[1]; j++ )
     513             :                 {
     514    22613760 :                     for ( i = 0; i < numAnalysisChannels; i++ )
     515             :                     {
     516    20729280 :                         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     1075120 :             for ( i = 0; i < num_freq_bands; i++ )
     523             :             {
     524     1029216 :                 brange[0] = hMcMasa->band_grouping[i];
     525     1029216 :                 brange[1] = hMcMasa->band_grouping[i + 1];
     526     2913696 :                 for ( j = brange[0]; j < brange[1]; j++ )
     527             :                 {
     528     1884480 :                     compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) );
     529             :                 }
     530             :             }
     531             : 
     532             :             /* Compute standard FOA */
     533             :             /* W */
     534       45904 :             v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins );
     535       45904 :             v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins );
     536      459040 :             for ( i = 2; i < numAnalysisChannels; i++ )
     537             :             {
     538      413136 :                 v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins );
     539      413136 :                 v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins );
     540             :             }
     541             : 
     542             :             /* Y */
     543       45904 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins );
     544       45904 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins );
     545      504944 :             for ( i = 1; i < numAnalysisChannels; i++ )
     546             :             {
     547      459040 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins );
     548      459040 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins );
     549             :             }
     550             : 
     551             :             /* Z */
     552       45904 :             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       45904 :                 v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins );
     561       45904 :                 v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins );
     562      504944 :                 for ( i = 1; i < numAnalysisChannels; i++ )
     563             :                 {
     564      459040 :                     v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins );
     565      459040 :                     v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins );
     566             :                 }
     567             :             }
     568             : 
     569             :             /* X */
     570       45904 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins );
     571       45904 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins );
     572      504944 :             for ( i = 1; i < numAnalysisChannels; i++ )
     573             :             {
     574      459040 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins );
     575      459040 :                 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       45904 :             mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins );
     581       45904 :             mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins );
     582             : 
     583             :             /* Y */
     584       45904 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins );
     585       45904 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins );
     586      504944 :             for ( i = 1; i < numAnalysisChannels; i++ )
     587             :             {
     588      459040 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins );
     589      459040 :                 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       45904 :             set_zero( FoaEven_RealBuffer[2], num_freq_bins );
     594       45904 :             set_zero( FoaEven_ImagBuffer[2], num_freq_bins );
     595             : 
     596             :             /* X */
     597       45904 :             v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins );
     598       45904 :             v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins );
     599      504944 :             for ( i = 1; i < numAnalysisChannels; i++ )
     600             :             {
     601      459040 :                 v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins );
     602      459040 :                 v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins );
     603             :             }
     604             : 
     605             :             /* Direction estimation */
     606       45904 :             computeIntensityVector_ana( hMcMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real );
     607       45904 :             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       45904 :             computeIntensityVector_ana( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, num_freq_bands, intensity_even_real );
     611       45904 :             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       45904 :             hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */
     615       45904 :             index = hMcMasa->index_buffer_intensity;
     616      183616 :             for ( i = 0; i < DIRAC_NUM_DIMS; i++ )
     617             :             {
     618             :                 /* only real part needed */
     619      137712 :                 mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands );
     620             :             }
     621       45904 :             mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands );
     622             : 
     623       45904 :             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       45904 :             if ( !hMcMasa->isHorizontalSetup )
     627             :             {
     628       45904 :                 mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands );
     629       45904 :                 computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, num_freq_bands, vertical_diffuseness_vector );
     630       45904 :                 v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands );
     631             :             }
     632             : 
     633     1075120 :             for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     634             :             {
     635     1029216 :                 norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] );
     636             : 
     637     1029216 :                 hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx];
     638     1029216 :                 hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx];
     639     1029216 :                 hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx];
     640             : 
     641     1029216 :                 diffuseness_m[band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx];
     642     1029216 :                 renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx];
     643             :             }
     644             :         }
     645             : 
     646      268780 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     647             :         {
     648     1029216 :             for ( d = 0; d < DIRAC_NUM_DIMS; d++ )
     649             :             {
     650      771912 :                 dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx];
     651             :             }
     652      257304 :             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      268780 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     657             :         {
     658             :             /* Compute absolute values */
     659     3087648 :             for ( i = 0; i < numAnalysisChannels; i++ )
     660             :             {
     661    19812408 :                 for ( j = i; j < numAnalysisChannels; j++ )
     662             :                 {
     663    16982064 :                     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     2830344 :                 lsEnergy[i] = absCOVls[i][i];
     666             :             }
     667             : 
     668             :             /* Find loudest channel */
     669      257304 :             maxEne = lsEnergy[0];
     670      257304 :             loudestCh = 0;
     671     2830344 :             for ( i = 1; i < numAnalysisChannels; i++ )
     672             :             {
     673     2573040 :                 if ( lsEnergy[i] > maxEne )
     674             :                 {
     675      479426 :                     maxEne = lsEnergy[i];
     676      479426 :                     loudestCh = i;
     677             :                 }
     678             :             }
     679             : 
     680             :             /* Compute surrounding coherence */
     681      257304 :             surrCoh = 1.0f;
     682     3087648 :             for ( i = 0; i < numAnalysisChannels; i++ )
     683             :             {
     684     2830344 :                 if ( i != loudestCh )
     685             :                 {
     686     2573040 :                     if ( i < loudestCh )
     687             :                     {
     688     1530587 :                         i1 = i;
     689     1530587 :                         i2 = loudestCh;
     690             :                     }
     691             :                     else
     692             :                     {
     693     1042453 :                         i1 = loudestCh;
     694     1042453 :                         i2 = i;
     695             :                     }
     696     2573040 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) );
     697     2573040 :                     surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh;
     698             :                 }
     699             :             }
     700      257304 :             surrCoh = surrCoh * surrCoh;
     701      257304 :             surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f;
     702      257304 :             surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f;
     703             : 
     704             :             /* Compute spread coherence */
     705      257304 :             if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */
     706             :             {
     707       20569 :                 minAngleDist = 180.0f;
     708       20569 :                 i1 = 0;
     709       20569 :                 currentAzi = azimuth_m_values[block_m_idx][band_m_idx];
     710      164552 :                 for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ )
     711             :                 {
     712      143983 :                     angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] );
     713      143983 :                     if ( angleDist > 180.0f )
     714             :                     {
     715        3618 :                         angleDist = fabsf( angleDist - 360.0f );
     716             :                     }
     717      143983 :                     if ( angleDist < minAngleDist )
     718             :                     {
     719       45942 :                         minAngleDist = angleDist;
     720       45942 :                         i1 = i;
     721             :                     }
     722             :                 }
     723       20569 :                 i2 = hMcMasa->leftNearest[i1];
     724       20569 :                 i3 = hMcMasa->rightNearest[i1];
     725             : 
     726       20569 :                 if ( i2 < i3 )
     727             :                 {
     728       16340 :                     stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     729             :                 }
     730             :                 else
     731             :                 {
     732        4229 :                     stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) );
     733             :                 }
     734       20569 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON );
     735       20569 :                 stereoness = stereoCoh * lsEnergyRelation;
     736             : 
     737       20569 :                 if ( i1 < i2 )
     738             :                 {
     739        7181 :                     tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     740             :                 }
     741             :                 else
     742             :                 {
     743       13388 :                     tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) );
     744             :                 }
     745       20569 :                 if ( i1 < i3 )
     746             :                 {
     747        6579 :                     tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     748             :                 }
     749             :                 else
     750             :                 {
     751       13990 :                     tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) );
     752             :                 }
     753       20569 :                 cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2;
     754       20569 :                 lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON );
     755       20569 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON );
     756       20569 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     757       20569 :                 tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON );
     758       20569 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     759       20569 :                 tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON );
     760       20569 :                 lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation;
     761       20569 :                 cohwideness = cohPanCoh * lsEnergyRelation;
     762             : 
     763       20569 :                 spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness;
     764       20569 :                 if ( spreadCoh > 0.5f )
     765             :                 {
     766        6337 :                     if ( cohwideness > stereoness )
     767             :                     {
     768        2001 :                         tempCoh = stereoness - ( cohwideness - 0.5f );
     769        2001 :                         spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f;
     770             :                     }
     771             :                 }
     772       20569 :                 spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f;
     773       20569 :                 spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f;
     774             : 
     775             :                 /* Compute energy ratio tuning parameter */
     776       20569 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON;
     777       20569 :                 lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     778       20569 :                 stereoRatio = stereoCoh * lsEnergyRelation - surrCoh;
     779             : 
     780       20569 :                 lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum;
     781       20569 :                 cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh;
     782             : 
     783       20569 :                 cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio;
     784       20569 :                 cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f;
     785       20569 :                 cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f;
     786             :             }
     787             :             else /* Otherwise, set spread coherence to zero */
     788             :             {
     789      236735 :                 spreadCoh = 0.0f;
     790      236735 :                 cohRatio = 0.0f;
     791      236735 :                 lsEnergySum = sum_f( lsEnergy, numAnalysisChannels );
     792             :             }
     793             : 
     794             :             /* Store values */
     795      257304 :             spreadCoherence[block_m_idx][band_m_idx] = spreadCoh;
     796      257304 :             surroundingCoherence[block_m_idx][band_m_idx] = surrCoh;
     797      257304 :             coherentEnergyRatio[band_m_idx] = cohRatio;
     798             :         }
     799             : 
     800             :         /* Determine energy ratios */
     801      268780 :         for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ )
     802             :         {
     803      257304 :             if ( renormalization_factor_diff[band_m_idx] > EPSILON )
     804             :             {
     805      256878 :                 diffuseness_m[band_m_idx] /= renormalization_factor_diff[band_m_idx];
     806             :             }
     807             :             else
     808             :             {
     809         426 :                 diffuseness_m[band_m_idx] = 0.0f;
     810             :             }
     811             : 
     812      257304 :             energyRatio[block_m_idx][band_m_idx] = 1.0f - diffuseness_m[band_m_idx];
     813      257304 :             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        2869 :     return;
     818             : }
     819             : 
     820             : 
     821             : /* Compute downmix */
     822        2869 : 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        2869 :     numAnalysisChannels = nchan_inp - 1;
     837             : 
     838        2869 :     multiChEne = 0.0f;
     839       34428 :     for ( j = 0; j < numAnalysisChannels; j++ )
     840             :     {
     841    20760839 :         for ( i = 0; i < input_frame; i++ )
     842             :         {
     843    20729280 :             multiChEne += data_f[j][i] * data_f[j][i];
     844             :         }
     845             :     }
     846             : 
     847        2869 :     if ( nchan_transport == 2 )
     848             :     {
     849             :         int16_t numSideChannels; /* Channels other than left, right, center */
     850             :         int16_t leftIndex, rightIndex;
     851             : 
     852        1510 :         numSideChannels = numAnalysisChannels / 2 - 1;
     853        7550 :         for ( j = 0; j < numSideChannels; j++ )
     854             :         {
     855        6040 :             leftIndex = j * 2 + 3;
     856        6040 :             rightIndex = j * 2 + 4;
     857             : 
     858     4064920 :             for ( i = 0; i < input_frame; i++ )
     859             :             {
     860     4058880 :                 data_f[0][i] += data_f[leftIndex][i];
     861     4058880 :                 data_f[1][i] += data_f[rightIndex][i];
     862             :             }
     863             :         }
     864             : 
     865     1016230 :         for ( i = 0; i < input_frame; i++ )
     866             :         {
     867     1014720 :             dmx_c = INV_SQRT2 * data_f[2][i];
     868     1014720 :             data_f[0][i] += dmx_c;
     869     1014720 :             data_f[1][i] += dmx_c;
     870             :         }
     871             :     }
     872        1359 :     else if ( nchan_transport == 1 )
     873             :     {
     874      871119 :         for ( i = 0; i < input_frame; i++ )
     875             :         {
     876     9567360 :             for ( j = 1; j < numAnalysisChannels; j++ )
     877             :             {
     878     8697600 :                 data_f[0][i] += data_f[j][i];
     879             :             }
     880             :         }
     881             :     }
     882             : 
     883        2869 :     downmixEne = 0.0f;
     884        7248 :     for ( j = 0; j < nchan_transport; j++ )
     885             :     {
     886     2903579 :         for ( i = 0; i < input_frame; i++ )
     887             :         {
     888     2899200 :             downmixEne += data_f[j][i] * data_f[j][i];
     889             :         }
     890             :     }
     891             : 
     892        2869 :     alpha = 0.1f;
     893        2869 :     hMcMasa->prevMultiChEne = alpha * multiChEne + ( 1.0f - alpha ) * hMcMasa->prevMultiChEne;
     894        2869 :     hMcMasa->prevDownmixEne = alpha * downmixEne + ( 1.0f - alpha ) * hMcMasa->prevDownmixEne;
     895             : 
     896        2869 :     prevEQ = hMcMasa->prevEQ;
     897        2869 :     currEQ = sqrtf( hMcMasa->prevMultiChEne / ( hMcMasa->prevDownmixEne + EPSILON ) );
     898        2869 :     hMcMasa->prevEQ = currEQ;
     899             : 
     900     1887349 :     for ( i = 0; i < input_frame; i++ )
     901             :     {
     902     1884480 :         instEQ = hMcMasa->interpolator[i] * currEQ + ( 1.0f - hMcMasa->interpolator[i] ) * prevEQ;
     903     4783680 :         for ( j = 0; j < nchan_transport; j++ )
     904             :         {
     905     2899200 :             data_f[j][i] *= instEQ;
     906             :         }
     907             :     }
     908             : 
     909        2869 :     return;
     910             : }
     911             : 
     912             : 
     913             : /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */
     914     1884480 : 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    22613760 :     for ( i = 0; i < N; i++ )
     926             :     {
     927    20729280 :         a = sr[i][freq];
     928    20729280 :         b = si[i][freq];
     929   145104960 :         for ( j = i; j < N; j++ )
     930             :         {
     931   124375680 :             c = sr[j][freq];
     932   124375680 :             d = si[j][freq];
     933   124375680 :             COVls->xr[i][j] += a * c + b * d;
     934   124375680 :             COVls->xi[i][j] += b * c - a * d;
     935             :         }
     936             :     }
     937             : 
     938     1884480 :     return;
     939             : }
     940             : 
     941             : /*-------------------------------------------------------------------------
     942             :  * computeVerticalDiffuseness()
     943             :  *
     944             :  *
     945             :  *------------------------------------------------------------------------*/
     946             : 
     947       45904 : 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       45904 :     float tmp = 0;
     959             :     const float *p_tmp_c;
     960             : 
     961             :     /* Set variables to zero */
     962       45904 :     set_f( intensity_slow, 0.0f, MASA_FREQUENCY_BANDS );
     963       45904 :     set_f( energy_slow, 0.0f, MASA_FREQUENCY_BANDS );
     964             : 
     965     1514832 :     for ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i )
     966             :     {
     967             :         /* Energy slow */
     968     1468928 :         p_tmp_c = buffer_energy + i * num_freq_bands;
     969    34403840 :         for ( k = 0; k < num_freq_bands; k++ )
     970             :         {
     971    32934912 :             energy_slow[k] += *( p_tmp_c++ );
     972             :         }
     973             : 
     974             :         /* Intensity slow */
     975    34403840 :         for ( k = 0; k < num_freq_bands; k++ )
     976             :         {
     977    32934912 :             intensity_slow[k] += buffer_intensity[i][k];
     978             :         }
     979             :     }
     980             : 
     981             :     /* Compute absolute value */
     982     1075120 :     for ( k = 0; k < num_freq_bands; k++ )
     983             :     {
     984     1029216 :         intensity_slow_abs[k] = fabsf( intensity_slow[k] );
     985             :     }
     986             : 
     987             :     /* Compute Diffuseness */
     988     1075120 :     for ( i = 0; i < num_freq_bands; ++i )
     989             :     {
     990     1029216 :         tmp = intensity_slow_abs[i] / ( energy_slow[i] + EPSILON );
     991     1029216 :         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     1029216 :         tmp = 1.0f - tmp;
     993     1029216 :         diffuseness[i] = ( ( tmp < 1.0f ) ? ( ( tmp < 0.0f ) ? 0.f : tmp ) : 1.0f );
     994             :     }
     995             : 
     996       45904 :     return;
     997             : }
     998             : 
     999             : 
    1000          38 : 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          38 :     lsSpacing = 360.0f / (float) numChannels;
    1018          38 :     oddLayout = numChannels % 2;
    1019          38 :     numChannelsHalf = numChannels / 2;
    1020             : 
    1021          38 :     mvr2r( ls_azimuth, ls_azimuth_temp, numChannels );
    1022         247 :     for ( i = 0; i < numChannels; i++ )
    1023             :     {
    1024         209 :         smallestAzimuth = 1000.0f;
    1025         209 :         smallestAzimuthIndex = 0;
    1026        1444 :         for ( j = 0; j < numChannels; j++ )
    1027             :         {
    1028        1235 :             if ( ls_azimuth_temp[j] < smallestAzimuth )
    1029             :             {
    1030         399 :                 smallestAzimuth = ls_azimuth_temp[j];
    1031         399 :                 smallestAzimuthIndex = j;
    1032             :             }
    1033             :         }
    1034         209 :         ls_azimuth_order[i] = smallestAzimuthIndex;
    1035         209 :         ls_azimuth_temp[smallestAzimuthIndex] = 1000.0f;
    1036             :     }
    1037             : 
    1038          38 :     if ( oddLayout )
    1039             :     {
    1040          19 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf );
    1041             :     }
    1042             :     else
    1043             :     {
    1044          19 :         startAzimuth = -lsSpacing * ( (float) numChannelsHalf - 0.5f );
    1045             :     }
    1046             : 
    1047         247 :     for ( i = 0; i < numChannels; i++ )
    1048             :     {
    1049         209 :         ls_azimuth_even_ordered[i] = (float) i * lsSpacing + startAzimuth;
    1050             :     }
    1051             : 
    1052         247 :     for ( i = 0; i < numChannels; i++ )
    1053             :     {
    1054         209 :         ls_azimuth_even[ls_azimuth_order[i]] = roundf( ls_azimuth_even_ordered[i] );
    1055             :     }
    1056             : 
    1057          38 :     return;
    1058             : }
    1059             : 
    1060             : 
    1061             : /*-------------------------------------------------------------------------
    1062             :  * ivas_create_masa_out_meta()
    1063             :  *
    1064             :  *
    1065             :  *------------------------------------------------------------------------*/
    1066             : 
    1067      310431 : 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      310431 :     numDirections = 1;
    1084      310431 :     numFrequencyBands = MASA_FREQUENCY_BANDS;
    1085             : 
    1086             :     /* Construct descriptive meta */
    1087     2793879 :     for ( i = 0; i < 8; i++ )
    1088             :     {
    1089     2483448 :         extOutMeta->descriptiveMeta.formatDescriptor[i] = ivasmasaFormatDescriptor[i];
    1090             :     }
    1091      310431 :     extOutMeta->descriptiveMeta.numberOfDirections = numDirections - 1;
    1092      310431 :     extOutMeta->descriptiveMeta.numberOfChannels = (uint8_t) ( nchan_transport - 1 );
    1093             :     /* Following correspond to "unknown" values */
    1094      310431 :     extOutMeta->descriptiveMeta.sourceFormat = 0x0u;
    1095      310431 :     extOutMeta->descriptiveMeta.transportDefinition = 0x0u;
    1096      310431 :     extOutMeta->descriptiveMeta.channelAngle = 0x0u;
    1097      310431 :     extOutMeta->descriptiveMeta.channelDistance = 0x0u;
    1098      310431 :     extOutMeta->descriptiveMeta.channelLayout = 0x0u;
    1099             : 
    1100             :     /* Construct spatial metadata from estimated values */
    1101     1552155 :     for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1102             :     {
    1103             :         /* Spherical index */
    1104    31043100 :         for ( band = 0; band < numFrequencyBands; band++ )
    1105             :         {
    1106    29801376 :             spherical_index = index_theta_phi_16( &elevation_m_values[sf][band], &azimuth_m_values[sf][band], Sph_Grid16 );
    1107    29801376 :             extOutMeta->directionIndex[0][sf][band] = spherical_index;
    1108    29801376 :             extOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT;
    1109             :         }
    1110             : 
    1111             :         /* Direct-to-total ratio */
    1112    31043100 :         for ( band = 0; band < numFrequencyBands; band++ )
    1113             :         {
    1114    29801376 :             extOutMeta->directToTotalRatio[0][sf][band] = (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1115    29801376 :             extOutMeta->directToTotalRatio[1][sf][band] = 0;
    1116             :         }
    1117             : 
    1118             :         /* Spread coherence */
    1119    31043100 :         for ( band = 0; band < numFrequencyBands; band++ )
    1120             :         {
    1121    29801376 :             extOutMeta->spreadCoherence[0][sf][band] = (uint8_t) floorf( spreadCoherence[sf][band] * UINT8_MAX );
    1122    29801376 :             extOutMeta->spreadCoherence[1][sf][band] = 0;
    1123             :         }
    1124             : 
    1125             :         /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */
    1126    31043100 :         for ( band = 0; band < numFrequencyBands; band++ )
    1127             :         {
    1128    29801376 :             extOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX - (uint8_t) floorf( energyRatio[sf][band] * UINT8_MAX );
    1129             :         }
    1130             : 
    1131             :         /* Surround coherence */
    1132    31043100 :         for ( band = 0; band < numFrequencyBands; band++ )
    1133             :         {
    1134    29801376 :             extOutMeta->surroundCoherence[sf][band] = (uint8_t) floorf( surroundingCoherence[sf][band] * UINT8_MAX );
    1135             :         }
    1136             :     }
    1137             : 
    1138      310431 :     return;
    1139             : }
    1140             : 
    1141             : 
    1142             : /*-------------------------------------------------------------------------
    1143             :  * ivas_masa_zero_high_bands()
    1144             :  *
    1145             :  *
    1146             :  *------------------------------------------------------------------------*/
    1147             : 
    1148      206652 : 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     1033260 :     for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    1160             :     {
    1161     2893128 :         for ( band = nbands; band < MASA_FREQUENCY_BANDS; band++ )
    1162             :         {
    1163     2066520 :             elevation_m_values[sf][band] = 0.0f;
    1164     2066520 :             azimuth_m_values[sf][band] = 0.0f;
    1165     2066520 :             energyRatio[sf][band] = 0.0f;
    1166     2066520 :             spreadCoherence[sf][band] = 0.0f;
    1167     2066520 :             surroundingCoherence[sf][band] = 0.0f;
    1168             :         }
    1169             :     }
    1170             : 
    1171      206652 :     return;
    1172             : }

Generated by: LCOV version 1.14