LCOV - code coverage report
Current view: top level - lib_rend - ivas_omasa_ana_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 368 380 96.8 %
Date: 2025-08-23 01:22:27 Functions: 7 7 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 "options.h"
      34             : #include <stdlib.h>
      35             : #include <math.h>
      36             : #include "ivas_cnst.h"
      37             : #include "ivas_prot_rend_fx.h"
      38             : #include "ivas_prot_fx.h"
      39             : #include "prot_fx.h"
      40             : #include "ivas_stat_rend.h"
      41             : #include "ivas_rom_com.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : /*-------------------------------------------------------------------------
      45             :  * Local function prototypes
      46             :  *------------------------------------------------------------------------*/
      47             : 
      48             : 
      49             : static void ivas_omasa_dmx_fx(
      50             :     Word32 data_in_f_fx[][L_FRAME48k],
      51             :     Word16 *data_in_q,
      52             :     const Word16 input_frame,
      53             :     const Word16 nchan_transport,
      54             :     const Word16 nchan_ism,
      55             :     const Word32 ism_azimuth_fx[MAX_NUM_OBJECTS],
      56             :     const Word32 ism_elevation_fx[MAX_NUM_OBJECTS],
      57             :     Word32 prev_gains_fx[][MASA_MAX_TRANSPORT_CHANNELS],
      58             :     const Word16 interpolator_fx[L_FRAME48k] );
      59             : 
      60             : 
      61             : static void ivas_omasa_param_est_ana_fx(
      62             :     OMASA_ANA_HANDLE hOMasa,
      63             :     Word32 data_f_fx[][L_FRAME48k],
      64             :     Word16 data_f_q,
      65             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
      66             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   // Q22
      67             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
      68             :     Word16 *energyRatio_q,
      69             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
      70             :     Word16 *spreadCoherence_q,
      71             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
      72             :     Word16 *surroundingCoherence_q,
      73             :     const Word16 input_frame,
      74             :     const Word16 nchan_ism );
      75             : 
      76             : /*--------------------------------------------------------------------------*
      77             :  * ivas_omasa_ana_open()
      78             :  *
      79             :  * Allocate and initialize OMASA handle
      80             :  *--------------------------------------------------------------------------*/
      81             : 
      82           1 : ivas_error ivas_omasa_ana_open(
      83             :     OMASA_ANA_HANDLE *hOMasaPtr, /* i/o: OMASA data handle pointer */
      84             :     Word32 input_Fs,             /* i  : Sampling frequency        */
      85             :     UWord16 total_num_objects    /* i  : Number of objects         */
      86             : )
      87             : {
      88             :     Word16 i, j;
      89             :     OMASA_ANA_HANDLE hOMasa;
      90             :     Word16 numAnalysisChannels;
      91             :     Word16 maxBin, input_frame;
      92             :     ivas_error error;
      93             :     Word16 scale;
      94             : 
      95           1 :     error = IVAS_ERR_OK;
      96           1 :     move32();
      97             : 
      98           1 :     IF( ( hOMasa = (OMASA_ANA_HANDLE) malloc( sizeof( OMASA_ANA_DATA ) ) ) == NULL )
      99             :     {
     100           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA\n" ) );
     101             :     }
     102             : 
     103           1 :     numAnalysisChannels = (Word16) total_num_objects;
     104           1 :     move16();
     105             : 
     106             :     /* Determine the number of bands */
     107           1 :     hOMasa->nbands = MASA_FREQUENCY_BANDS;
     108           1 :     move16();
     109             : 
     110             :     /* Determine band grouping */
     111           1 :     Copy( MASA_band_grouping_24, hOMasa->band_grouping, 24 + 1 );
     112             : 
     113             :     /* maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); */
     114           1 :     maxBin = extract_l( Mpy_32_32( input_Fs, 2684355 /* INV_CLDFB_BANDWIDTH in Q31 */ ) ); // Q: ( ( Q0 + Q31 ) - Q31 ) -> Q0
     115             : 
     116          24 :     FOR( i = 1; i < hOMasa->nbands + 1; i++ )
     117             :     {
     118          24 :         IF( GE_16( hOMasa->band_grouping[i], maxBin ) )
     119             :         {
     120           1 :             hOMasa->band_grouping[i] = maxBin;
     121           1 :             move16();
     122           1 :             hOMasa->nbands = i;
     123           1 :             move16();
     124           1 :             BREAK;
     125             :         }
     126             :     }
     127             : 
     128             :     /* Determine block grouping */
     129           1 :     Copy( DirAC_block_grouping, hOMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 );
     130             : 
     131             :     /* open/initialize CLDFB */
     132           1 :     hOMasa->num_Cldfb_instances = numAnalysisChannels;
     133           5 :     FOR( i = 0; i < hOMasa->num_Cldfb_instances; i++ )
     134             :     {
     135           4 :         IF( NE_32( ( error = openCldfb_ivas_fx( &( hOMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
     136             :         {
     137           0 :             return error;
     138             :         }
     139             :     }
     140             : 
     141           1 :     FOR( ; i < MAX_NUM_OBJECTS; i++ )
     142             :     {
     143           0 :         hOMasa->cldfbAnaEnc[i] = NULL;
     144             :     }
     145             : 
     146           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     147             :     {
     148           3 :         IF( ( hOMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL )
     149             :         {
     150           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
     151             :         }
     152             : 
     153          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     154             :         {
     155          12 :             IF( ( hOMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
     156             :             {
     157           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
     158             :             }
     159          12 :             set_zero_fx( hOMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS );
     160             :         }
     161           3 :         IF( ( hOMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL )
     162             :         {
     163           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
     164             :         }
     165             : 
     166          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     167             :         {
     168          12 :             IF( ( hOMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL )
     169             :             {
     170           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
     171             :             }
     172          12 :             set16_fx( hOMasa->direction_vector_e[i][j], 0, MASA_FREQUENCY_BANDS );
     173             :         }
     174             :     }
     175             : 
     176           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     177             :     {
     178          99 :         FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     179             :         {
     180          96 :             IF( ( hOMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL )
     181             :             {
     182           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA data\n" ) );
     183             :             }
     184          96 :             set_zero_fx( hOMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS );
     185             :         }
     186             :     }
     187           1 :     set16_fx( hOMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF );
     188           1 :     set16_fx( hOMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF );
     189           1 :     set_zero_fx( hOMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS );
     190             : 
     191           5 :     FOR( i = 0; i < MAX_NUM_OBJECTS; i++ )
     192             :     {
     193           4 :         set32_fx( hOMasa->prev_object_dm_gains_fx[i], INV_SQRT_2_Q31, MASA_MAX_TRANSPORT_CHANNELS );
     194             :     }
     195             : 
     196             :     /* input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); */
     197           1 :     input_frame = extract_l( Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) );
     198         961 :     FOR( i = 0; i < input_frame; i++ )
     199             :     {
     200         960 :         hOMasa->interpolator_fx[i] = BASOP_Util_Divide1616_Scale( i, input_frame, &scale );
     201         960 :         move16();
     202         960 :         hOMasa->interpolator_fx[i] = shl( hOMasa->interpolator_fx[i], scale ); // Q15
     203         960 :         move16();
     204             :     }
     205             : 
     206           1 :     hOMasa->index_buffer_intensity = 0;
     207           1 :     move16();
     208             : 
     209           1 :     IF( ( hOMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL )
     210             :     {
     211           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     212             :     }
     213             : 
     214           1 :     IF( ( hOMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL )
     215             :     {
     216           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) );
     217             :     }
     218             : 
     219           1 :     generate_gridEq_fx( hOMasa->sph_grid16 );
     220             : 
     221           5 :     FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
     222             :     {
     223           4 :         set_zero_fx( hOMasa->energy_fx[i], MASA_FREQUENCY_BANDS );
     224             :     }
     225             : 
     226           1 :     set_zero_fx( hOMasa->ism_azimuth_fx, MAX_NUM_OBJECTS );
     227           1 :     set_zero_fx( hOMasa->ism_elevation_fx, MAX_NUM_OBJECTS );
     228             : 
     229           1 :     ( *hOMasaPtr ) = hOMasa;
     230             : 
     231           1 :     return error;
     232             : }
     233             : 
     234             : /*--------------------------------------------------------------------------*
     235             :  * ivas_omasa_ana_close()
     236             :  *
     237             :  * Close OMASA handle
     238             :  *--------------------------------------------------------------------------*/
     239             : 
     240        2664 : void ivas_omasa_ana_close(
     241             :     OMASA_ANA_HANDLE *hOMasa /* i/o: analysis OMASA handle */
     242             : )
     243             : {
     244             :     Word16 i, j;
     245             : 
     246        2664 :     test();
     247        2664 :     IF( hOMasa == NULL || *hOMasa == NULL )
     248             :     {
     249        2663 :         return;
     250             :     }
     251             : 
     252           5 :     FOR( i = 0; i < ( *hOMasa )->num_Cldfb_instances; i++ )
     253             :     {
     254           4 :         deleteCldfb_ivas_fx( &( ( *hOMasa )->cldfbAnaEnc[i] ) );
     255             :     }
     256             : 
     257           4 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     258             :     {
     259          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     260             :         {
     261          12 :             free( ( *hOMasa )->direction_vector_m_fx[i][j] );
     262          12 :             ( *hOMasa )->direction_vector_m_fx[i][j] = NULL;
     263             :         }
     264             : 
     265          15 :         FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ )
     266             :         {
     267          12 :             free( ( *hOMasa )->direction_vector_e[i][j] );
     268          12 :             ( *hOMasa )->direction_vector_e[i][j] = NULL;
     269             :         }
     270             : 
     271          99 :         FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
     272             :         {
     273          96 :             free( ( *hOMasa )->buffer_intensity_real_fx[i][j] );
     274          96 :             ( *hOMasa )->buffer_intensity_real_fx[i][j] = NULL;
     275             :         }
     276             : 
     277           3 :         free( ( *hOMasa )->direction_vector_m_fx[i] );
     278           3 :         ( *hOMasa )->direction_vector_m_fx[i] = NULL;
     279             : 
     280           3 :         free( ( *hOMasa )->direction_vector_e[i] );
     281           3 :         ( *hOMasa )->direction_vector_e[i] = NULL;
     282             :     }
     283             : 
     284           1 :     free( ( *hOMasa )->hMasaOut );
     285           1 :     ( *hOMasa )->hMasaOut = NULL;
     286           1 :     free( ( *hOMasa )->sph_grid16 );
     287           1 :     ( *hOMasa )->sph_grid16 = NULL;
     288             : 
     289           1 :     free( ( *hOMasa ) );
     290           1 :     ( *hOMasa ) = NULL;
     291             : 
     292           1 :     return;
     293             : }
     294             : 
     295             : /*--------------------------------------------------------------------------*
     296             :  * ivas_omasa_ana()
     297             :  *
     298             :  * OMASA analysis function
     299             :  *--------------------------------------------------------------------------*/
     300             : 
     301             : 
     302         150 : void ivas_omasa_ana_fx(
     303             :     OMASA_ANA_HANDLE hOMasa,           /* i/o: OMASA analysis handle                       */
     304             :     Word32 data_in_f_fx[][L_FRAME48k], /* i/o: Input / transport audio signals             */
     305             :     Word16 *data_in_q,
     306             :     const Word16 input_frame,     /* i  : Input frame size                            */
     307             :     const Word16 nchan_transport, /* i  : Number of transport channels                */
     308             :     const Word16 nchan_ism        /* i  : Number of objects for parameter analysis    */
     309             : )
     310             : {
     311             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     312             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     313             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     314             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     315             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
     316             :     Word16 spreadCoherence_q, sorroundingCoherence_q, energyRatio_q;
     317             : 
     318             :     /* Estimate MASA parameters from the objects */
     319         150 :     ivas_omasa_param_est_ana_fx( hOMasa, data_in_f_fx, *data_in_q, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, &energyRatio_q, spreadCoherence_fx, &spreadCoherence_q, surroundingCoherence_fx, &sorroundingCoherence_q, input_frame, nchan_ism );
     320             : 
     321             :     /* Create MASA metadata buffer from the estimated values */
     322         150 :     ivas_create_masa_out_meta_fx( hOMasa->hMasaOut, hOMasa->sph_grid16, nchan_transport, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, Q31, Q31, Q31 );
     323             : 
     324             :     /* Downmix */
     325         150 :     ivas_omasa_dmx_fx( data_in_f_fx, data_in_q, input_frame, nchan_transport, nchan_ism, hOMasa->ism_azimuth_fx, hOMasa->ism_elevation_fx, hOMasa->prev_object_dm_gains_fx, hOMasa->interpolator_fx );
     326             : 
     327         150 :     return;
     328             : }
     329             : 
     330             : 
     331             : /*--------------------------------------------------------------------------*
     332             :  * Local functions
     333             :  *--------------------------------------------------------------------------*/
     334             : 
     335             : /* Estimate MASA parameters from the objects */
     336             : 
     337             : 
     338         150 : static void ivas_omasa_param_est_ana_fx(
     339             :     OMASA_ANA_HANDLE hOMasa,
     340             :     Word32 data_f_fx[][L_FRAME48k],
     341             :     Word16 data_f_q,
     342             :     Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], // Q22
     343             :     Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],   // Q22
     344             :     Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
     345             :     Word16 *energyRatio_q,
     346             :     Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
     347             :     Word16 *spreadCoherence_q,
     348             :     Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS],
     349             :     Word16 *surroundingCoherence_q,
     350             :     const Word16 input_frame,
     351             :     const Word16 nchan_ism )
     352             : {
     353             :     Word16 ts, i, d, j;
     354             :     Word16 num_freq_bins, num_freq_bands, index;
     355             :     Word16 l_ts;
     356             : 
     357             :     Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
     358             :     Word32 Chnl_RealBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
     359             :     Word16 Chnl_RealBuffer_q[MAX_NUM_OBJECTS];
     360             :     Word16 Chnl_ImagBuffer_q[MAX_NUM_OBJECTS];
     361             :     Word32 Chnl_ImagBuffer_fx[MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX];
     362             :     Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     363             :     Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX];
     364             :     Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     365             :     Word16 intensity_real_q[MASA_FREQUENCY_BANDS];
     366             :     Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS];
     367             :     Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS];
     368         150 :     Word16 diffuseness_q = 0;
     369         150 :     move16();
     370             :     Word16 diffuseness_e[MASA_FREQUENCY_BANDS];
     371             :     Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS];
     372             : 
     373             :     Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS];
     374             :     Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS];
     375             :     Word32 norm_tmp_fx;
     376             : 
     377             :     Word32 dir_v_fx[DIRAC_NUM_DIMS] /*, L_tmp1, L_tmp2*/;
     378             :     Word16 dir_v_q /*, norm_tmp_q*/;
     379             :     Word16 band_m_idx, block_m_idx;
     380             : 
     381             :     Word16 mrange[2];
     382             :     Word16 brange[2];
     383             : 
     384         150 :     num_freq_bins = hOMasa->cldfbAnaEnc[0]->no_channels;
     385         150 :     move16();
     386         150 :     num_freq_bands = hOMasa->nbands;
     387         150 :     move16();
     388         150 :     l_ts = shr( input_frame, 4 );
     389             : 
     390             :     Word16 intensity_q;
     391             :     Word16 reference_power_q;
     392             : 
     393         150 :     set16_zero_fx( Chnl_RealBuffer_q, MAX_NUM_OBJECTS );
     394         150 :     set16_zero_fx( Chnl_ImagBuffer_q, MAX_NUM_OBJECTS );
     395             : 
     396             :     /* Compute ISM to FOA matrices */
     397         750 :     FOR( i = 0; i < nchan_ism; i++ )
     398             :     {
     399         600 :         hOMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31;
     400         600 :         move32();
     401         600 :         hOMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( Mpy_32_32( hOMasa->ism_azimuth_fx[i], 46603 /*32767/360*/ ) /*Q22+Q24-31=>Q15*/ ) ), getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ) ); // Q31
     402         600 :         move32();
     403         600 :         hOMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ), 16 ); // Q31
     404         600 :         move32();
     405         600 :         hOMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_azimuth_fx[i], 46603 /*2^24/360*/ ) ) ), getCosWord16R2( extract_l( Mpy_32_32( hOMasa->ism_elevation_fx[i], 46603 /*2^24/360*/ ) ) ) ); // Q31
     406         600 :         move32();
     407             :     }
     408             : 
     409             :     /* do processing over all CLDFB time slots */
     410         750 :     FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
     411             :     {
     412         600 :         mrange[0] = hOMasa->block_grouping[block_m_idx];
     413         600 :         move16();
     414         600 :         mrange[1] = hOMasa->block_grouping[block_m_idx + 1];
     415         600 :         move16();
     416             : 
     417       15000 :         FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
     418             :         {
     419       14400 :             hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0;
     420       14400 :             move32();
     421       14400 :             hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0;
     422       14400 :             move32();
     423       14400 :             hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0;
     424       14400 :             move32();
     425             : 
     426       14400 :             hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0;
     427       14400 :             move16();
     428       14400 :             hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0;
     429       14400 :             move16();
     430       14400 :             hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0;
     431       14400 :             move16();
     432             :         }
     433             : 
     434             :         /* Need to initialize renormalization_factors, and variables to be normalized */
     435             : 
     436         600 :         set_zero_fx( renormalization_factor_diff_fx, hOMasa->nbands );
     437         600 :         set16_fx( renormalization_factor_diff_e, 0, hOMasa->nbands );
     438         600 :         set_zero_fx( diffuseness_m_fx, hOMasa->nbands );
     439         600 :         set16_fx( diffuseness_e, 0, hOMasa->nbands );
     440         600 :         set_zero_fx( hOMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
     441         600 :         set16_fx( hOMasa->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
     442             : 
     443        3000 :         FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
     444             :         {
     445        2400 :             Word16 cr_q = MAX_16, ci_q = MAX_16, sf, c_e;
     446        2400 :             move16();
     447        2400 :             move16();
     448        2400 :             Word16 inp_q = data_f_q;
     449        2400 :             move16();
     450       12000 :             FOR( i = 0; i < nchan_ism; i++ )
     451             :             {
     452        9600 :                 inp_q = data_f_q;
     453        9600 :                 cldfbAnalysis_ts_fx_var_q( &( data_f_fx[i][i_mult( l_ts, ts )] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hOMasa->cldfbAnaEnc[i], &inp_q );
     454             : 
     455        9600 :                 cr_q = s_min( cr_q, L_norm_arr( Chnl_ImagBuffer_fx[i], l_ts ) );
     456        9600 :                 ci_q = s_min( ci_q, L_norm_arr( Chnl_RealBuffer_fx[i], l_ts ) );
     457             :             }
     458        2400 :             sf = sub( s_min( cr_q, ci_q ), 4 );
     459       12000 :             FOR( i = 0; i < nchan_ism; i++ )
     460             :             {
     461        9600 :                 scale_sig32( Chnl_RealBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
     462        9600 :                 scale_sig32( Chnl_ImagBuffer_fx[i], l_ts, sf ); // Q-> inp_q + sf
     463             :             }
     464        2400 :             inp_q = add( inp_q, sf );
     465        2400 :             c_e = sub( 31, inp_q );
     466             : 
     467             :             /* Compute channel-based energy for metadata processing */
     468       60000 :             FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ )
     469             :             {
     470       57600 :                 brange[0] = hOMasa->band_grouping[band_m_idx];
     471       57600 :                 move16();
     472       57600 :                 brange[1] = hOMasa->band_grouping[band_m_idx + 1];
     473       57600 :                 move16();
     474      201600 :                 FOR( j = brange[0]; j < brange[1]; j++ )
     475             :                 {
     476      720000 :                     FOR( i = 0; i < nchan_ism; i++ )
     477             :                     {
     478      576000 :                         Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); // Q-> 2*inp_q - 31, e = 31 - (2*inp_q - 31) = 62 - 2*inp_q = 2*(31 - inp_q) = 2*c_e
     479      576000 :                         hOMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->energy_fx[block_m_idx][band_m_idx], hOMasa->energy_e[block_m_idx][band_m_idx], temp, shl( c_e, 1 ), &hOMasa->energy_e[block_m_idx][band_m_idx] );
     480      576000 :                         move32();
     481             :                     }
     482             :                 }
     483             :             }
     484             : 
     485             :             /* Compute FOA */
     486             :             /* W */
     487             : 
     488        2400 :             Copy32( Chnl_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); // inp_q
     489        2400 :             Copy32( Chnl_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); // inp_q
     490             : 
     491        9600 :             FOR( i = 1; i < nchan_ism; i++ )
     492             :             {
     493        7200 :                 v_add_fixed_no_hdrm( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); // Q:  Chnl_RealBuffer_q
     494        7200 :                 v_add_fixed_no_hdrm( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); // Q:  Chnl_ImagBuffer_q
     495             :             }
     496             : 
     497             :             /* Y */
     498             : 
     499        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); // Q: Chnl_RealBuffer_q
     500        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     501             : 
     502        9600 :             FOR( i = 1; i < nchan_ism; i++ )
     503             :             {
     504        7200 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); // Q: Chnl_RealBuffer_q
     505        7200 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     506             :             }
     507             : 
     508             :             /* Z */
     509             : 
     510        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); // Q: Chnl_RealBuffer_q
     511        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     512             : 
     513        9600 :             FOR( i = 1; i < nchan_ism; i++ )
     514             :             {
     515        7200 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); // Q: Chnl_RealBuffer_q
     516        7200 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     517             :             }
     518             : 
     519        2400 :             v_multc_fixed( Chnl_RealBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); // Q: Chnl_RealBuffer_q
     520        2400 :             v_multc_fixed( Chnl_ImagBuffer_fx[0], hOMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     521             : 
     522        9600 :             FOR( i = 1; i < nchan_ism; i++ )
     523             :             {
     524        7200 :                 v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); // Q: Chnl_RealBuffer_q
     525        7200 :                 v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hOMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); // Q: Chnl_ImagBuffer_q
     526             :             }
     527        2400 :             computeIntensityVector_ana_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx, intensity_real_q, inp_q );
     528             : 
     529        2400 :             computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], 0, intensity_real_q ); /* Q direction_vector_fx = Q30*/
     530             :             /* Power estimation for diffuseness */
     531             : 
     532        2400 :             computeReferencePower_ana_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands, inp_q, &reference_power_q );
     533             : 
     534             :             /* Aligning intensity_real to a common Q-factor */
     535        2400 :             minimum_fx( intensity_real_q, num_freq_bands, &intensity_q );
     536             : 
     537             :             Word16 tmp;
     538       60000 :             FOR( i = 0; i < num_freq_bands; i++ )
     539             :             {
     540       57600 :                 tmp = sub( intensity_q, intensity_real_q[i] );
     541       57600 :                 intensity_real_fx[0][i] = L_shl( intensity_real_fx[0][i], tmp );
     542       57600 :                 move32();
     543       57600 :                 intensity_real_fx[1][i] = L_shl( intensity_real_fx[1][i], tmp );
     544       57600 :                 move32();
     545       57600 :                 intensity_real_fx[2][i] = L_shl( intensity_real_fx[2][i], tmp );
     546       57600 :                 move32();
     547             :             }
     548             : 
     549             :             /* Fill buffers of length "averaging_length" time slots for intensity and energy */
     550        2400 :             hOMasa->index_buffer_intensity = add( ( hOMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */
     551        2400 :             move16();
     552        2400 :             index = hOMasa->index_buffer_intensity;
     553        2400 :             move16();
     554             : 
     555        9600 :             FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
     556             :             {
     557             :                 /* only real part needed */
     558        7200 :                 Copy32( intensity_real_fx[i], &( hOMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); // intensity_q
     559             :             }
     560        2400 :             hOMasa->buffer_intensity_real_q[index - 1] = intensity_q;
     561        2400 :             move16();
     562        2400 :             Copy32( reference_power_fx[ts], &( hOMasa->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands );
     563        2400 :             hOMasa->buffer_energy_q[index - 1] = reference_power_q;
     564        2400 :             move16();
     565             : 
     566        2400 :             computeDiffuseness_fixed( hOMasa->buffer_intensity_real_fx, hOMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hOMasa->buffer_intensity_real_q, hOMasa->buffer_energy_q, &diffuseness_q ); // diffuseness_q=Q30
     567             : 
     568       60000 :             FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
     569             :             {
     570       57600 :                 norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*reference_power_q*/
     571       57600 :                 hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hOMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[0][block_m_idx][band_m_idx] );
     572       57600 :                 move32();
     573       57600 :                 hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hOMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[1][block_m_idx][band_m_idx] );
     574       57600 :                 move32();
     575       57600 :                 hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hOMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hOMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), sub( 31 + 1, reference_power_q ), &hOMasa->direction_vector_e[2][block_m_idx][band_m_idx] );
     576       57600 :                 move32();
     577             : 
     578       57600 :                 diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), 1 ), sub( 31, reference_power_q ), &diffuseness_e[band_m_idx] );
     579       57600 :                 move32();
     580       57600 :                 renormalization_factor_diff_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], reference_power_fx[ts][band_m_idx], sub( 31, reference_power_q ), &renormalization_factor_diff_e[band_m_idx] );
     581       57600 :                 move32();
     582             :             }
     583             :         }
     584             : 
     585       15000 :         FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
     586             :         {
     587       14400 :             Word16 max_e = MIN_16;
     588       14400 :             move16();
     589       57600 :             FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
     590             :             {
     591       43200 :                 max_e = s_max( max_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] );
     592             :             }
     593       14400 :             max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/
     594       57600 :             FOR( d = 0; d < DIRAC_NUM_DIMS; d++ )
     595             :             {
     596       43200 :                 dir_v_fx[d] = L_shr( hOMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( max_e, hOMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) );
     597       43200 :                 move32();
     598             :             }
     599       14400 :             dir_v_q = sub( 31, max_e );
     600             : 
     601       14400 :             ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, dir_v_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] );
     602             :         }
     603             : 
     604             :         /* Determine energy ratios */
     605       15000 :         FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
     606             :         {
     607             :             Word16 diffuseness_m_e;
     608       14400 :             IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) )
     609             :             {
     610       14400 :                 diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e );
     611       14400 :                 move32();
     612       14400 :                 diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) );
     613       14400 :                 diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31
     614       14400 :                 move32();
     615             :             }
     616             :             ELSE
     617             :             {
     618           0 :                 diffuseness_m_fx[band_m_idx] = 0;
     619           0 :                 move32();
     620             :             }
     621       14400 :             energyRatio_fx[block_m_idx][band_m_idx] = L_sub( ONE_IN_Q31, diffuseness_m_fx[band_m_idx] );
     622       14400 :             move32();
     623             :         }
     624             : 
     625             :         /* Set coherences to zero, as this mode is used at lowest bit rates where the coherences are not transmitted */
     626       15000 :         FOR( band_m_idx = 0; band_m_idx < hOMasa->nbands; band_m_idx++ )
     627             :         {
     628       14400 :             spreadCoherence_fx[block_m_idx][band_m_idx] = 0;
     629       14400 :             move32();
     630       14400 :             surroundingCoherence_fx[block_m_idx][band_m_idx] = 0;
     631       14400 :             move32();
     632             :         }
     633             :     }
     634         150 :     *energyRatio_q = Q31;
     635         150 :     *spreadCoherence_q = Q31;
     636         150 :     *surroundingCoherence_q = Q31;
     637         150 :     move16();
     638         150 :     move16();
     639         150 :     move16();
     640         150 :     return;
     641             : }
     642             : 
     643             : 
     644             : /* Compute downmix */
     645         150 : static void ivas_omasa_dmx_fx(
     646             :     Word32 data_in_f_fx[][L_FRAME48k],
     647             :     Word16 *data_in_q,
     648             :     const Word16 input_frame,
     649             :     const Word16 nchan_transport,
     650             :     const Word16 nchan_ism,
     651             :     const Word32 ism_azimuth_fx[MAX_NUM_OBJECTS],
     652             :     const Word32 ism_elevation_fx[MAX_NUM_OBJECTS],
     653             :     Word32 prev_gains_fx[][MASA_MAX_TRANSPORT_CHANNELS],
     654             :     const Word16 interpolator_fx[L_FRAME48k] )
     655             : {
     656             :     Word16 i, j, k, l, tmp1, tmp2;
     657             : 
     658             :     Word16 azimuth_fx, elevation_fx;
     659             :     Word16 gains_fx[MASA_MAX_TRANSPORT_CHANNELS];
     660             :     Word16 g1_fx, g2_fx, scale;
     661             :     Word32 data_out_f_fx[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k], L_tmp;
     662             :     Word16 max_e, tmp_e;
     663             :     Word16 in_e[960];
     664             :     Word16 data_e[4];
     665             : 
     666         450 :     FOR( i = 0; i < nchan_transport; i++ )
     667             :     {
     668         300 :         set_zero_fx( data_out_f_fx[i], input_frame );
     669             :     }
     670         150 :     set16_fx( data_e, 0, 4 );
     671         150 :     set16_fx( in_e, 0, 960 );
     672             : 
     673         750 :     FOR( i = 0; i < nchan_ism; i++ )
     674             :     {
     675             : 
     676         600 :         azimuth_fx = extract_l( L_shr( ism_azimuth_fx[i], Q22 ) );     // Q0
     677         600 :         elevation_fx = extract_l( L_shr( ism_elevation_fx[i], Q22 ) ); // Q0
     678             : 
     679         600 :         ivas_ism_get_stereo_gains_fx( azimuth_fx, elevation_fx, &gains_fx[0], &gains_fx[1] );
     680             : 
     681             :         /* Downmix using the panning gains */
     682        1800 :         FOR( j = 0; j < nchan_transport; j++ )
     683             :         {
     684        1200 :             test();
     685        1200 :             IF( abs_s( gains_fx[j] ) > 0 || L_abs( prev_gains_fx[i][j] ) > 0 )
     686             :             {
     687     1060944 :                 FOR( k = 0; k < input_frame; k++ )
     688             :                 {
     689             : 
     690     1059840 :                     g1_fx = interpolator_fx[k]; // Q15
     691     1059840 :                     move16();
     692     1059840 :                     scale = BASOP_Util_Add_MantExp( 16384, 1, negate( g1_fx ), 0, &g2_fx );
     693             : 
     694     1059840 :                     tmp1 = mult( g1_fx, gains_fx[j] );
     695     1059840 :                     tmp2 = mult( g2_fx, (Word16) L_shr( prev_gains_fx[i][j], 16 ) ); // Q: ( ( ( 15 - scale ) + ( Q31 - Q16 ) ) - Q15 ) -> ( 15 - scale )
     696     1059840 :                     scale = BASOP_Util_Add_MantExp( tmp1, 0, tmp2, scale, &tmp1 );
     697             : 
     698     1059840 :                     L_tmp = data_in_f_fx[i][k]; // data_in_q
     699     1059840 :                     move32();
     700     1059840 :                     tmp_e = sub( 31, *data_in_q );
     701     1059840 :                     move16();
     702             : 
     703     1059840 :                     L_tmp = Mpy_32_16_1( L_tmp, tmp1 );
     704     1059840 :                     scale = add( scale, tmp_e );
     705             : 
     706     1059840 :                     data_out_f_fx[j][k] = BASOP_Util_Add_Mant32Exp( data_out_f_fx[j][k], data_e[j], L_tmp, scale, &in_e[k] );
     707     1059840 :                     move32();
     708             :                 }
     709        1104 :                 max_e = in_e[0];
     710        1104 :                 move16();
     711     1059840 :                 FOR( l = 1; l < L_FRAME48k; l++ )
     712             :                 {
     713     1058736 :                     IF( LT_16( max_e, in_e[l] ) )
     714             :                     {
     715        2363 :                         max_e = in_e[l];
     716        2363 :                         move16();
     717             :                     }
     718             :                 }
     719             : 
     720     1060944 :                 FOR( l = 0; l < L_FRAME48k; l++ )
     721             :                 {
     722     1059840 :                     data_out_f_fx[j][l] = L_shr( data_out_f_fx[j][l], sub( max_e, in_e[l] ) ); // exponent: max_e, Q: ( 15 - max_e )
     723     1059840 :                     move32();
     724             :                 }
     725        1104 :                 data_e[j] = max_e;
     726        1104 :                 move16();
     727             :             }
     728             : 
     729        1200 :             prev_gains_fx[i][j] = L_deposit_h( gains_fx[j] ); // Q31
     730        1200 :             move32();
     731             :         }
     732             :     }
     733             : 
     734         150 :     max_e = data_e[0];
     735         150 :     move16();
     736         300 :     FOR( i = 1; i < nchan_transport; i++ )
     737             :     {
     738         150 :         if ( LT_16( max_e, data_e[i] ) )
     739             :         {
     740          50 :             max_e = data_e[i];
     741          50 :             move16();
     742             :         }
     743             :     }
     744             : 
     745         450 :     FOR( i = 0; i < nchan_transport; i++ )
     746             :     {
     747      288300 :         FOR( j = 0; j < input_frame; j++ )
     748             :         {
     749      288000 :             data_out_f_fx[i][j] = L_shr( data_out_f_fx[i][j], sub( max_e, data_e[i] ) ); // exponent: max_e, Q: ( 15 - max_e )
     750      288000 :             move32();
     751             :         }
     752             :     }
     753             : 
     754         450 :     FOR( i = 0; i < nchan_transport; i++ )
     755             :     {
     756         300 :         Copy32( data_out_f_fx[i], data_in_f_fx[i], input_frame );
     757         300 :         *data_in_q = sub( 31, max_e );
     758         300 :         move16();
     759             :     }
     760             : 
     761         150 :     return;
     762             : }
     763             : 
     764             : /* Compute downmix */
     765             : 
     766             : 
     767             : /*--------------------------------------------------------------------------*
     768             :  * computeIntensityVector_ana()
     769             :  *
     770             :  *
     771             :  *--------------------------------------------------------------------------*/
     772             : 
     773        9600 : void computeIntensityVector_ana_fx(
     774             :     const Word16 *band_grouping,                                  /* i  : Band grouping for estimation   */
     775             :     Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i  : Real part of input signal   Qx */
     776             :     Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i  : Imag part of input sig      Qx */
     777             :     const Word16 num_frequency_bands,                             /* i  : Number of frequency bands      */
     778             :     Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS],  /* o  : Intensity           */
     779             :     Word16 q_intensity_real[MASA_FREQUENCY_BANDS],
     780             :     Word16 inp_q )
     781             : {
     782             :     /* Reminder
     783             :      * X = a + ib; Y = c + id
     784             :      * X*Y = ac - bd + i(ad +bc)
     785             :      */
     786             :     Word16 i, j;
     787             :     Word32 real, img;
     788             :     Word16 brange[2];
     789        9600 :     Word16 shift_value = add( shl( inp_q, 1 ), 1 );
     790             :     Word16 tmp_norm;
     791      240000 :     FOR( i = 0; i < num_frequency_bands; i++ )
     792             :     {
     793      230400 :         brange[0] = band_grouping[i];
     794      230400 :         move16();
     795      230400 :         brange[1] = band_grouping[i + 1];
     796      230400 :         move16();
     797      230400 :         Word16 num_bins = sub( brange[1], brange[0] );
     798      230400 :         Word16 gb = find_guarded_bits_fx( num_bins );
     799             :         Word16 norm;
     800             : 
     801      230400 :         Word64 tmp_1 = 0, tmp_2 = 0, tmp_3 = 0;
     802      230400 :         move64();
     803      230400 :         move64();
     804      230400 :         move64();
     805             : 
     806      806400 :         FOR( j = brange[0]; j < brange[1]; j++ )
     807             :         {
     808      576000 :             real = Cldfb_RealBuffer[0][j];
     809      576000 :             move32();
     810      576000 :             img = Cldfb_ImagBuffer[0][j];
     811      576000 :             move32();
     812             :             Word64 t1, t2, t3;
     813      576000 :             t1 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[3][j], real ), Cldfb_ImagBuffer[3][j], img ); /* 2 * q_cldfb + 1 */
     814      576000 :             t2 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[1][j], real ), Cldfb_ImagBuffer[1][j], img ); /* 2 * q_cldfb + 1 */
     815      576000 :             t3 = W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[2][j], real ), Cldfb_ImagBuffer[2][j], img ); /* 2 * q_cldfb + 1 */
     816      576000 :             t1 = W_shr( t1, gb );
     817      576000 :             t2 = W_shr( t2, gb );
     818      576000 :             t3 = W_shr( t3, gb );
     819             :             /* Intensity is XYZ order, audio is WYZX order. */
     820      576000 :             tmp_1 = W_add( tmp_1, t1 ); /* 2 * q_cldfb + 1 */
     821      576000 :             tmp_2 = W_add( tmp_2, t2 ); /* 2 * q_cldfb + 1 */
     822      576000 :             tmp_3 = W_add( tmp_3, t3 ); /* 2 * q_cldfb + 1 */
     823             :         }
     824      230400 :         norm = 63;
     825      230400 :         move16();
     826      230400 :         IF( tmp_1 != 0 )
     827             :         {
     828      230400 :             tmp_norm = W_norm( tmp_1 );
     829      230400 :             norm = s_min( norm, tmp_norm );
     830             :         }
     831      230400 :         IF( tmp_2 != 0 )
     832             :         {
     833      229632 :             tmp_norm = W_norm( tmp_2 );
     834      229632 :             norm = s_min( norm, tmp_norm );
     835             :         }
     836      230400 :         IF( tmp_3 != 0 )
     837             :         {
     838      172416 :             tmp_norm = W_norm( tmp_3 );
     839      172416 :             norm = s_min( norm, tmp_norm );
     840             :         }
     841      230400 :         norm = sub( norm, 32 );
     842      230400 :         intensity_real[0][i] = W_shl_sat_l( tmp_1, norm ); // shift_value - (gb - norm)
     843      230400 :         move32();
     844      230400 :         intensity_real[1][i] = W_shl_sat_l( tmp_2, norm ); // shift_value - (gb - norm)
     845      230400 :         move32();
     846      230400 :         intensity_real[2][i] = W_shl_sat_l( tmp_3, norm ); // shift_value - (gb - norm)
     847      230400 :         q_intensity_real[i] = sub( shift_value, sub( gb, norm ) );
     848      230400 :         move16();
     849             :     }
     850             : 
     851        9600 :     return;
     852             : }
     853             : /*--------------------------------------------------------------------------*
     854             :  * computeIntensityVector_ana()
     855             :  *
     856             :  *
     857             :  *--------------------------------------------------------------------------*/
     858             : 
     859             : 
     860             : /*--------------------------------------------------------------------------*
     861             :  * computeReferencePower_ana()
     862             :  *
     863             :  *
     864             :  *--------------------------------------------------------------------------*/
     865             : 
     866        7200 : void computeReferencePower_ana_fx(
     867             :     const Word16 *band_grouping,                                  /* i  : Band grouping for estimation                  */
     868             :     Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i  : Real part of input signal    input_q          */
     869             :     Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i  : Imag part of input signal    input_q          */
     870             :     Word32 *reference_power,                                      /* o  : Estimated power                               */
     871             :     const Word16 num_freq_bands,                                  /* i  : Number of frequency bands                     */
     872             :     const Word16 input_q,                                         /* i  : Q-factor Real and Imag part of input signal   */
     873             :     Word16 *reference_power_q                                     /* o  : Q-factor of the estimated power               */
     874             : )
     875             : {
     876             :     Word16 brange[2];
     877             :     Word16 ch_idx, i, j, s;
     878             :     Word64 reference_power64[MASA_FREQUENCY_BANDS];
     879      180000 :     FOR( i = 0; i < num_freq_bands; i++ )
     880             :     {
     881      172800 :         brange[0] = band_grouping[i];
     882      172800 :         move16();
     883      172800 :         brange[1] = band_grouping[i + 1];
     884      172800 :         move16();
     885      172800 :         reference_power64[i] = 0;
     886      172800 :         move64();
     887             : 
     888      864000 :         FOR( ch_idx = 0; ch_idx < FOA_CHANNELS; ch_idx++ )
     889             :         {
     890             :             /* abs()^2 */
     891     2419200 :             FOR( j = brange[0]; j < brange[1]; j++ )
     892             :             {
     893     1728000 :                 reference_power64[i] = W_add( W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[ch_idx][j], Cldfb_RealBuffer[ch_idx][j] ), Cldfb_ImagBuffer[ch_idx][j], Cldfb_ImagBuffer[ch_idx][j] ), reference_power64[i] ); // 2 * input_q + 1
     894     1728000 :                 move64();
     895             :             }
     896             :         }
     897             :     }
     898             : 
     899        7200 :     s = sub( W_norm_arr( reference_power64, num_freq_bands ), 1 );
     900      180000 :     FOR( i = 0; i < num_freq_bands; i++ )
     901             :     {
     902      172800 :         reference_power[i] = W_extract_h( W_shl( reference_power64[i], s ) ); // 2 * input_q + 1 + s - 32
     903      172800 :         move32();
     904             :     }
     905        7200 :     *reference_power_q = sub( add( shl( input_q, 1 ), s ), 30 ); /* Bypassing the v_multc ,so output q = 2 * input_q + s - 30 */
     906        7200 :     move16();
     907             : 
     908        7200 :     return;
     909             : }

Generated by: LCOV version 1.14