LCOV - code coverage report
Current view: top level - lib_dec - ivas_out_setup_conversion_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 673 709 94.9 %
Date: 2025-10-13 22:24:20 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 <stdint.h>
      34             : #include "options.h"
      35             : #include <math.h>
      36             : #include <assert.h>
      37             : #include "prot_fx.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "ivas_rom_com.h"
      40             : #include "ivas_rom_rend.h"
      41             : #include "wmc_auto.h"
      42             : #include "ivas_prot_fx.h"
      43             : 
      44             : #include "debug.h"
      45             : 
      46             : /*----------------------------------------------------------------------------------*
      47             :  * Local constants
      48             :  *----------------------------------------------------------------------------------*/
      49             : 
      50             : 
      51             : #define LS_OUT_CONV_SMOOTHING_FACTOR_Q31 93415539
      52             : #define LS_OUT_CONV_CLIP_FACTOR_MAX_Q30  2147483647
      53             : #define LS_OUT_CONV_CLIP_FACTOR_MIN_Q30  322122547
      54             : 
      55             : 
      56             : /*----------------------------------------------------------------------------------*
      57             :  * Local functions
      58             :  *----------------------------------------------------------------------------------*/
      59             : 
      60     3637445 : static void ivas_lssetupconversion_computeEQFactor_fx(
      61             :     Word32 *outputEnergy,
      62             :     Word16 output_exp,
      63             :     Word32 *inputEnergy,
      64             :     Word16 input_exp,
      65             :     Word32 *EQ )
      66             : {
      67     3637445 :     test();
      68     3637445 :     IF( ( *outputEnergy == 0 ) && ( *inputEnergy == 0 ) )
      69             :     {
      70      870908 :         *EQ = ONE_IN_Q30; // Q30
      71      870908 :         move32();
      72      870908 :         return;
      73             :     }
      74             :     /* Compute the Equalization Gain */
      75             :     Word16 tmp_e;
      76     2766537 :     Word16 tmp = BASOP_Util_Divide3232_Scale( *outputEnergy, L_add( EPSILON_FX, *inputEnergy ), &tmp_e );
      77     2766537 :     tmp_e = add( tmp_e, sub( output_exp, input_exp ) );
      78     2766537 :     Word32 tmp_32 = L_deposit_h( tmp );
      79     2766537 :     tmp_32 = Sqrt32( tmp_32, &tmp_e );
      80     2766537 :     *EQ = L_shr_sat( tmp_32, sub( 1, tmp_e ) ); // range of EQ in float 0.3 - 2.0
      81     2766537 :     move32();
      82             : 
      83     2766537 :     *EQ = L_min( *EQ, LS_OUT_CONV_CLIP_FACTOR_MAX_Q30 );
      84     2766537 :     *EQ = L_max( *EQ, LS_OUT_CONV_CLIP_FACTOR_MIN_Q30 );
      85     2766537 :     move32();
      86     2766537 :     move32();
      87             : 
      88     2766537 :     return;
      89             : }
      90             : 
      91             : 
      92          69 : static void ivas_lssetupconversion_mdct_init_bands_fx(
      93             :     const Word16 output_frame, /* i  : output frame length             */
      94             :     const Word16 tcx_mode,     /* i  : tcx mode (TCX10, TCX 20)        */
      95             :     Word16 *sfbOffset,         /* o  : sfb offset table                */
      96             :     Word16 *sfbCnt             /* o  : number of sfbs                  */
      97             : )
      98             : {
      99             :     SpectrumWarping const *lpcBndsParam;
     100             :     Word16 i, cnt, specStartOffset, L_frameTCX;
     101             :     const UWord8 *sfbWidths;
     102             : 
     103          69 :     IF( EQ_16( tcx_mode, TCX_20_CORE ) )
     104             :     {
     105          69 :         L_frameTCX = output_frame;
     106          69 :         move16();
     107             :     }
     108             :     ELSE
     109             :     {
     110           0 :         L_frameTCX = shr( output_frame, 1 );
     111             :     }
     112             : 
     113             : 
     114          69 :     SWITCH( output_frame )
     115             :     {
     116          69 :         case L_FRAME48k:
     117             :         case L_FRAME32k:
     118          69 :             lpcBndsParam = sw32000Hz;
     119          69 :             BREAK;
     120           0 :         case L_FRAME25_6k:
     121           0 :             lpcBndsParam = sw25600Hz;
     122           0 :             BREAK;
     123           0 :         case L_FRAME16k:
     124           0 :             lpcBndsParam = sw16000Hz;
     125           0 :             BREAK;
     126           0 :         default:
     127           0 :             assert( !"Subband division not defined for this frame size" );
     128             :             return;
     129             :     }
     130             : 
     131          69 :     IF( EQ_16( tcx_mode, TCX_20_CORE ) )
     132             :     {
     133          69 :         sfbWidths = lpcBndsParam->bandLengthsTCX20;
     134          69 :         cnt = 64;
     135          69 :         move16();
     136             :     }
     137             :     ELSE
     138             :     {
     139           0 :         sfbWidths = lpcBndsParam->bandLengthsTCX10;
     140           0 :         cnt = 32;
     141           0 :         move16();
     142             :     }
     143             : 
     144             :     /* calc sfb offsets */
     145          69 :     specStartOffset = 0;
     146          69 :     move16();
     147             : 
     148        4485 :     FOR( i = 0; i < cnt; i++ )
     149             :     {
     150        4416 :         sfbOffset[i] = s_min( specStartOffset, L_frameTCX );
     151        4416 :         move16();
     152        4416 :         specStartOffset = add( specStartOffset, sfbWidths[i] );
     153             : 
     154        4416 :         IF( GE_16( sfbOffset[i], L_frameTCX ) )
     155             :         {
     156           0 :             BREAK;
     157             :         }
     158             :     }
     159             : 
     160          69 :     *sfbCnt = i;
     161          69 :     move16();
     162          69 :     sfbOffset[*sfbCnt] = s_min( specStartOffset, L_frameTCX );
     163          69 :     move16();
     164             : 
     165          69 :     IF( LT_16( sfbOffset[*sfbCnt], L_frameTCX ) )
     166             :     {
     167          66 :         Word16 nMissingBins = sub( L_frameTCX, sfbOffset[*sfbCnt] );
     168             : 
     169          66 :         IF( LT_16( shr( (Word16) sfbWidths[i], 1 ), nMissingBins ) )
     170             :         {
     171          66 :             ( *sfbCnt ) = add( ( *sfbCnt ), 1 );
     172          66 :             move16();
     173             :         }
     174          66 :         sfbOffset[*sfbCnt] = L_frameTCX;
     175          66 :         move16();
     176             :     }
     177             : 
     178          69 :     return;
     179             : }
     180             : 
     181             : 
     182           1 : static void get_custom_ls_conversion_matrix_fx(
     183             :     const EFAP_HANDLE hEFAPdata,                 /* i  : EFAP handle                            */
     184             :     const IVAS_OUTPUT_SETUP hTransSetup,         /* i  : Transport channel configuration handle */
     185             :     const LSSETUP_CUSTOM_HANDLE hLsSetupCustom,  /* i  : Custom LS Setup handle                 */
     186             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion /* o  : LS Setup Conversion Handle             */
     187             : )
     188             : {
     189             :     Word16 ch_in, ch_in_woLFE;
     190             :     Word16 ch_out, ch_out_woLFE;
     191             :     Word16 nchan_in, nchan_out;
     192             :     Word16 lfe_in_idx, lfe_out_idx;
     193             : 
     194             :     Word32 dmxCoeff_LFE;
     195             :     Word32 tmp_gains[MAX_OUTPUT_CHANNELS];
     196             : 
     197           1 :     lfe_in_idx = -1;
     198           1 :     move16();
     199           1 :     lfe_out_idx = -1;
     200           1 :     move16();
     201             : 
     202           1 :     nchan_in = add( hTransSetup.nchan_out_woLFE, hTransSetup.num_lfe );
     203           1 :     nchan_out = add( hLsSetupCustom->num_spk, hLsSetupCustom->num_lfe );
     204             : 
     205             :     /* The below code will need to be restructured in case additional LFEs must be supported */
     206           1 :     if ( hTransSetup.num_lfe > 0 )
     207             :     {
     208           1 :         lfe_in_idx = hTransSetup.index_lfe[0];
     209           1 :         move16();
     210             :     }
     211           1 :     if ( hLsSetupCustom->num_lfe > 0 )
     212             :     {
     213           0 :         lfe_out_idx = hLsSetupCustom->lfe_idx[0];
     214           0 :         move16();
     215             :     }
     216             : 
     217           1 :     IF( EQ_16( hTransSetup.nchan_out_woLFE, 1 ) )
     218             :     {
     219           0 :         dmxCoeff_LFE = ONE_IN_Q30;
     220           0 :         move32();
     221             :     }
     222             :     ELSE
     223             :     {
     224           1 :         dmxCoeff_LFE = L_shl( (Word32) div_s( 1, hTransSetup.nchan_out_woLFE ), Q15 ); // Q30
     225             :     }
     226             : 
     227           7 :     FOR( ( ch_in = 0, ch_in_woLFE = 0 ); ch_in < nchan_in; ( ch_in++, ch_in_woLFE++ ) )
     228             :     {
     229           6 :         IF( EQ_16( lfe_in_idx, ch_in ) )
     230             :         {
     231           1 :             IF( lfe_out_idx >= 0 )
     232             :             {
     233             :                 /* re-route LFE */
     234           0 :                 hLsSetUpConversion->dmxMtx_fx[ch_in][lfe_out_idx] = ONE_IN_Q30;
     235           0 :                 move32();
     236             :             }
     237             :             ELSE
     238             :             {
     239             :                 /* mix the LFE to all channels */
     240           1 :                 set32_fx( hLsSetUpConversion->dmxMtx_fx[ch_in], dmxCoeff_LFE, nchan_out );
     241             :             }
     242             : 
     243           1 :             ch_in_woLFE = sub( ch_in_woLFE, 1 );
     244             :         }
     245           5 :         ELSE IF( NE_16( lfe_out_idx, ch_in ) )
     246             :         {
     247             :             /* Set the values of hLsSetUpConversion->dmxMtx to EFAP gains, skipping LFE */
     248           5 :             efap_determine_gains_fx( hEFAPdata, tmp_gains, hTransSetup.ls_azimuth_fx[ch_in_woLFE], hTransSetup.ls_elevation_fx[ch_in_woLFE], EFAP_MODE_EFAP );
     249             : 
     250          85 :             FOR( ( ch_out = 0, ch_out_woLFE = 0 ); ch_out < nchan_out; ( ch_out++, ch_out_woLFE++ ) )
     251             :             {
     252          80 :                 IF( EQ_16( lfe_out_idx, ch_out ) )
     253             :                 {
     254           0 :                     ch_out_woLFE = sub( ch_out_woLFE, 1 );
     255             :                 }
     256             :                 ELSE
     257             :                 {
     258          80 :                     hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; // Q30
     259          80 :                     move32();
     260             :                 }
     261             :             }
     262             :         }
     263             :     }
     264             : 
     265           1 :     return;
     266             : }
     267             : 
     268         125 : static ivas_error get_ls_conversion_matrix_fx(
     269             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion,
     270             :     const AUDIO_CONFIG input_config,
     271             :     const AUDIO_CONFIG output_config )
     272             : {
     273             :     Word16 i, k;
     274             :     Word16 ch_in, ch_out;
     275             :     Word16 nchan_in, nchan_out;
     276             :     Word16 index;
     277             :     Word32 value;
     278             :     const LS_CONVERSION_MATRIX_FX *conversion_matrix_fx;
     279             : 
     280         125 :     conversion_matrix_fx = NULL;
     281             : 
     282         125 :     nchan_in = audioCfg2channels( input_config );
     283         125 :     nchan_out = audioCfg2channels( output_config );
     284             : 
     285             :     /* Search the table for a mapping */
     286        3437 :     FOR( i = 0; i < LS_SETUP_CONVERSION_NUM_MAPPINGS; i++ )
     287             :     {
     288        3437 :         test();
     289        3437 :         IF( ( EQ_32( input_config, ls_conversion_mapping_fx[i].input_config ) ) && ( EQ_32( output_config, ls_conversion_mapping_fx[i].output_config ) ) )
     290             :         {
     291             :             /* Special handling for MONO and STEREO downmix */
     292         125 :             test();
     293         125 :             IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) )
     294             :             {
     295          82 :                 FOR( ( ch_in = 0, k = 0 ); ch_in < nchan_in; ( ch_in++, k++ ) )
     296             :                 {
     297             :                     /* Skip two rows in the matrix for 5.1.x formats */
     298          74 :                     test();
     299          74 :                     test();
     300          74 :                     IF( EQ_16( ch_in, 6 ) && ( EQ_32( input_config, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( input_config, IVAS_AUDIO_CONFIG_5_1_4 ) ) )
     301             :                     {
     302           1 :                         k = add( k, 2 );
     303             :                     }
     304             : 
     305         216 :                     FOR( ch_out = 0; ch_out < nchan_out; ch_out++ )
     306             :                     {
     307         142 :                         IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) )
     308             :                         {
     309           6 :                             hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = ls_conversion_cicpX_mono_fx[k][ch_out]; // Q30
     310           6 :                             move32();
     311             :                         }
     312             :                         ELSE
     313             :                         {
     314         136 :                             hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = ls_conversion_cicpX_stereo_fx[k][ch_out]; // Q30
     315         136 :                             move32();
     316             :                         }
     317             :                     }
     318             :                 }
     319           8 :                 return IVAS_ERR_OK;
     320             :             }
     321             :             ELSE
     322             :             {
     323         117 :                 conversion_matrix_fx = ls_conversion_mapping_fx[i].conversion_matrix_fx;
     324             : 
     325             :                 /* If a mapping is defined with a NULL matrix, 1:1 upmix of input channels */
     326         117 :                 IF( conversion_matrix_fx == NULL )
     327             :                 {
     328         812 :                     FOR( k = 0; k < nchan_in; k++ )
     329             :                     {
     330         696 :                         hLsSetUpConversion->dmxMtx_fx[k][k] = ONE_IN_Q30;
     331         696 :                         move32();
     332             :                     }
     333         116 :                     return IVAS_ERR_OK;
     334             :                 }
     335             :                 ELSE
     336             :                 {
     337           9 :                     FOR( k = 1; k < ( conversion_matrix_fx[0].index + 1 ); k++ )
     338             :                     {
     339           8 :                         index = conversion_matrix_fx[k].index;
     340           8 :                         move16();
     341           8 :                         value = conversion_matrix_fx[k].value; // Q30
     342           8 :                         move16();
     343             : 
     344           8 :                         IF( index != 0 )
     345             :                         {
     346           7 :                             ch_in = idiv1616( index, nchan_out );
     347             :                         }
     348             :                         ELSE
     349             :                         {
     350           1 :                             ch_in = 0;
     351           1 :                             move16();
     352             :                         }
     353           8 :                         ch_out = index % nchan_out;
     354           8 :                         move16();
     355             : 
     356           8 :                         hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = value; // Q30
     357           8 :                         move32();
     358             :                     }
     359             :                 }
     360           1 :                 return IVAS_ERR_OK;
     361             :             }
     362             :         }
     363             :     }
     364             : 
     365           0 :     return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "The conversion matrix between these formats is not defined!\n" );
     366             : }
     367             : 
     368             : 
     369             : /*-------------------------------------------------------------------------
     370             :  * ivas_ls_setup_conversion_open()
     371             :  *
     372             :  * Open the LS configuration Conversion Module
     373             :  *-------------------------------------------------------------------------*/
     374             : 
     375         126 : ivas_error ivas_ls_setup_conversion_open_fx(
     376             :     Decoder_Struct *st_ivas /* i/o: IVAS decoder structure  */
     377             : )
     378             : {
     379             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
     380             :     Word16 chIdx, inChannels, outChannels;
     381             :     Word16 output_frame;
     382             :     Word32 output_Fs;
     383             :     Word16 paramUpmixMonoStereo;
     384             :     ivas_error error;
     385             : 
     386         126 :     test();
     387         126 :     test();
     388         126 :     test();
     389         126 :     IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) && ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) ) )
     390             :     {
     391           1 :         paramUpmixMonoStereo = TRUE;
     392           1 :         move16();
     393             :     }
     394             :     ELSE
     395             :     {
     396         125 :         paramUpmixMonoStereo = FALSE;
     397         125 :         move16();
     398             :     }
     399         126 :     output_Fs = st_ivas->hDecoderConfig->output_Fs;
     400         126 :     move32();
     401         126 :     outChannels = st_ivas->hDecoderConfig->nchan_out;
     402         126 :     move16();
     403         126 :     output_frame = (Word16) ( output_Fs / FRAMES_PER_SEC );
     404             : 
     405             :     /* Allocate memory to the handle */
     406         126 :     IF( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL )
     407             :     {
     408           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
     409             :     }
     410             : 
     411         126 :     assert( LE_16( outChannels, MAX_OUTPUT_CHANNELS ) );
     412             : 
     413         126 :     IF( EQ_32( st_ivas->renderer_type, RENDERER_MC_PARAMMC ) )
     414             :     {
     415          57 :         inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
     416          57 :         hLsSetUpConversion->sfbCnt = (Word16) ( L_add( output_Fs, 400 ) / CLDFB_BANDWIDTH );
     417         715 :         FOR( chIdx = 0; chIdx < outChannels; chIdx++ )
     418             :         {
     419         658 :             IF( ( hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
     420             :             {
     421           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
     422             :             }
     423         658 :             IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = (Word32 *) malloc( hLsSetUpConversion->sfbCnt * sizeof( Word32 ) ) ) == NULL )
     424             :             {
     425           0 :                 return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
     426             :             }
     427         658 :             set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
     428         658 :             hLsSetUpConversion->te_prev_exp[chIdx] = 0;
     429         658 :             move16();
     430         658 :             set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[chIdx], 0, hLsSetUpConversion->sfbCnt );
     431         658 :             hLsSetUpConversion->dmx_prev_exp[chIdx] = 0;
     432         658 :             move16();
     433             :         }
     434         311 :         FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
     435             :         {
     436         254 :             hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
     437         254 :             hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
     438             :         }
     439             :     }
     440             :     ELSE
     441             :     {
     442          69 :         test();
     443          69 :         IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) )
     444             :         {
     445           1 :             IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
     446             :             {
     447           1 :                 inChannels = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 );
     448             :             }
     449             :             ELSE
     450             :             {
     451           0 :                 inChannels = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
     452             :             }
     453             :         }
     454             :         ELSE
     455             :         {
     456          68 :             inChannels = st_ivas->nchan_transport;
     457          68 :             move16();
     458             :         }
     459             : 
     460             :         /*Initialization of MDCT bands with TCX20 resolution */
     461          69 :         ivas_lssetupconversion_mdct_init_bands_fx( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt );
     462          69 :         IF( ( hLsSetUpConversion->targetEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
     463             :         {
     464           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
     465             :         }
     466          69 :         IF( ( hLsSetUpConversion->dmxEnergyPrev_fx[0] = (Word32 *) malloc( ( MAX_SFB + 2 ) * sizeof( Word32 ) ) ) == NULL )
     467             :         {
     468           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) );
     469             :         }
     470             : 
     471        1104 :         FOR( chIdx = 1; chIdx < MAX_CICP_CHANNELS; chIdx++ )
     472             :         {
     473        1035 :             hLsSetUpConversion->targetEnergyPrev_fx[chIdx] = NULL;
     474        1035 :             hLsSetUpConversion->dmxEnergyPrev_fx[chIdx] = NULL;
     475             :         }
     476          69 :         set32_fx( hLsSetUpConversion->targetEnergyPrev_fx[0], 0, MAX_SFB + 2 );
     477          69 :         set32_fx( hLsSetUpConversion->dmxEnergyPrev_fx[0], 0, MAX_SFB + 2 );
     478             : 
     479          69 :         hLsSetUpConversion->te_prev_exp[0] = 0;
     480          69 :         hLsSetUpConversion->dmx_prev_exp[0] = 0;
     481          69 :         move16();
     482          69 :         move16();
     483             :     }
     484             : 
     485             :     /* Initialize the DMX conversion matrix */
     486         910 :     FOR( chIdx = 0; chIdx < inChannels; chIdx++ )
     487             :     {
     488             :         /* Allocate memory depending on the number of output channels */
     489         784 :         IF( ( hLsSetUpConversion->dmxMtx_fx[chIdx] = (Word32 *) malloc( outChannels * sizeof( Word32 ) ) ) == NULL )
     490             :         {
     491           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) );
     492             :         }
     493         784 :         set32_fx( hLsSetUpConversion->dmxMtx_fx[chIdx], 0, outChannels );
     494             :     }
     495             : 
     496        1358 :     FOR( ; chIdx < MAX_CICP_CHANNELS; chIdx++ )
     497             :     {
     498        1232 :         hLsSetUpConversion->dmxMtx_fx[chIdx] = NULL;
     499             :     }
     500             : 
     501         126 :     IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
     502             :     {
     503           1 :         get_custom_ls_conversion_matrix_fx( st_ivas->hEFAPdata, st_ivas->hTransSetup, st_ivas->hLsSetupCustom, hLsSetUpConversion );
     504             :     }
     505             :     ELSE
     506             :     {
     507         125 :         IF( NE_32( st_ivas->transport_config, IVAS_AUDIO_CONFIG_INVALID ) )
     508             :         {
     509         125 :             IF( EQ_16( paramUpmixMonoStereo, TRUE ) )
     510             :             {
     511           1 :                 IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, IVAS_AUDIO_CONFIG_5_1_2, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
     512             :                 {
     513           0 :                     return error;
     514             :                 }
     515             :             }
     516             :             ELSE
     517             :             {
     518         124 :                 IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->transport_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
     519             :                 {
     520           0 :                     return error;
     521             :                 }
     522             :             }
     523             :         }
     524             :         ELSE
     525             :         {
     526           0 :             IF( ( error = get_ls_conversion_matrix_fx( hLsSetUpConversion, st_ivas->intern_config, st_ivas->hDecoderConfig->output_config ) ) != IVAS_ERR_OK )
     527             :             {
     528           0 :                 return error;
     529             :             }
     530             :         }
     531             :     }
     532             : 
     533         126 :     st_ivas->hLsSetUpConversion = hLsSetUpConversion;
     534             : 
     535         126 :     return IVAS_ERR_OK;
     536             : }
     537             : 
     538             : /*-------------------------------------------------------------------------
     539             :  * ivas_ls_setup_conversion_close()
     540             :  *
     541             :  * Close the LS configuration Conversion Module
     542             :  *-------------------------------------------------------------------------*/
     543             : 
     544         870 : void ivas_ls_setup_conversion_close_fx(
     545             :     LSSETUP_CONVERSION_HANDLE *hLsSetUpConversion /* i/o: LS converter handle          */
     546             : )
     547             : {
     548             :     Word16 idx;
     549         870 :     test();
     550         870 :     IF( hLsSetUpConversion == NULL || *hLsSetUpConversion == NULL )
     551             :     {
     552         744 :         return;
     553             :     }
     554             : 
     555        2142 :     FOR( idx = 0; idx < MAX_CICP_CHANNELS; idx++ )
     556             :     {
     557        2016 :         IF( ( *hLsSetUpConversion )->dmxMtx_fx[idx] != NULL )
     558             :         {
     559         784 :             free( ( *hLsSetUpConversion )->dmxMtx_fx[idx] );
     560         784 :             ( *hLsSetUpConversion )->dmxMtx_fx[idx] = NULL;
     561             :         }
     562             : 
     563        2016 :         IF( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] != NULL )
     564             :         {
     565         727 :             free( ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] );
     566         727 :             ( *hLsSetUpConversion )->targetEnergyPrev_fx[idx] = NULL;
     567             :         }
     568             : 
     569        2016 :         IF( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] != NULL )
     570             :         {
     571         727 :             free( ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] );
     572         727 :             ( *hLsSetUpConversion )->dmxEnergyPrev_fx[idx] = NULL;
     573             :         }
     574             :     }
     575             : 
     576         126 :     free( *hLsSetUpConversion );
     577         126 :     *hLsSetUpConversion = NULL;
     578             : 
     579         126 :     return;
     580             : }
     581             : 
     582             : /*-------------------------------------------------------------------------
     583             :  * ivas_ls_setup_conversion()
     584             :  *
     585             :  * Convert (downmix or upmix) the input LS configuration
     586             :  * to output LS configuration in time domain
     587             :  *-------------------------------------------------------------------------*/
     588             : 
     589        7457 : void ivas_ls_setup_conversion_fx(
     590             :     Decoder_Struct *st_ivas,   /* i  : IVAS decoder structure           */
     591             :     const Word16 input_chans,  /* i  : number of input channels to the renderer        */
     592             :     const Word16 output_frame, /* i  : frame length                     */
     593             :     Word32 *input[],           /* i  : LS input/output synthesis signal Qx*/
     594             :     Word32 *output[]           /* i/o: LS input/output synthesis signal Qx*/
     595             : )
     596             : {
     597             :     Word16 chInIdx, chOutIdx, idx;
     598             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
     599             :     Word32 dmxCoeff, tmpVal;
     600             :     Word32 output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; // Qx
     601             : 
     602        7457 :     push_wmops( "LS_Renderer" );
     603             : 
     604        7457 :     hLsSetUpConversion = st_ivas->hLsSetUpConversion;
     605             : 
     606       69341 :     FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
     607             :     {
     608       61884 :         set32_fx( output_tmp[chOutIdx], 0, output_frame );
     609      433468 :         FOR( chInIdx = 0; chInIdx < input_chans; chInIdx++ )
     610             :         {
     611      371584 :             dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
     612      371584 :             move32();
     613             : 
     614      371584 :             IF( dmxCoeff == 0 )
     615             :             {
     616      305602 :                 CONTINUE;
     617             :             }
     618       65982 :             ELSE IF( EQ_32( dmxCoeff, ONE_IN_Q30 ) )
     619             :             {
     620    21981902 :                 FOR( idx = 0; idx < output_frame; idx++ )
     621             :                 {
     622    21953400 :                     output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], input[chInIdx][idx] );
     623    21953400 :                     move32();
     624             :                 }
     625             :             }
     626             :             ELSE
     627             :             {
     628    35864680 :                 FOR( idx = 0; idx < output_frame; idx++ )
     629             :                 {
     630    35827200 :                     tmpVal = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), input[chInIdx][idx] );
     631    35827200 :                     output_tmp[chOutIdx][idx] = L_add( output_tmp[chOutIdx][idx], tmpVal );
     632    35827200 :                     move32();
     633             :                 }
     634             :             }
     635             :         }
     636             :     }
     637             : 
     638             :     /* Copy to output buffer */
     639       69341 :     FOR( chOutIdx = 0; chOutIdx < st_ivas->hDecoderConfig->nchan_out; chOutIdx++ )
     640             :     {
     641       61884 :         Copy32( output_tmp[chOutIdx], output[chOutIdx], output_frame );
     642             :     }
     643             : 
     644        7457 :     pop_wmops();
     645             : 
     646        7457 :     return;
     647             : }
     648             : 
     649             : /*-------------------------------------------------------------------------
     650             :  * ivas_ls_setup_conversion_process_mdct()
     651             :  *
     652             :  * Equalization in MDCT Domain
     653             :  *-------------------------------------------------------------------------*/
     654             : 
     655        6504 : void ivas_ls_setup_conversion_process_mdct_fx(
     656             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure          */
     657             :     Word32 *output[]         /* i/o: output synthesis signal         */
     658             : )
     659             : {
     660             :     /* Declaration of all required variables */
     661             :     Word16 i, bandIdx, chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx, idx, j;
     662             :     Word16 inChannels, outChannels, num_CPE;
     663             :     Word16 transform_type[MAX_CICP_CHANNELS][2];
     664             :     Word16 frameSize;
     665             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     666             :     Word64 targetEnergy64[MAX_SFB + 2], dmxEnergy64[MAX_SFB + 2];
     667             :     Word16 scf1, scf2;
     668             : #else
     669             :     Word32 targetEnergy[MAX_SFB + 2], dmxEnergy[MAX_SFB + 2];
     670             :     Word16 dmxEnergy_exp[MAX_SFB + 2], dmxEnergy_exp_temp;
     671             : #endif
     672             :     Word32 dmxCoeff;
     673             :     Word32 dmxSignalReal[L_FRAME48k], dmxSignalImag[L_FRAME48k];
     674             :     Word32 eqGain;
     675             :     Word32 *sig[NB_DIV], *pTmp[NB_DIV], *x[MAX_CICP_CHANNELS][NB_DIV];
     676             :     Word32 mdst[L_FRAME48k];
     677             :     Word32 convertRes[L_FRAME48k];
     678             :     Word16 start, stop, start_tcx5, stop_tcx5;
     679             :     Word16 mct_chan_mode[MAX_CICP_CHANNELS];
     680             : 
     681             :     /* Declare all handles */
     682             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
     683             :     CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
     684             : 
     685        6504 :     push_wmops( "LS_Renderer_MDCT" );
     686             : 
     687             :     /* Assign all the declared variables */
     688        6504 :     inChannels = st_ivas->nchan_transport;
     689        6504 :     move16();
     690        6504 :     outChannels = st_ivas->hDecoderConfig->nchan_out;
     691        6504 :     move16();
     692        6504 :     num_CPE = st_ivas->nCPE;
     693        6504 :     move16();
     694             : 
     695             :     /* Assign output pointer to variable x */
     696             : 
     697             :     // Scale the array
     698        6504 :     Word16 q_output = 31;
     699        6504 :     move16();
     700       45728 :     FOR( i = 0; i < inChannels; ++i )
     701             :     {
     702       39224 :         q_output = s_min( q_output, L_norm_arr( output[i], L_FRAME48k ) );
     703             :     }
     704             : 
     705        6504 :     Word16 tmp_sub = sub( st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt], st_ivas->hLsSetUpConversion->sfbOffset[st_ivas->hLsSetUpConversion->sfbCnt - 1] );
     706        6504 :     Word16 guard_1 = shr( add( find_guarded_bits_fx( tmp_sub ), 1 ), 1 );
     707        6504 :     Word16 guard_2 = find_guarded_bits_fx( L_mult0( outChannels, inChannels ) );
     708        6504 :     q_output = sub( q_output, s_max( guard_1, guard_2 ) );
     709             :     /* Increase the guard bit by 1 to avoid overflow only if q_output is positive */
     710        6504 :     if ( q_output > 0 )
     711             :     {
     712        4727 :         q_output = sub( q_output, 1 );
     713             :     }
     714             : 
     715       45728 :     FOR( i = 0; i < inChannels; ++i )
     716             :     {
     717    37694264 :         FOR( j = 0; j < L_FRAME48k; ++j )
     718             :         {
     719    37655040 :             output[i][j] = L_shl( output[i][j], q_output );
     720             :         }
     721             :     }
     722             : 
     723       45728 :     FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
     724             :     {
     725       39224 :         x[chInIdx][0] = output[chInIdx];                  // Q(q_output)
     726       39224 :         x[chInIdx][1] = output[chInIdx] + L_FRAME48k / 2; // Q(q_output)
     727             :     }
     728             : 
     729             :     /* Assign all the declared handles*/
     730        6504 :     hLsSetUpConversion = st_ivas->hLsSetUpConversion;
     731       26116 :     FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
     732             :     {
     733       19612 :         hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
     734             :     }
     735             : 
     736             :     /* Get the core type */
     737       26116 :     FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
     738             :     {
     739       58836 :         FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
     740             :         {
     741             :             /* get the channel index */
     742       39224 :             chInIdx = add( imult1616( cpe_idx, CPE_CHANNELS ), idx );
     743       39224 :             assert( LE_16( chInIdx, inChannels ) );
     744       39224 :             transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
     745       39224 :             move16();
     746       39224 :             transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
     747       39224 :             move16();
     748       39224 :             mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
     749       39224 :             move16();
     750             :         }
     751             :     }
     752             : 
     753             :     /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
     754        6504 :     frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
     755        6504 :     move16();
     756             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     757        6504 :     set64_fx( targetEnergy64, 0, MAX_SFB + 2 );
     758        6504 :     set64_fx( dmxEnergy64, 0, MAX_SFB + 2 );
     759        6504 :     scf1 = 63;
     760        6504 :     scf2 = 63;
     761        6504 :     move16();
     762        6504 :     move16();
     763             : #else
     764             :     set32_fx( targetEnergy, 0, MAX_SFB + 2 );
     765             :     set32_fx( dmxEnergy, 0, MAX_SFB + 2 );
     766             :     set16_fx( dmxEnergy_exp, 0, MAX_SFB + 2 );
     767             :     dmxEnergy_exp_temp = 0;
     768             :     move16();
     769             : #endif
     770             : 
     771       57152 :     FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
     772             :     {
     773             :         /* Step 0: Set the buffers to zero */
     774       50648 :         set32_fx( dmxSignalReal, 0, frameSize );
     775       50648 :         set32_fx( dmxSignalImag, 0, frameSize );
     776             : 
     777      354936 :         FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
     778             :         {
     779      304288 :             dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
     780      304288 :             move32();
     781             : 
     782      304288 :             test();
     783      304288 :             IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
     784             :             {
     785             :                 /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
     786      199937 :                 IF( dmxCoeff )
     787             :                 {
     788             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     789             :                     Word64 targetEne64;
     790             :                     Word32 tmpDMXSig;
     791             : #else
     792             :                     Word32 tmpDMXSig, targetEne;
     793             : #endif
     794             :                     /* Convert the signal resolution to TCX20 */
     795             :                     /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
     796       28824 :                     pTmp[0] = x[chInIdx][0]; // Q(q_output)
     797       28824 :                     sig[0] = pTmp[0];
     798       28824 :                     pTmp[1] = x[chInIdx][1];
     799       28824 :                     sig[1] = pTmp[1]; // Q(q_output)
     800             : 
     801             :                     /* convert (sub)frames to higher frequency resolution */
     802       28824 :                     IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
     803             :                     {
     804        1521 :                         FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
     805             :                         {
     806        1014 :                             IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
     807             :                             {
     808             :                                 /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
     809         536 :                                 sig[subFrameIdx] = convertRes + L_shr( L_mult0( subFrameIdx, frameSize ), 1 );
     810         536 :                                 pTmp[subFrameIdx] = sig[subFrameIdx];
     811         536 :                                 convert_coeffs_to_higher_res_fx( x[chInIdx][subFrameIdx], x[chInIdx][subFrameIdx] + shr( frameSize, 2 ), pTmp[subFrameIdx], shr( frameSize, 2 ) );
     812             :                             }
     813             :                         }
     814             : 
     815             :                         /* convert channel with TCX10 to TCX20 resolution */
     816         507 :                         sig[0] = convertRes;
     817         507 :                         convert_coeffs_to_higher_res_fx( pTmp[0], pTmp[1], sig[0], frameSize / 2 );
     818             :                     }
     819             : 
     820             :                     /* MDST estimate */
     821       28824 :                     mdst[0] = mdst[frameSize - 1] = 0;
     822       28824 :                     move32();
     823       28824 :                     move32();
     824    27514216 :                     FOR( i = 1; i < frameSize - 1; i++ )
     825             :                     {
     826    27485392 :                         mdst[i] = L_sub( sig[0][i + 1], sig[0][i - 1] ); // Q(q_output)
     827             :                     }
     828             : 
     829     1901984 :                     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
     830             :                     {
     831     1873160 :                         start = hLsSetUpConversion->sfbOffset[bandIdx];
     832     1873160 :                         move16();
     833     1873160 :                         stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
     834     1873160 :                         move16();
     835             : 
     836             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     837     1873160 :                         targetEne64 = 0;
     838     1873160 :                         move64();
     839             : #else
     840             :                         targetEne = 0;
     841             :                         move32();
     842             : #endif
     843             : 
     844             :                         /* Loop over all the bins in the band */
     845    29416200 :                         FOR( binIdx = start; binIdx < stop; binIdx++ )
     846             :                         {
     847    27543040 :                             tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), sig[0][binIdx] );
     848    27543040 :                             dmxSignalReal[binIdx] = L_add( dmxSignalReal[binIdx], tmpDMXSig );
     849    27543040 :                             move32();
     850             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     851    27543040 :                             targetEne64 = W_mac_32_32( targetEne64, tmpDMXSig, tmpDMXSig );
     852             : #else
     853             :                             targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
     854             : #endif
     855    27543040 :                             tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), mdst[binIdx] );
     856    27543040 :                             dmxSignalImag[binIdx] = L_add( dmxSignalImag[binIdx], tmpDMXSig );
     857    27543040 :                             move32();
     858             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     859    27543040 :                             targetEne64 = W_mac_32_32( targetEne64, tmpDMXSig, tmpDMXSig );
     860             : #else
     861             :                             targetEne = L_add( targetEne, Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
     862             : #endif
     863             :                         }
     864             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     865     1873160 :                         targetEnergy64[bandIdx] = W_add( targetEnergy64[bandIdx], W_shr( targetEne64, 1 ) );
     866     1873160 :                         if ( NE_64( targetEnergy64[bandIdx], 0 ) )
     867             :                         {
     868     1863990 :                             scf1 = s_min( scf1, W_norm( targetEnergy64[bandIdx] ) );
     869             :                         }
     870             : #else
     871             :                         targetEnergy[bandIdx] = L_add( targetEnergy[bandIdx], targetEne );
     872             :                         move32();
     873             : #endif
     874             :                     } /* end of band loop */
     875             :                 }
     876             :             }
     877             :         } /* end of chInIdx loop */
     878             : 
     879     3342688 :         FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
     880             :         {
     881             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     882             :             Word32 tmpReal, tmpImag;
     883             :             Word64 DMXEne64;
     884             : #else
     885             :             Word32 tmpReal, tmpImag, DMXEne;
     886             :             Word16 DMXEne_exp;
     887             : #endif
     888     3292040 :             start = hLsSetUpConversion->sfbOffset[bandIdx];
     889     3292040 :             move16();
     890     3292040 :             stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
     891     3292040 :             move16();
     892             : 
     893             :             /* Loop over all the bins in the band */
     894             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     895     3292040 :             DMXEne64 = 0;
     896     3292040 :             move64();
     897             : #else
     898             :             DMXEne = 0;
     899             :             move32();
     900             :             DMXEne_exp = 0;
     901             :             move16();
     902             : #endif
     903             : 
     904    51888520 :             FOR( binIdx = start; binIdx < stop; binIdx++ )
     905             :             {
     906    48596480 :                 tmpReal = dmxSignalReal[binIdx];
     907    48596480 :                 move32();
     908    48596480 :                 tmpImag = dmxSignalImag[binIdx];
     909    48596480 :                 move32();
     910             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     911    48596480 :                 DMXEne64 = W_mac_32_32( DMXEne64, tmpReal, tmpReal );
     912    48596480 :                 DMXEne64 = W_mac_32_32( DMXEne64, tmpImag, tmpImag );
     913             : #else
     914             :                 DMXEne = BASOP_Util_Add_Mant32Exp( DMXEne, DMXEne_exp, L_add( Mpy_32_32( tmpReal, tmpReal ), Mpy_32_32( tmpImag, tmpImag ) ), sub( 40, shl( q_output, 1 ) ), &DMXEne_exp );
     915             : #endif
     916             :             }
     917             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     918     3292040 :             dmxEnergy64[bandIdx] = W_add( dmxEnergy64[bandIdx], W_shr( DMXEne64, 1 ) );
     919     3292040 :             if ( NE_64( dmxEnergy64[bandIdx], 0 ) )
     920             :             {
     921     3234911 :                 scf2 = s_min( scf2, W_norm( dmxEnergy64[bandIdx] ) );
     922             :             }
     923             : #else
     924             :             dmxEnergy[bandIdx] = BASOP_Util_Add_Mant32Exp( dmxEnergy[bandIdx], dmxEnergy_exp[bandIdx], DMXEne, DMXEne_exp, &dmxEnergy_exp[bandIdx] );
     925             :             move32();
     926             :             dmxEnergy_exp_temp = s_max( dmxEnergy_exp_temp, dmxEnergy_exp[bandIdx] );
     927             : #endif
     928             :         }
     929             :     } /* end of out channel loop */
     930             : #ifndef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     931             :     /* Scaling to common exponent */
     932             :     FOR( bandIdx = 0; bandIdx < MAX_SFB + 2; bandIdx++ )
     933             :     {
     934             :         dmxEnergy[bandIdx] = L_shl( dmxEnergy[bandIdx], sub( dmxEnergy_exp[bandIdx], dmxEnergy_exp_temp ) );
     935             :         move32();
     936             :     }
     937             : #endif
     938             :     /* Step 3: Peform energy smoothing */
     939        6504 :     Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
     940        6504 :     scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, te_scale );
     941             : 
     942             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     943        6504 :     Word16 dmx_scale = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
     944        6504 :     scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_scale );
     945             : 
     946        6504 :     Word16 targetEnergy_e = sub( add( sub( 40, shl( q_output, 1 ) ), 1 ), scf1 );
     947        6504 :     Word16 te_max_e = s_max( targetEnergy_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) );
     948             : 
     949        6504 :     Word16 dmxEnergy_e = sub( add( sub( 40, shl( q_output, 1 ) ), 1 ), scf2 );
     950        6504 :     Word16 dmx_max_e = s_max( dmxEnergy_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_scale ) );
     951             : #else
     952             :     Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt );
     953             :     scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[0], hLsSetUpConversion->sfbCnt, dmx_sacle );
     954             : 
     955             :     Word16 te_max_e = s_max( sub( 40, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) );
     956             :     Word16 dmx_max_e = s_max( dmxEnergy_exp_temp, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) );
     957             : #endif
     958             : 
     959      429224 :     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
     960             :     {
     961             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
     962             :         Word32 targetEnergy, dmxEnergy;
     963             : 
     964      422720 :         targetEnergy = W_extract_h( W_shl( targetEnergy64[bandIdx], scf1 ) );
     965      422720 :         targetEnergy = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy, sub( te_max_e, targetEnergy_e ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) ) ) ) );
     966      422720 :         move32();
     967      422720 :         hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy;
     968      422720 :         move32();
     969             : 
     970      422720 :         dmxEnergy = W_extract_h( W_shl( dmxEnergy64[bandIdx], scf2 ) );
     971      422720 :         dmxEnergy = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy, sub( dmx_max_e, dmxEnergy_e ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_scale ) ) ) ) );
     972      422720 :         move32();
     973      422720 :         hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy;
     974      422720 :         move32();
     975             : #else
     976             :         targetEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[bandIdx], sub( te_max_e, sub( 40, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[0], te_scale ) ) ) ) );
     977             :         move32();
     978             :         dmxEnergy[bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[bandIdx], sub( dmx_max_e, dmxEnergy_exp_temp ) ) ), Mpy_32_32( ( ONE_IN_Q31 - LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[0], dmx_sacle ) ) ) ) );
     979             :         move32();
     980             :         hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy[bandIdx]; /* te_prev_exp = 40 - 2*q_output */
     981             :         move32();
     982             :         hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy[bandIdx]; /* dmx_prev_exp = 40 - 2*q_output */
     983             :         move32();
     984             : #endif
     985             :     }
     986             : 
     987        6504 :     hLsSetUpConversion->te_prev_exp[0] = te_max_e; /* te_prev_exp = 40 - 2*q_output */
     988        6504 :     move16();
     989        6504 :     hLsSetUpConversion->dmx_prev_exp[0] = dmx_max_e; /* dmx_prev_exp = 40 - 2*q_output */
     990        6504 :     move16();
     991             : 
     992       45728 :     FOR( i = 0; i < inChannels; ++i )
     993             :     {
     994    37694264 :         FOR( j = 0; j < L_FRAME48k; ++j )
     995             :         {
     996    37655040 :             output[i][j] = L_shr( output[i][j], q_output );
     997    37655040 :             move32();
     998             :         }
     999             :     }
    1000             : 
    1001             :     /* Step 4: Perform equalization */
    1002       45728 :     FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
    1003             :     {
    1004       39224 :         test();
    1005       39224 :         IF( NE_16( chInIdx, LFE_CHANNEL ) && NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
    1006             :         {
    1007       25825 :             IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
    1008             :             {
    1009             :                 /* TCX20 */
    1010     1672376 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1011             :                 {
    1012     1647032 :                     start = hLsSetUpConversion->sfbOffset[bandIdx];
    1013     1647032 :                     move16();
    1014     1647032 :                     stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
    1015     1647032 :                     move16();
    1016             : 
    1017             :                     /* Compute Eq gains */
    1018             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
    1019     1647032 :                     ivas_lssetupconversion_computeEQFactor_fx( &hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->te_prev_exp[0],
    1020     1647032 :                                                                &hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->dmx_prev_exp[0],
    1021             :                                                                &eqGain ); // Q(eqGain) = 30
    1022             : #else
    1023             :                     ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain ); // Q(eqGain) = 30
    1024             : #endif
    1025    25872312 :                     FOR( binIdx = start; binIdx < stop; binIdx++ )
    1026             :                     {
    1027    24225280 :                         x[chInIdx][0][binIdx] = Mpy_32_32( L_shl( x[chInIdx][0][binIdx], 1 ), eqGain ); // Q - 1
    1028    24225280 :                         move32();
    1029             :                     }
    1030             :                 }
    1031             :             }
    1032             :             ELSE
    1033             :             {
    1034         481 :                 stop_tcx5 = 0;
    1035         481 :                 move16();
    1036       31714 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1037             :                 {
    1038       31233 :                     start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
    1039       31233 :                     move16();
    1040       31233 :                     stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
    1041       31233 :                     move16();
    1042             : 
    1043             :                     /* Compute Eq gains */
    1044             : #ifdef FIX_1962_FORMAT_CONV_SPECTRAL_DIFF
    1045       31233 :                     ivas_lssetupconversion_computeEQFactor_fx( &hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->te_prev_exp[0],
    1046       31233 :                                                                &hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], hLsSetUpConversion->dmx_prev_exp[0],
    1047             :                                                                &eqGain );
    1048             : #else
    1049             :                     ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain );
    1050             : #endif
    1051       93699 :                     FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
    1052             :                     {
    1053       62466 :                         IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
    1054             :                         {
    1055             :                             /* TCX10 */
    1056      242823 :                             FOR( binIdx = start; binIdx < stop; binIdx++ )
    1057             :                             {
    1058      213280 :                                 x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
    1059      213280 :                                 move32();
    1060             :                             }
    1061             :                         }
    1062             :                         ELSE
    1063             :                         {
    1064             :                             /* TCX5*/
    1065       32923 :                             start_tcx5 = stop_tcx5;
    1066       32923 :                             move16();
    1067       32923 :                             stop_tcx5 = shr( add( stop, 1 ), 1 );
    1068             : 
    1069      145803 :                             FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
    1070             :                             {
    1071      112880 :                                 x[chInIdx][subFrameIdx][binIdx] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx], 1 ), eqGain );
    1072      112880 :                                 move32();
    1073      112880 :                                 x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = Mpy_32_32( L_shl( x[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], 1 ), eqGain );
    1074      112880 :                                 move32();
    1075             :                             }
    1076             :                         }
    1077             :                     }
    1078             :                 }
    1079             :             }
    1080             :         }
    1081             :     }
    1082             : 
    1083        6504 :     pop_wmops();
    1084        6504 :     return;
    1085             : }
    1086             : 
    1087             : 
    1088             : /*-------------------------------------------------------------------------
    1089             :  * ivas_ls_setup_conversion_process_mdct_param_mc()
    1090             :  *
    1091             :  * Equalization in MDCT Domain
    1092             :  *-------------------------------------------------------------------------*/
    1093             : 
    1094          20 : void ivas_ls_setup_conversion_process_mdct_param_mc_fx(
    1095             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure          */
    1096             :     Word32 *x_fx[][NB_DIV],
    1097             :     Word16 x_e[CPE_CHANNELS][NB_DIV] /* i/o: Exponent for output synthesis signal */
    1098             : )
    1099             : {
    1100             :     Word32 targetEnergy_fx[MAX_SFB + 2], dmxEnergy_fx[MAX_SFB + 2];
    1101             :     Word32 eqGain_fx;
    1102             :     Word32 *sig_fx[MAX_CICP_CHANNELS][NB_DIV], *pTmp_fx[NB_DIV];
    1103             :     Word32 mdst_fx[MAX_CICP_CHANNELS][L_FRAME48k];
    1104             :     Word32 convertRes_fx[MAX_CICP_CHANNELS][L_FRAME48k];
    1105             :     Word32 cx_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
    1106             :     Word32 cx_imag_fx[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
    1107             :     Word32 cy_fx[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS];
    1108             :     Word32 real_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
    1109             :     Word32 imag_in_buffer_fx[PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS];
    1110             :     Word32 real_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
    1111             :     Word32 imag_buffer_fx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS];
    1112             :     Word32 Nrqq_fx[MAX_OUTPUT_CHANNELS];
    1113             :     Word32 target_ch_ener_fx[MAX_OUTPUT_CHANNELS];
    1114             :     Word16 *ild_q_fx;
    1115             : 
    1116             :     Word32 DMXEne_fx;
    1117             :     Word32 dmxCoeff_fx;
    1118             :     Word32 dmxSignalReal_fx[L_FRAME48k], dmxSignalImag_fx[L_FRAME48k];
    1119             : 
    1120             :     Word32 tmpReal_fx, tmpImag_fx;
    1121             :     Word32 tmpDMXSig_fx;
    1122             : 
    1123             :     /* Declaration of all required variables */
    1124             :     Word16 i;
    1125             :     Word16 idx;
    1126             :     Word16 nchan_transport, nchan_out, nchan_transport_format;
    1127             :     Word16 chInIdx, chOutIdx, cpe_idx, subFrameIdx, binIdx;
    1128             :     Word16 band, bandIdx, num_bands;
    1129             : 
    1130             :     Word16 num_CPE;
    1131             :     Word16 transform_type[MAX_CICP_CHANNELS][2];
    1132             :     Word16 frameSize;
    1133             : 
    1134             :     Word16 start, stop, start_tcx5, stop_tcx5;
    1135             :     Word16 mct_chan_mode[MAX_CICP_CHANNELS];
    1136             :     Word16 all_ch_ignored; // Flag for checking if all channels are ignored
    1137             : 
    1138             :     /* Declare all handles */
    1139             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
    1140             :     CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS];
    1141             :     PARAM_MC_DEC_HANDLE hParamMC;
    1142             : 
    1143             :     /* Step 0: Set the buffers to zero */
    1144          20 :     set_zero_fx( dmxSignalReal_fx, L_FRAME48k );
    1145          20 :     set_zero_fx( dmxSignalImag_fx, L_FRAME48k );
    1146             : 
    1147             :     /* Assign all the declared variables */
    1148          20 :     nchan_transport = st_ivas->nchan_transport;
    1149          20 :     nchan_out = st_ivas->hDecoderConfig->nchan_out;
    1150          20 :     num_CPE = st_ivas->nCPE;
    1151          20 :     nchan_transport_format = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe );
    1152          20 :     hLsSetUpConversion = st_ivas->hLsSetUpConversion;
    1153             :     /* Assign all the declared handles*/
    1154          60 :     FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
    1155             :     {
    1156          40 :         hCPE[cpe_idx] = st_ivas->hCPE[cpe_idx];
    1157             :     }
    1158          20 :     hParamMC = st_ivas->hParamMC;
    1159             : 
    1160             :     /* Get the core type */
    1161          60 :     FOR( cpe_idx = 0; cpe_idx < num_CPE; cpe_idx++ )
    1162             :     {
    1163         120 :         FOR( idx = 0; idx < CPE_CHANNELS; idx++ )
    1164             :         {
    1165             :             /* get the channel index */
    1166          80 :             chInIdx = add( cpe_idx * CPE_CHANNELS, idx );
    1167          80 :             assert( chInIdx <= nchan_transport );
    1168          80 :             transform_type[chInIdx][0] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[0];
    1169          80 :             move16();
    1170          80 :             transform_type[chInIdx][1] = hCPE[cpe_idx]->hCoreCoder[idx]->transform_type[1];
    1171          80 :             move16();
    1172          80 :             mct_chan_mode[chInIdx] = hCPE[cpe_idx]->hCoreCoder[idx]->mct_chan_mode;
    1173          80 :             move16();
    1174             :         }
    1175             :     }
    1176             : 
    1177             :     /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
    1178          20 :     frameSize = hLsSetUpConversion->sfbOffset[hLsSetUpConversion->sfbCnt];
    1179          20 :     move16();
    1180          20 :     set_zero_fx( targetEnergy_fx, MAX_SFB + 2 );
    1181          20 :     set_zero_fx( dmxEnergy_fx, MAX_SFB + 2 );
    1182             : 
    1183          80 :     FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
    1184             :     {
    1185          60 :         IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
    1186             :         {
    1187             :             /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
    1188          60 :             sig_fx[chInIdx][0] = pTmp_fx[0] = x_fx[chInIdx][0]; /*Q=31-x_e[chInIdx][0]*/
    1189          60 :             sig_fx[chInIdx][1] = pTmp_fx[1] = x_fx[chInIdx][1]; /*Q=31-x_e[chInIdx][1]*/
    1190             :             /* convert (sub)frames to higher frequency resolution */
    1191          60 :             IF( NE_16( transform_type[chInIdx][0], TCX_20 ) )
    1192             :             {
    1193          21 :                 FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
    1194             :                 {
    1195          14 :                     IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_5 ) )
    1196             :                     {
    1197             :                         /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
    1198           7 :                         pTmp_fx[subFrameIdx] = sig_fx[chInIdx][subFrameIdx] = convertRes_fx[chInIdx] + L_mult0( subFrameIdx, frameSize ) / 2;
    1199           7 :                         convert_coeffs_to_higher_res_fx( x_fx[chInIdx][subFrameIdx], x_fx[chInIdx][subFrameIdx] + frameSize / 4, pTmp_fx[subFrameIdx], frameSize / 4 ); /*Q=31-x_e[chInIdx][subFrameIdx]*/
    1200             :                     }
    1201             :                 }
    1202             : 
    1203             :                 /* convert channel with TCX10 to TCX20 resolution */
    1204           7 :                 sig_fx[chInIdx][0] = convertRes_fx[chInIdx];
    1205             : 
    1206             :                 // Scale_sig32(pTmp_fx_1_0, frameSize / 2, x_e[chInIdx][1] - x_e[chInIdx][0] );                  /*Scaling down the Q from 31-x_e[chInIdx][1] to 31-x_e[chInIdx][0]*/
    1207           7 :                 convert_coeffs_to_higher_res_fx( pTmp_fx[0], pTmp_fx[1], sig_fx[chInIdx][0], frameSize / 2 ); /*Q=31-x_e[chInIdx][0]*/
    1208             :             }
    1209             :         }
    1210             :     }
    1211          20 :     Word16 input_exp, output_exp = 0;
    1212          20 :     move16();
    1213             : 
    1214             :     /* precalculate MDST estimate */
    1215          80 :     FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
    1216             :     {
    1217          60 :         IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
    1218             :         {
    1219          60 :             mdst_fx[chInIdx][0] = mdst_fx[chInIdx][frameSize - 1] = 0;
    1220          60 :             move32();
    1221       38340 :             FOR( i = 1; i < frameSize - 1; i++ )
    1222             :             {
    1223       38280 :                 mdst_fx[chInIdx][i] = L_sub( sig_fx[chInIdx][0][i + 1], sig_fx[chInIdx][0][i - 1] ); /*Q=31-x_e[chInIdx][0]*/
    1224       38280 :                 move32();
    1225             :             }
    1226             :         }
    1227             :     }
    1228             : 
    1229             :     /* Step 1.1, calculate Cx from MDST estimate */
    1230         420 :     FOR( bandIdx = 0; bandIdx < PARAM_MC_MAX_PARAMETER_BANDS; bandIdx++ )
    1231             :     {
    1232         400 :         set_zero_fx( cx_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
    1233         400 :         set_zero_fx( cx_imag_fx[bandIdx], PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
    1234             :     }
    1235          20 :     set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
    1236          20 :     set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
    1237          20 :     Word16 max_e = 0;
    1238          20 :     move16();
    1239          20 :     all_ch_ignored = 1;
    1240          20 :     move16();
    1241          80 :     FOR( idx = 0; idx < nchan_transport; idx++ )
    1242             :     {
    1243          60 :         IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
    1244             :         {
    1245          60 :             max_e = s_max( max_e, x_e[idx][0] );
    1246          60 :             all_ch_ignored = 0;
    1247          60 :             move16();
    1248             :         }
    1249             :     }
    1250          20 :     if ( all_ch_ignored )
    1251             :     {
    1252           0 :         max_e = 31;
    1253           0 :         move16();
    1254             :     }
    1255         280 :     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1256             :     {
    1257         260 :         set_zero_fx( real_in_buffer_fx, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
    1258         260 :         set_zero_fx( imag_in_buffer_fx, PARAM_MC_MAX_BANDS_IN_PARAMETER_BAND * PARAM_MC_BAND_TO_MDCT_BAND_RATIO * MAX_TRANSPORT_CHANNELS );
    1259         260 :         set_zero_fx( real_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
    1260         260 :         set_zero_fx( imag_buffer_fx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS );
    1261             : 
    1262         260 :         start = hLsSetUpConversion->sfbOffset[bandIdx];
    1263         260 :         move16();
    1264         260 :         stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
    1265         260 :         move16();
    1266         260 :         num_bands = sub( stop, start );
    1267             : 
    1268       13060 :         FOR( i = 0; i < num_bands; i++ )
    1269             :         {
    1270       12800 :             band = add( start, i );
    1271       51200 :             FOR( idx = 0; idx < nchan_transport; idx++ )
    1272             :             {
    1273       38400 :                 IF( NE_16( mct_chan_mode[idx], MCT_CHAN_MODE_IGNORE ) )
    1274             :                 {
    1275       38400 :                     real_in_buffer_fx[i + ( num_bands * idx )] = L_shr( sig_fx[idx][0][band], sub( max_e, x_e[idx][0] ) ); /*Setting the exponent to max_e*/
    1276       38400 :                     imag_in_buffer_fx[i + ( num_bands * idx )] = L_shr( mdst_fx[idx][band], sub( max_e, x_e[idx][0] ) );   /*Setting the exponent to max_e*/
    1277       38400 :                     move32();
    1278       38400 :                     move32();
    1279             :                 }
    1280             :             }
    1281             :         }
    1282         260 :         input_exp = max_e;
    1283         260 :         move16();
    1284         260 :         IF( all_ch_ignored == 0 )
    1285             :         {
    1286         260 :             Word16 shift = 1;
    1287         260 :             move16();
    1288       38660 :             FOR( i = 0; i < num_bands * nchan_transport; ++i )
    1289             :             {
    1290       38400 :                 real_in_buffer_fx[i] = L_shr( real_in_buffer_fx[i], shift );
    1291       38400 :                 move32();
    1292       38400 :                 imag_in_buffer_fx[i] = L_shr( imag_in_buffer_fx[i], shift );
    1293       38400 :                 move32();
    1294             :             }
    1295         260 :             input_exp = add( input_exp, shift );
    1296             :         }
    1297             : 
    1298         260 :         cmplx_matrix_square_fx( real_in_buffer_fx, imag_in_buffer_fx, num_bands, nchan_transport, real_buffer_fx, imag_buffer_fx, input_exp, &output_exp );
    1299         260 :         v_add_32( cx_fx[bandIdx], real_buffer_fx, cx_fx[bandIdx], i_mult( nchan_transport, nchan_transport ) );           /*Q=Q_real_buffer=Q_imag_buffer=output_exp*/
    1300         260 :         v_add_32( cx_imag_fx[bandIdx], imag_buffer_fx, cx_imag_fx[bandIdx], i_mult( nchan_transport, nchan_transport ) ); /*Q=Q_real_buffer=Q_imag_buffer=output_exp*/
    1301             :     }
    1302          20 :     if ( all_ch_ignored )
    1303             :     {
    1304           0 :         output_exp = 29;
    1305           0 :         move16();
    1306             :     }
    1307             : 
    1308          20 :     Word16 exp_in = 10, exp_out = 0;
    1309          20 :     move16();
    1310          20 :     move16();
    1311         280 :     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1312             :     {
    1313         260 :         DMXEne_fx = 0;
    1314         260 :         move16();
    1315         260 :         set_zero_fx( cy_fx, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS );
    1316         260 :         set_zero_fx( Nrqq_fx, MAX_OUTPUT_CHANNELS );
    1317         260 :         set_zero_fx( target_ch_ener_fx, MAX_OUTPUT_CHANNELS );
    1318             :         /* Step 1.2, get target channel energies for the transported format, Nrqq calculation */
    1319         260 :         ild_q_fx = hParamMC->icld_q_fx + imult1616( bandIdx, hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe );
    1320         260 :         move16();
    1321        3380 :         FOR( chInIdx = 0; chInIdx < nchan_transport_format; chInIdx++ )
    1322             :         {
    1323        3120 :             Word32 ref_ener_fx = 0;
    1324        3120 :             move32();
    1325             :             Word16 ref_channel_cnt;
    1326             :             Word16 ref_channel_idx;
    1327             : 
    1328        6240 :             FOR( ref_channel_cnt = 0; ref_channel_cnt < hParamMC->hMetadataPMC->ild_mapping_conf->num_ref_channels[chInIdx]; ref_channel_cnt++ )
    1329             :             {
    1330        3120 :                 ref_channel_idx = hParamMC->hMetadataPMC->ild_mapping_conf->ref_channel_idx[chInIdx][ref_channel_cnt];
    1331        3120 :                 move16();
    1332        3120 :                 ref_ener_fx = L_add( ref_ener_fx, cx_fx[bandIdx][ref_channel_idx + ( ref_channel_idx * nchan_transport )] ); /*Exponent=output_exp*/
    1333             :             }
    1334             :             Word32 temp;
    1335        3120 :             temp = BASOP_util_Pow2( L_mult0( ild_q_fx[chInIdx], 2721 /*log2(10)*(2^13)/10*/ ), exp_in, &exp_out );
    1336        3120 :             Nrqq_fx[hParamMC->hMetadataPMC->ild_mapping_conf->ild_index[chInIdx]] = L_shr( Mpy_32_16_1( ref_ener_fx, extract_l( Mpy_32_32( temp, hParamMC->hMetadataPMC->ild_factors_fx[chInIdx] ) ) ), sub( 2, exp_out ) ); /*exp=output_exp*/
    1337        3120 :             move32();
    1338             :         }
    1339             : 
    1340             :         /* Step 1.3 get target Cy () (with dmx matrix from CICPX to MONO/STEREO saved in hParamMC) */
    1341         780 :         FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
    1342             :         {
    1343        6760 :             FOR( i = 0; i < nchan_transport_format; i++ )
    1344             :             {
    1345        6240 :                 target_ch_ener_fx[chOutIdx] = L_add( target_ch_ener_fx[chOutIdx], L_shl( Mpy_32_32( Nrqq_fx[i], hParamMC->ls_conv_dmx_matrix_fx[chOutIdx + ( i * nchan_out )] ), 1 ) ); /*output_exp + 2*/
    1346        6240 :                 move32();
    1347             :             }
    1348         520 :             cy_fx[chOutIdx + ( nchan_out * chOutIdx )] = target_ch_ener_fx[chOutIdx];
    1349         520 :             move32();
    1350             :         }
    1351             : 
    1352             :         /* Step 1.4 final target energy for the band would then be the sum over the diagonal of Cy*/
    1353         780 :         FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
    1354             :         {
    1355         520 :             targetEnergy_fx[bandIdx] = L_add( targetEnergy_fx[bandIdx], cy_fx[chOutIdx + ( nchan_out * chOutIdx )] ); /*exp=output_exp+2*/
    1356         520 :             move32();
    1357             :         }
    1358             : 
    1359             :         /* Step 2: Calculate DMX ener */
    1360         260 :         start = hLsSetUpConversion->sfbOffset[bandIdx];
    1361         260 :         move16();
    1362         260 :         stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
    1363         260 :         move16();
    1364             : 
    1365         780 :         FOR( chOutIdx = 0; chOutIdx < nchan_out; chOutIdx++ )
    1366             :         {
    1367        2080 :             FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
    1368             :             {
    1369        1560 :                 IF( mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE )
    1370             :                 {
    1371        1560 :                     dmxCoeff_fx = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx];
    1372             : 
    1373             :                     /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */
    1374        1560 :                     IF( dmxCoeff_fx )
    1375             :                     {
    1376             :                         /* Loop over all the bins in the band */
    1377       52240 :                         FOR( binIdx = start; binIdx < stop; binIdx++ )
    1378             :                         {
    1379       51200 :                             tmpDMXSig_fx = Mult_32_32( dmxCoeff_fx, L_shr( sig_fx[chInIdx][0][binIdx], sub( max_e, x_e[chInIdx][0] ) ) ); /*max_e+1*/
    1380       51200 :                             dmxSignalReal_fx[binIdx] = L_add( dmxSignalReal_fx[binIdx], tmpDMXSig_fx );
    1381       51200 :                             move32();
    1382             : 
    1383       51200 :                             tmpDMXSig_fx = Mult_32_32( dmxCoeff_fx, L_shr( mdst_fx[chInIdx][binIdx], sub( max_e, x_e[chInIdx][0] ) ) ); /*max_e+1*/
    1384       51200 :                             dmxSignalImag_fx[binIdx] = L_add( dmxSignalImag_fx[binIdx], tmpDMXSig_fx );
    1385       51200 :                             move32();
    1386             :                         }
    1387             :                     }
    1388             :                 }
    1389             :             }
    1390             :             /* Loop over all the bins in the band */
    1391         520 :             DMXEne_fx = 0;
    1392         520 :             move32();
    1393       26120 :             FOR( binIdx = start; binIdx < stop; binIdx++ )
    1394             :             {
    1395       25600 :                 tmpReal_fx = L_shr( dmxSignalReal_fx[binIdx], 1 );
    1396       25600 :                 tmpImag_fx = L_shr( dmxSignalImag_fx[binIdx], 1 );
    1397             : 
    1398       25600 :                 DMXEne_fx = L_add( DMXEne_fx, Mult_32_32( tmpReal_fx, tmpReal_fx ) + Mult_32_32( tmpImag_fx, tmpImag_fx ) ); /*2*(max_e + 2)*/
    1399             :             }
    1400             :         }
    1401             : 
    1402         260 :         dmxEnergy_fx[bandIdx] = DMXEne_fx; /*2*(max_e+2)*/
    1403         260 :         move32();
    1404             :     }
    1405             : 
    1406             :     /* Step 3: Peform energy smoothing */
    1407         280 :     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1408             :     {
    1409         260 :         targetEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, targetEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx], add( output_exp, sub( 2, hLsSetUpConversion->te_prev_exp[0] ) ) ) ) ); /*output_exp + 2*/
    1410         260 :         move32();
    1411         260 :         dmxEnergy_fx[bandIdx] = L_add( Mult_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, dmxEnergy_fx[bandIdx] ), Mult_32_32( L_sub( MAX_32, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx], sub( shl( add( max_e, 2 ), 1 ), hLsSetUpConversion->dmx_prev_exp[0] ) ) ) ); /*2 * (max_e + 2)*/
    1412         260 :         move32();
    1413         260 :         hLsSetUpConversion->targetEnergyPrev_fx[0][bandIdx] = targetEnergy_fx[bandIdx];
    1414         260 :         move32();
    1415         260 :         hLsSetUpConversion->dmxEnergyPrev_fx[0][bandIdx] = dmxEnergy_fx[bandIdx];
    1416         260 :         move32();
    1417             :     }
    1418          20 :     hLsSetUpConversion->te_prev_exp[0] = add( output_exp, 2 );
    1419          20 :     move16();
    1420          20 :     hLsSetUpConversion->dmx_prev_exp[0] = shl( add( max_e, 2 ), 1 );
    1421          20 :     move16();
    1422             :     /* Step 4: Perform equalization */
    1423          80 :     FOR( chInIdx = 0; chInIdx < nchan_transport; chInIdx++ )
    1424             :     {
    1425          60 :         IF( NE_16( mct_chan_mode[chInIdx], MCT_CHAN_MODE_IGNORE ) )
    1426             :         {
    1427          60 :             IF( EQ_16( transform_type[chInIdx][0], TCX_20 ) )
    1428             :             {
    1429             :                 /*TCX20*/
    1430         742 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1431             :                 {
    1432         689 :                     start = hLsSetUpConversion->sfbOffset[bandIdx];
    1433         689 :                     move16();
    1434         689 :                     stop = hLsSetUpConversion->sfbOffset[bandIdx + 1];
    1435         689 :                     move16();
    1436             : 
    1437             :                     /*Compute Eq gains */
    1438         689 :                     ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
    1439             : 
    1440       34609 :                     FOR( binIdx = start; binIdx < stop; binIdx++ )
    1441             :                     {
    1442       33920 :                         x_fx[chInIdx][0][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][0][binIdx], eqGain_fx ), 1 );
    1443             :                     }
    1444             :                 }
    1445             :             }
    1446             :             ELSE
    1447             :             {
    1448           7 :                 stop_tcx5 = 0;
    1449           7 :                 move16();
    1450          98 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1451             :                 {
    1452          91 :                     start = shr( hLsSetUpConversion->sfbOffset[bandIdx], 1 );
    1453          91 :                     stop = shr( hLsSetUpConversion->sfbOffset[bandIdx + 1], 1 );
    1454             : 
    1455             :                     /*Compute Eq gains */
    1456          91 :                     ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy_fx[bandIdx], hLsSetUpConversion->te_prev_exp[0], &dmxEnergy_fx[bandIdx], hLsSetUpConversion->dmx_prev_exp[0], &eqGain_fx );
    1457             : 
    1458             : 
    1459         273 :                     FOR( subFrameIdx = 0; subFrameIdx < NB_DIV; subFrameIdx++ )
    1460             :                     {
    1461         182 :                         IF( EQ_16( transform_type[chInIdx][subFrameIdx], TCX_10 ) )
    1462             :                         {
    1463             :                             /*TCX10*/
    1464        2331 :                             FOR( binIdx = start; binIdx < stop; binIdx++ )
    1465             :                             {
    1466        2240 :                                 x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
    1467        2240 :                                 move32();
    1468             :                             }
    1469             :                         }
    1470             :                         ELSE
    1471             :                         {
    1472             :                             /* TCX5*/
    1473          91 :                             start_tcx5 = stop_tcx5;
    1474          91 :                             move16();
    1475          91 :                             stop_tcx5 = shr( add( stop, 1 ), 1 );
    1476        1211 :                             FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
    1477             :                             {
    1478        1120 :                                 x_fx[chInIdx][subFrameIdx][binIdx] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx], eqGain_fx ), 1 );
    1479        1120 :                                 move32();
    1480             :                             }
    1481             : 
    1482        1211 :                             FOR( binIdx = start_tcx5; binIdx < stop_tcx5; binIdx++ )
    1483             :                             {
    1484        1120 :                                 x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )] = L_shl( Mult_32_32( x_fx[chInIdx][subFrameIdx][binIdx + ( frameSize >> 2 )], eqGain_fx ), 1 );
    1485        1120 :                                 move32();
    1486             :                             }
    1487             :                         }
    1488             :                     }
    1489             :                 }
    1490             :             }
    1491             :         }
    1492             :     }
    1493          20 :     return;
    1494             : }
    1495             : 
    1496             : 
    1497             : /*-------------------------------------------------------------------------
    1498             :  * ivas_ls_setup_conversion_process_param_mc()
    1499             :  *
    1500             :  * LS setup conversion in the CLDFB domain for Parametric MC
    1501             :  *-------------------------------------------------------------------------*/
    1502             : 
    1503        1360 : void ivas_lssetupconversion_process_param_mc_fx(
    1504             :     Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle                */
    1505             :     const Word16 num_timeslots,
    1506             :     Word32 Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals                                         Q6*/
    1507             :     Word32 Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals                                         Q6*/
    1508             :     Word16 channel_active[MAX_CICP_CHANNELS]                                                                  /* i  : bitmap indicating which output channels are active */
    1509             : )
    1510             : {
    1511             :     Word16 slotIdx, chOutIdx, chInIdx, bandIdx;
    1512             :     Word16 inChannels, outChannels;
    1513             :     Word32 targetEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    1514             :     Word32 dmxEnergy[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    1515             :     Word32 tmpDMXSig, dmxCoeff, tmpReal, tmpImag;
    1516             :     Word32 EQ;
    1517             :     Word32 Cldfb_RealBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    1518             :     Word32 Cldfb_ImagBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    1519             :     LSSETUP_CONVERSION_HANDLE hLsSetUpConversion;
    1520             :     Word16 i, k;
    1521             : 
    1522        1360 :     push_wmops( "LS_Renderer_Process_Param_MC" );
    1523             :     /* inits */
    1524        1360 :     inChannels = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe );
    1525        1360 :     move16();
    1526        1360 :     outChannels = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe );
    1527        1360 :     move16();
    1528             : 
    1529        1360 :     hLsSetUpConversion = st_ivas->hLsSetUpConversion;
    1530        1360 :     EQ = 0;
    1531        1360 :     move32();
    1532             : 
    1533        1360 :     set16_fx( channel_active, 0, outChannels );
    1534             : 
    1535             :     /* Loop over each time slots and compute dmx for each time slot */
    1536        6800 :     FOR( slotIdx = 0; slotIdx < num_timeslots; slotIdx++ )
    1537             :     {
    1538             :         // Scale the array
    1539        5440 :         Word16 q_output = 31;
    1540       38080 :         FOR( i = 0; i < inChannels; ++i )
    1541             :         {
    1542       32640 :             q_output = s_min( q_output, L_norm_arr( Cldfb_RealBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
    1543       32640 :             q_output = s_min( q_output, L_norm_arr( Cldfb_ImagBuffer_InOut[i][slotIdx], hLsSetUpConversion->sfbCnt ) );
    1544             :         }
    1545             : 
    1546        5440 :         Word16 guard_1 = find_guarded_bits_fx( inChannels );
    1547        5440 :         q_output = sub( q_output, guard_1 );
    1548             : 
    1549       38080 :         FOR( i = 0; i < inChannels; ++i )
    1550             :         {
    1551     1991040 :             FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
    1552             :             {
    1553     1958400 :                 Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
    1554     1958400 :                 Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shl( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q(6 + q_output)
    1555             :             }
    1556             :         }
    1557             :         /* copy buffers */
    1558       38080 :         FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
    1559             :         {
    1560       32640 :             Copy32( Cldfb_RealBuffer_InOut[chInIdx][slotIdx], Cldfb_RealBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
    1561       32640 :             Copy32( Cldfb_ImagBuffer_InOut[chInIdx][slotIdx], Cldfb_ImagBuffer_tmp[chInIdx], CLDFB_NO_CHANNELS_MAX ); // Q(6 + q_output)
    1562             :         }
    1563             :         /* set the buffers to zero */
    1564       70720 :         FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
    1565             :         {
    1566       65280 :             set32_fx( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
    1567       65280 :             set32_fx( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx], 0, CLDFB_NO_CHANNELS_MAX );
    1568             : 
    1569       65280 :             set32_fx( dmxEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
    1570       65280 :             set32_fx( targetEnergy[chOutIdx], 0, CLDFB_NO_CHANNELS_MAX );
    1571             :         }
    1572             : 
    1573             :         /* Compute the target energy and DMX signal */
    1574       70720 :         FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
    1575             :         {
    1576      456960 :             FOR( chInIdx = 0; chInIdx < inChannels; chInIdx++ )
    1577             :             {
    1578      391680 :                 dmxCoeff = hLsSetUpConversion->dmxMtx_fx[chInIdx][chOutIdx]; // Q30
    1579      391680 :                 move32();
    1580      391680 :                 IF( dmxCoeff == 0 )
    1581             :                 {
    1582      359040 :                     CONTINUE;
    1583             :                 }
    1584             :                 ELSE
    1585             :                 {
    1586       32640 :                     channel_active[chOutIdx] = s_or( 1, channel_active[chOutIdx] );
    1587       32640 :                     move16();
    1588     1991040 :                     FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1589             :                     {
    1590     1958400 :                         tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_RealBuffer_tmp[chInIdx][bandIdx] ); // Q(6 + q_output)
    1591     1958400 :                         Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
    1592     1958400 :                         move32();
    1593     1958400 :                         targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) ); // Q((6 + q_output)*2 - 31)
    1594     1958400 :                         move32();
    1595             : 
    1596     1958400 :                         tmpDMXSig = Mpy_32_32( L_shl_sat( dmxCoeff, 1 ), Cldfb_ImagBuffer_tmp[chInIdx][bandIdx] );
    1597     1958400 :                         Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = L_add( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], tmpDMXSig );
    1598     1958400 :                         move32();
    1599     1958400 :                         targetEnergy[chOutIdx][bandIdx] = L_add( targetEnergy[chOutIdx][bandIdx], Mpy_32_32( tmpDMXSig, tmpDMXSig ) );
    1600     1958400 :                         move32();
    1601             :                     }
    1602             :                 }
    1603             :             }
    1604             :         }
    1605             : 
    1606             :         /* Compute the DMX energy */
    1607       70720 :         FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
    1608             :         {
    1609       65280 :             IF( channel_active[chOutIdx] )
    1610             :             {
    1611     1991040 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1612             :                 {
    1613     1958400 :                     tmpReal = Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
    1614     1958400 :                     move32();
    1615     1958400 :                     tmpImag = Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx]; // Q(6 + q_output)
    1616     1958400 :                     move32();
    1617             : 
    1618     1958400 :                     dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( tmpReal, tmpReal ), Mpy_32_32( tmpImag, tmpImag ) ); // Q((6 + q_output)*2 - 31)
    1619     1958400 :                     move32();
    1620             :                 }
    1621             :             }
    1622             :         }
    1623             : 
    1624             :         /* Peform energy smoothing */
    1625       70720 :         FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
    1626             :         {
    1627       65280 :             IF( channel_active[chOutIdx] )
    1628             :             {
    1629       32640 :                 Word16 te_scale = getScaleFactor32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
    1630       32640 :                 scale_sig32( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, te_scale );
    1631       32640 :                 Word16 dmx_sacle = getScaleFactor32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt );
    1632       32640 :                 scale_sig32( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx], hLsSetUpConversion->sfbCnt, dmx_sacle );
    1633             : 
    1634       32640 :                 Word16 te_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) );
    1635       32640 :                 Word16 dmx_max_e = s_max( sub( 50, shl( q_output, 1 ) ), sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) );
    1636             : 
    1637     1991040 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1638             :                 {
    1639     1958400 :                     targetEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( targetEnergy[chOutIdx][bandIdx], sub( te_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx], sub( te_max_e, sub( hLsSetUpConversion->te_prev_exp[chOutIdx], te_scale ) ) ) ) );
    1640     1958400 :                     move32();
    1641     1958400 :                     dmxEnergy[chOutIdx][bandIdx] = L_add( Mpy_32_32( LS_OUT_CONV_SMOOTHING_FACTOR_Q31, L_shr( dmxEnergy[chOutIdx][bandIdx], sub( dmx_max_e, sub( 50, shl( q_output, 1 ) ) ) ) ), Mpy_32_32( L_sub( ONE_IN_Q31, LS_OUT_CONV_SMOOTHING_FACTOR_Q31 ), L_shr( hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx], sub( dmx_max_e, sub( hLsSetUpConversion->dmx_prev_exp[chOutIdx], dmx_sacle ) ) ) ) );
    1642     1958400 :                     move32();
    1643     1958400 :                     hLsSetUpConversion->targetEnergyPrev_fx[chOutIdx][bandIdx] = targetEnergy[chOutIdx][bandIdx]; // Q0
    1644     1958400 :                     move32();
    1645     1958400 :                     hLsSetUpConversion->dmxEnergyPrev_fx[chOutIdx][bandIdx] = dmxEnergy[chOutIdx][bandIdx]; // Q0
    1646     1958400 :                     move32();
    1647             :                 }
    1648             : 
    1649       32640 :                 hLsSetUpConversion->te_prev_exp[chOutIdx] = te_max_e; /* te_prev_exp = 50 - 2*q_output */
    1650       32640 :                 move16();
    1651       32640 :                 hLsSetUpConversion->dmx_prev_exp[chOutIdx] = dmx_max_e; /* dmx_prev_exp = 50 - 2*q_output */
    1652       32640 :                 move16();
    1653             :             }
    1654             :         }
    1655             : 
    1656       70720 :         FOR( i = 0; i < outChannels; ++i )
    1657             :         {
    1658     3982080 :             FOR( k = 0; k < hLsSetUpConversion->sfbCnt; ++k )
    1659             :             {
    1660     3916800 :                 Cldfb_RealBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_RealBuffer_InOut[i][slotIdx][k], q_output ); // Q6
    1661     3916800 :                 move32();
    1662     3916800 :                 Cldfb_ImagBuffer_InOut[i][slotIdx][k] = L_shr( Cldfb_ImagBuffer_InOut[i][slotIdx][k], q_output ); // Q6
    1663     3916800 :                 move32();
    1664             :             }
    1665             :         }
    1666             : 
    1667             :         /* Compute and perform equalization */
    1668       70720 :         FOR( chOutIdx = 0; chOutIdx < outChannels; chOutIdx++ )
    1669             :         {
    1670       65280 :             IF( channel_active[chOutIdx] )
    1671             :             {
    1672     1991040 :                 FOR( bandIdx = 0; bandIdx < hLsSetUpConversion->sfbCnt; bandIdx++ )
    1673             :                 {
    1674     1958400 :                     ivas_lssetupconversion_computeEQFactor_fx( &targetEnergy[chOutIdx][bandIdx], hLsSetUpConversion->te_prev_exp[chOutIdx], &dmxEnergy[chOutIdx][bandIdx], hLsSetUpConversion->dmx_prev_exp[chOutIdx], &EQ ); // Q(EQ) = Q30
    1675     1958400 :                     Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_RealBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
    1676     1958400 :                     move32();
    1677     1958400 :                     Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx] = Mpy_32_32( L_shl( Cldfb_ImagBuffer_InOut[chOutIdx][slotIdx][bandIdx], 1 ), EQ );
    1678     1958400 :                     move32();
    1679             :                 }
    1680             :             }
    1681             :         }
    1682             :     }
    1683             : 
    1684        1360 :     pop_wmops();
    1685        1360 :     return;
    1686             : }

Generated by: LCOV version 1.14