LCOV - code coverage report
Current view: top level - lib_enc - ivas_mct_enc_mct_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 479 484 99.0 %
Date: 2025-05-03 01:55:50 Functions: 11 11 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 "ivas_cnst.h"
      37             : #include "ivas_prot_fx.h"
      38             : #include "prot_fx.h"
      39             : #include "prot_fx_enc.h"
      40             : #include "wmc_auto.h"
      41             : #include <assert.h>
      42             : 
      43             : 
      44             : /*--------------------------------------------------------------*
      45             :  * Local constants
      46             :  *---------------------------------------------------------------*/
      47             : 
      48             : #define SPAR_CORR_THRES        0.9f
      49             : #define DEFAULT_CORR_THRES     0.3f
      50             : #define SPAR_CORR_THRES_Q31    1932735283
      51             : #define DEFAULT_CORR_THRES_Q31 644245094
      52             : 
      53             : /*-------------------------------------------------------------------------
      54             :  * getChannelEnergies()
      55             :  *
      56             :  * Calculate energy for each cahnnel
      57             :  *-------------------------------------------------------------------------*/
      58      199482 : void getChannelEnergies_fx(
      59             :     Encoder_State **sts,            /* i/o: Encoder state structure                */
      60             :     Word32 nrg[MCT_MAX_CHANNELS],   /* o  : buffer with energies for each channel  */
      61             :     Word16 nrg_e[MCT_MAX_CHANNELS], /* o  : exponents of energies for each channel */
      62             :     const Word16 nchan              /* i  : number of channels                     */
      63             : )
      64             : {
      65             :     Word16 ch, n, gb, sum2_e;
      66             :     Word32 sum2;
      67             :     Word16 nSubframes, L_subframe;
      68             :     Encoder_State *st;
      69             : 
      70             :     /* Calculate energies per channel */
      71     1116856 :     FOR( ch = 0; ch < nchan; ch++ )
      72             :     {
      73      917374 :         st = sts[ch];
      74      917374 :         IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
      75             :         {
      76      891599 :             IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
      77             :             {
      78      872313 :                 nSubframes = 1;
      79      872313 :                 move16();
      80      872313 :                 L_subframe = st->hTcxEnc->L_frameTCX;
      81      872313 :                 move16();
      82             :             }
      83             :             ELSE
      84             :             {
      85       19286 :                 nSubframes = NB_DIV;
      86       19286 :                 move16();
      87       19286 :                 L_subframe = shr( st->hTcxEnc->L_frameTCX, 1 );
      88             :             }
      89             : 
      90      891599 :             gb = find_guarded_bits_fx( (Word32) L_subframe );
      91             : 
      92      891599 :             sum2_e = st->hTcxEnc->spectrum_e[0];
      93      891599 :             move16();
      94      891599 :             nrg[ch] = 0;
      95      891599 :             move32();
      96     1802484 :             FOR( n = 0; n < nSubframes; n++ )
      97             :             {
      98      910885 :                 sum2 = sum2_32_exp_fx( st->hTcxEnc->spectrum_fx[n], L_subframe, &sum2_e, gb ); // 31 - sum2_e
      99             : 
     100      910885 :                 nrg[ch] = BASOP_Util_Add_Mant32Exp( nrg[ch], nrg_e[ch], sum2, sum2_e, &nrg_e[ch] );
     101      910885 :                 move32();
     102             : 
     103      910885 :                 sum2_e = st->hTcxEnc->spectrum_e[0];
     104      910885 :                 move16();
     105             :             }
     106             : 
     107      891599 :             nrg[ch] = Sqrt32( nrg[ch], &nrg_e[ch] ); // nrg_e
     108      891599 :             move32();
     109             :         }
     110             :     }
     111             : 
     112      199482 :     return;
     113             : }
     114             : 
     115             : 
     116             : /*-------------------------------------------------------------------------
     117             :  * getNextBestCorrelation()
     118             :  *
     119             :  * find channel pair with highest cross-correlation
     120             :  *-------------------------------------------------------------------------*/
     121       99511 : static void getNextBestCorrelation_fx(
     122             :     Word32 xCorrMatrix[][MCT_MAX_CHANNELS], /* i  : cross-correlation matrix, Qx                                */
     123             :     Word16 *_ch1,                           /* o  : first channel of selected channel-pair                      */
     124             :     Word16 *_ch2,                           /* o  : second channel of selected channel-pair, Qx                 */
     125             :     Word32 *max_corr,                       /* o  : normalized cross correlation value of selected channel pair */
     126             :     const Word16 sortInd,
     127             :     const Word16 nChannels )
     128             : {
     129             :     Word32 tmp_corrVals[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2];
     130             :     Word16 tmp_org[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2];
     131             :     Word16 i, tmp_idx;
     132             :     Word16 ch1, ch2;
     133             : 
     134       99511 :     set32_fx( tmp_corrVals, 0, ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
     135             : 
     136             :     /* first sort correlation matrix */
     137       99511 :     i = 0;
     138       99511 :     move16();
     139      565155 :     FOR( ch1 = 0; ch1 < nChannels; ch1++ )
     140             :     {
     141     1532013 :         FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
     142             :         {
     143     1066369 :             IF( L_abs( xCorrMatrix[ch1][ch2] ) > 0 )
     144             :             {
     145      645086 :                 assert( i < ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 );
     146      645086 :                 tmp_corrVals[i] = L_abs( xCorrMatrix[ch1][ch2] ); // Qx
     147      645086 :                 move32();
     148      645086 :                 i = add( i, 1 );
     149             :             }
     150             :         }
     151             :     }
     152             : 
     153       99511 :     tmp_idx = sub( shr( imult1616( nChannels, sub( nChannels, 1 ) ), 1 ), 1 );
     154             : 
     155             :     /* sort values */
     156       99511 :     v_sort_ind_fixed( tmp_corrVals, tmp_org, add( tmp_idx, 1 ) );
     157             : 
     158             :     /* get max, or 2nd max and so on depending on sortInd value */
     159       99511 :     *max_corr = tmp_corrVals[( tmp_idx - sortInd )]; // Qx
     160       99511 :     move32();
     161             : 
     162             :     /*find channel pair for this max_corr*/
     163      565155 :     FOR( ch1 = 0; ch1 < nChannels; ch1++ )
     164             :     {
     165     1257400 :         FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ )
     166             :         {
     167      920198 :             IF( EQ_32( L_abs( xCorrMatrix[ch1][ch2] ), *max_corr ) )
     168             :             {
     169      128442 :                 *_ch1 = ch1;
     170      128442 :                 *_ch2 = ch2;
     171      128442 :                 *max_corr = xCorrMatrix[ch1][ch2]; /* assign to max_corr its actual value */ // Qx
     172      128442 :                 move16();
     173      128442 :                 move16();
     174      128442 :                 move32();
     175      128442 :                 BREAK;
     176             :             }
     177             :         }
     178             :     }
     179             : 
     180       99511 :     return;
     181             : }
     182             : 
     183             : 
     184             : /*-----------------------------------------------------------------------*
     185             :  * getCorrelationMatrix()
     186             :  *
     187             :  * calculates the cross correlation matrix for all active
     188             :  * channels
     189             :  *-----------------------------------------------------------------------*/
     190       99513 : static void getCorrelationMatrix_fx(
     191             :     Encoder_State **sts,                                    /* i  : core coder handle                                 */
     192             :     MCT_ENC_HANDLE hMCT,                                    /* i  : MCT handle                                        */
     193             :     Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS], /* o  : cross-correlation matrix, exponent: xCorrMatrix_e */
     194             :     Word16 *xCorrMatrix_e                                   /* o  : exponent of cross-correlation matrix              */
     195             : )
     196             : {
     197             :     Word16 ch1, ch2, n, nchan, res_q, s, max_e;
     198             :     Word16 xCorrMatrix_exp[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS];
     199             :     Word32 L_tmp;
     200             :     Word64 W_tmp;
     201             : 
     202       99513 :     nchan = hMCT->nchan_out_woLFE;
     203       99513 :     move16();
     204             : 
     205             :     /* correlation */
     206      557190 :     FOR( ch1 = 0; ch1 < nchan; ch1++ )
     207             :     {
     208     1891740 :         FOR( ch2 = ch1; ch2 < nchan; ch2++ )
     209             :         {
     210     1434063 :             xCorrMatrix[ch1][ch2] = 0;
     211     1434063 :             move32();
     212     1434063 :             xCorrMatrix_exp[ch1][ch2] = 0;
     213     1434063 :             move16();
     214             : 
     215     1434063 :             test();
     216     1434063 :             test();
     217     1434063 :             IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
     218             :                 NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     219             :             {
     220             :                 Word16 nSubframes;
     221             :                 Word16 L_subframe;
     222     1357483 :                 IF( EQ_16( sts[ch1]->core, TCX_20 ) )
     223             :                 {
     224     1336477 :                     nSubframes = 1;
     225     1336477 :                     move16();
     226     1336477 :                     L_subframe = sts[ch1]->hTcxEnc->L_frameTCX;
     227     1336477 :                     move16();
     228             :                 }
     229             :                 ELSE
     230             :                 {
     231       21006 :                     nSubframes = NB_DIV;
     232       21006 :                     move16();
     233       21006 :                     L_subframe = shr( sts[ch1]->hTcxEnc->L_frameTCX, 1 );
     234             :                 }
     235             : 
     236     2735972 :                 FOR( n = 0; n < nSubframes; n++ )
     237             :                 {
     238     1378489 :                     res_q = sub( 31, sts[0]->hTcxEnc->spectrum_e[0] );
     239     1378489 :                     L_tmp = dotp_fixed_32( sts[ch1]->hTcxEnc->spectrum_fx[n], sts[ch2]->hTcxEnc->spectrum_fx[n], L_subframe, 1, &res_q );
     240     1378489 :                     xCorrMatrix[ch1][ch2] = BASOP_Util_Add_Mant32Exp( xCorrMatrix[ch1][ch2], xCorrMatrix_exp[ch1][ch2], L_tmp, sub( 31, res_q ), &xCorrMatrix_exp[ch1][ch2] );
     241     1378489 :                     move32();
     242             :                 }
     243             :             }
     244             :         }
     245             :     }
     246             : 
     247             :     /* normalize */
     248      557190 :     FOR( ch1 = 0; ch1 < nchan; ch1++ )
     249             :     {
     250     1434063 :         FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
     251             :         {
     252             :             // tmp = sqrtf( xCorrMatrix[ch1][ch1] * xCorrMatrix[ch2][ch2] );
     253      976386 :             W_tmp = W_mult0_32_32( xCorrMatrix[ch1][ch1], xCorrMatrix[ch2][ch2] ); // ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] )
     254      976386 :             s = W_norm( W_tmp );
     255      976386 :             L_tmp = W_extract_h( W_shl( W_tmp, s ) ); // s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32
     256             : 
     257      976386 :             s = sub( add( s, 30 ), add( xCorrMatrix_exp[ch1][ch1], xCorrMatrix_exp[ch2][ch2] ) ); // s = s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32;
     258      976386 :             s = sub( 31, s );
     259      976386 :             L_tmp = Sqrt32( L_tmp, &s );
     260             : 
     261      976386 :             IF( L_tmp > 0 )
     262             :             {
     263             :                 // xCorrMatrix[ch1][ch2] /= tmp;
     264      935280 :                 xCorrMatrix[ch1][ch2] = L_deposit_h( BASOP_Util_Divide3232_Scale( xCorrMatrix[ch1][ch2], L_tmp, &res_q ) );
     265      935280 :                 xCorrMatrix_exp[ch1][ch2] = add( res_q, sub( xCorrMatrix_exp[ch1][ch2], s ) );
     266      935280 :                 move32();
     267      935280 :                 move16();
     268             :             }
     269             :             ELSE
     270             :             {
     271       41106 :                 xCorrMatrix[ch1][ch2] = 0;
     272       41106 :                 xCorrMatrix_exp[ch1][ch2] = 0;
     273       41106 :                 move32();
     274       41106 :                 move16();
     275             :             }
     276             :         }
     277             :     }
     278             : 
     279             :     /* Aligning the variable exponents for each element to a common exponent */
     280       99513 :     s = 31;
     281       99513 :     *xCorrMatrix_e = 0;
     282       99513 :     move16();
     283       99513 :     move16();
     284             : 
     285      457677 :     FOR( ch1 = 0; ch1 < nchan - 1; ch1++ )
     286             :     {
     287      358164 :         s = s_min( s, getScaleFactor32( &xCorrMatrix[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ) ) );
     288      358164 :         maximum_s( &xCorrMatrix_exp[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ), &max_e );
     289      358164 :         *xCorrMatrix_e = s_max( *xCorrMatrix_e, max_e );
     290      358164 :         move16();
     291             :     }
     292             : 
     293      557190 :     FOR( ch1 = 0; ch1 < nchan; ch1++ )
     294             :     {
     295     1434063 :         FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ )
     296             :         {
     297      976386 :             xCorrMatrix[ch1][ch2] = L_shl_sat( xCorrMatrix[ch1][ch2], add( s, sub( xCorrMatrix_exp[ch1][ch2], *xCorrMatrix_e ) ) ); // xCorrMatrix_e - s
     298      976386 :             move32();
     299             :         }
     300             :     }
     301       99513 :     *xCorrMatrix_e = sub( *xCorrMatrix_e, s );
     302       99513 :     move16();
     303             : 
     304       99513 :     return;
     305             : }
     306             : 
     307             : 
     308             : /*-----------------------------------------------------------------*
     309             :  * getBestCorrelation()
     310             :  *
     311             :  * searches for the best correlated channel pair
     312             :  *------------------------------------------------------------------*/
     313       93608 : static void getBestCorrelation_fx(
     314             :     MCT_ENC_HANDLE hMCT,                                     /* i  : MCT handle                                                      */
     315             :     Word16 *_ch1,                                            /* o  : first channel of selected channel-pair, Q0                      */
     316             :     Word16 *_ch2,                                            /* o  : second channel of selected channel-pair, Q0                     */
     317             :     Word32 *max_corr,                                        /* o  : normalized cross correlation value of selected channel pair, Qx */
     318             :     Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] ) /* i  : cross-correlation matrix, Qx                                    */
     319             : {
     320             :     Word16 ch1, ch2;
     321             : 
     322       93608 :     *_ch1 = -1;
     323       93608 :     *_ch2 = -1;
     324       93608 :     *max_corr = 0;
     325       93608 :     move16();
     326       93608 :     move16();
     327       93608 :     move32();
     328             : 
     329      616897 :     FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
     330             :     {
     331     1905777 :         FOR( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
     332             :         {
     333     1382488 :             IF( LT_32( L_abs( *max_corr ), L_abs( xCorrMatrix[ch1][ch2] ) ) )
     334             :             {
     335      186298 :                 *max_corr = xCorrMatrix[ch1][ch2]; // Qx
     336      186298 :                 move32();
     337             : 
     338      186298 :                 *_ch1 = ch1;
     339      186298 :                 *_ch2 = ch2;
     340      186298 :                 move16();
     341      186298 :                 move16();
     342             :             }
     343             :         }
     344             :     }
     345             : 
     346       93608 :     return;
     347             : }
     348             : 
     349             : 
     350             : /*----------------------------------------------------------------------*
     351             :  * getBlockValues()
     352             :  * stereo processing for the channels of current block
     353             :  *----------------------------------------------------------------------*/
     354       93690 : static void getBlockValues_fx(
     355             :     Encoder_State **sts,                            /* i/o: core coder handle                             */
     356             :     const Word16 ch1,                               /* i  : first channel of channel-pair                 */
     357             :     const Word16 ch2,                               /* i  : second channel of channel-pair                */
     358             :     MCT_BLOCK_DATA *hBlock,                         /* i  : stereo block handle                           */
     359             :     Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2],     /* i/o: MDST spectrum, Q = q_spec                     */
     360             :     Word32 *inv_spectrum[MCT_MAX_CHANNELS][2],      /* i/o: inverse spectrum, Q = q_spec                  */
     361             :     Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: invers MDST spectrum, Q = q_spec              */
     362             :     Word16 q_spec                                   /* i  : common Q factor of the above spectrum buffers */
     363             : )
     364             : {
     365             :     Word16 n;
     366             :     Word32 *p_mdst_spectrum[2][2];
     367             :     Word32 *p_inv_spectrum[2][2];
     368             :     Word32 *p_inv_mdst_spectrum[2][2];
     369             :     Encoder_State *p_st[2];
     370             : 
     371             :     /* init return values: */
     372       93690 :     hBlock->isActive = 1;
     373       93690 :     move16();
     374             : 
     375             :     /* map vectors to current block channels */
     376      281070 :     FOR( n = 0; n < 2; n++ )
     377             :     {
     378      187380 :         p_mdst_spectrum[0][n] = mdst_spectrum[ch1][n];         // q_spec
     379      187380 :         p_mdst_spectrum[1][n] = mdst_spectrum[ch2][n];         // q_spec
     380      187380 :         p_inv_spectrum[0][n] = inv_spectrum[ch1][n];           // q_spec
     381      187380 :         p_inv_spectrum[1][n] = inv_spectrum[ch2][n];           // q_spec
     382      187380 :         p_inv_mdst_spectrum[0][n] = inv_mdst_spectrum[ch1][n]; // q_spec
     383      187380 :         p_inv_mdst_spectrum[1][n] = inv_mdst_spectrum[ch2][n]; // q_spec
     384             :     }
     385       93690 :     p_st[0] = sts[ch1];
     386       93690 :     p_st[1] = sts[ch2];
     387             : 
     388       93690 :     stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1, sub( 31, q_spec ), sub( 31, q_spec ) );
     389             : 
     390       93690 :     test();
     391       93690 :     test();
     392       93690 :     test();
     393       93690 :     test();
     394       93690 :     if ( ( EQ_16( sts[ch1]->core, TCX_20_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) || ( EQ_16( sts[ch1]->core, TCX_10_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO && hBlock->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) )
     395             :     {
     396        4077 :         hBlock->isActive = 0;
     397        4077 :         move16();
     398             :     }
     399             : 
     400       93690 :     return;
     401             : }
     402             : 
     403             : 
     404             : /*-------------------------------------------------------------------*
     405             :  * updateCorrelationMatrix()
     406             :  *
     407             :  * updates the cross correlation matrix with modified spectra after
     408             :  * stereo block processing
     409             :  *-------------------------------------------------------------------*/
     410       89613 : static void updateCorrelationMatrix_fx(
     411             :     Encoder_State **sts,
     412             :     MCT_ENC_HANDLE hMCT,
     413             :     const Word16 _ch1,
     414             :     const Word16 _ch2,
     415             :     Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] // Qx
     416             : )
     417             : {
     418             :     Word16 ch1, ch2, n;
     419             : 
     420             :     /* correlation: */
     421      595448 :     FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ )
     422             :     {
     423     2407987 :         FOR( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ )
     424             :         {
     425     1902152 :             test();
     426     1902152 :             test();
     427     1902152 :             IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
     428             :                 NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     429             :             {
     430             :                 Word16 nSubframes;
     431     1829062 :                 IF( EQ_16( sts[ch1]->core, TCX_20 ) )
     432             :                 {
     433     1788622 :                     nSubframes = 1;
     434     1788622 :                     move16();
     435             :                 }
     436             :                 ELSE
     437             :                 {
     438       40440 :                     nSubframes = NB_DIV;
     439       40440 :                     move16();
     440             :                 }
     441             : 
     442     1829062 :                 test();
     443     1829062 :                 test();
     444     1829062 :                 test();
     445     1829062 :                 IF( EQ_16( ch1, _ch1 ) || EQ_16( ch2, _ch2 ) || EQ_16( ch1, _ch2 ) || EQ_16( ch2, _ch1 ) )
     446             :                 {
     447     1797824 :                     FOR( n = 0; n < nSubframes; n++ )
     448             :                     {
     449      906565 :                         xCorrMatrix[ch1][ch2] = 0; /*disable combinations with channels already processed */
     450      906565 :                         move32();
     451             :                     }
     452             :                 }
     453             :             }
     454             :         }
     455             :     }
     456             : 
     457       89613 :     return;
     458             : }
     459             : 
     460             : 
     461             : /*----------------------------------------------------------*
     462             :  * channelPairToIndex()
     463             :  * get the index of each channel pair
     464             :  *----------------------------------------------------------*/
     465       89613 : static Word16 channelPairToIndex_fx(
     466             :     const Word16 chIdx1,
     467             :     const Word16 chIdx2,
     468             :     const Word16 nChannels )
     469             : {
     470             :     Word16 ch1, ch2;
     471             :     Word16 pairIdx;
     472             : 
     473       89613 :     pairIdx = 0;
     474       89613 :     move16();
     475             : 
     476      333076 :     FOR( ch2 = 1; ch2 < nChannels; ch2++ )
     477             :     {
     478     1073212 :         FOR( ch1 = 0; ch1 < ch2; ch1++ )
     479             :         {
     480      829749 :             test();
     481      829749 :             IF( EQ_16( ch1, chIdx1 ) && EQ_16( ch2, chIdx2 ) )
     482             :             {
     483       89613 :                 return pairIdx;
     484             :             }
     485             :             ELSE
     486             :             {
     487      740136 :                 pairIdx = add( pairIdx, 1 );
     488             :             }
     489             :         }
     490             :     }
     491             : 
     492           0 :     return -1;
     493             : }
     494             : 
     495             : /*--------------------------------------------------------------------*
     496             :  * getGlobalILD()
     497             :  * get broadband ILD to mean energy and normalize channels with ratio
     498             :  *--------------------------------------------------------------------*/
     499       99513 : static void getGlobalILD_fx(
     500             :     Encoder_State **sts,
     501             :     MCT_ENC_HANDLE hMCT,
     502             :     Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], // Exponent is same as spectrum_fx i.e. spectrum_e
     503             :     const Word16 nchan )
     504             : {
     505             :     Word16 k, ch, nSubframes, L_subframe;
     506             :     Word32 nrg[MCT_MAX_CHANNELS];
     507             :     Word16 nrg_e[MCT_MAX_CHANNELS];
     508             :     Word16 ratio_fx, qratio;
     509       99513 :     Word32 meanE = 0;
     510             :     Word32 L_tmp;
     511       99513 :     Word16 cnt = 0, meanE_e = 0, L_tmp_e;
     512       99513 :     move32();
     513       99513 :     move16();
     514       99513 :     move16();
     515             : 
     516             :     /*Initializations*/
     517       99513 :     set16_fx( hMCT->lowE_ch, 0, nchan );
     518             : 
     519       99513 :     getChannelEnergies_fx( sts, nrg, nrg_e, nchan );
     520             : 
     521             :     /*calculate total energy without LFE*/
     522      557190 :     FOR( ch = 0; ch < nchan; ch++ )
     523             :     {
     524      457677 :         IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     525             :         {
     526      445645 :             meanE = BASOP_Util_Add_Mant32Exp( meanE, meanE_e, nrg[ch], nrg_e[ch], &meanE_e );
     527      445645 :             cnt = add( cnt, 1 );
     528             :         }
     529             :     }
     530             : 
     531             :     /*calculate mean energy*/
     532       99513 :     assert( cnt >= 2 );
     533       99513 :     L_tmp = BASOP_Util_Divide3216_Scale( meanE, cnt, &L_tmp_e );
     534       99513 :     L_tmp_e = add( L_tmp_e, sub( meanE_e, 15 ) );
     535             : 
     536             :     // meanE = max( meanE / cnt, EPSILON );
     537       99513 :     IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, EPSILON_FX_M, EPSILON_FX_E ), 1 ) )
     538             :     {
     539       99513 :         meanE = L_deposit_h( (Word16) L_tmp );
     540       99513 :         meanE_e = L_tmp_e;
     541       99513 :         move32();
     542       99513 :         move16();
     543             :     }
     544             :     ELSE
     545             :     {
     546           0 :         meanE = EPSILON_FX_M;
     547           0 :         meanE_e = EPSILON_FX_E;
     548           0 :         move32();
     549           0 :         move16();
     550             :     }
     551             : 
     552      557190 :     FOR( ch = 0; ch < nchan; ch++ )
     553             :     {
     554      457677 :         IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     555             :         {
     556      445645 :             IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) )
     557             :             {
     558      436002 :                 nSubframes = 1;
     559      436002 :                 move16();
     560      436002 :                 L_subframe = sts[ch]->hTcxEnc->L_frameTCX;
     561      436002 :                 move16();
     562             :             }
     563             :             ELSE
     564             :             {
     565        9643 :                 nSubframes = NB_DIV;
     566        9643 :                 move16();
     567        9643 :                 L_subframe = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
     568             :             }
     569             : 
     570      445645 :             IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( nrg[ch], nrg_e[ch], meanE, meanE_e ), 1 ) ) /*change it to meanE if final solution*/
     571             :             {
     572             :                 // ratio_fx = meanE / nrg[ch];
     573      166036 :                 ratio_fx = BASOP_Util_Divide3232_Scale( meanE, nrg[ch], &L_tmp_e );
     574      166036 :                 L_tmp_e = add( L_tmp_e, sub( meanE_e, nrg_e[ch] ) );
     575      166036 :                 ratio_fx = shl_sat( ratio_fx, L_tmp_e );
     576             : 
     577      166036 :                 hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
     578      166036 :                 move16();
     579             : 
     580      166036 :                 qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE / 2 ); // Q11
     581             :             }
     582             :             ELSE
     583             :             {
     584             :                 // ratio_fx = nrg[ch] / meanE;
     585      279609 :                 ratio_fx = BASOP_Util_Divide3232_Scale( nrg[ch], meanE, &L_tmp_e );
     586      279609 :                 L_tmp_e = add( L_tmp_e, sub( nrg_e[ch], meanE_e ) );
     587      279609 :                 ratio_fx = shl_sat( ratio_fx, L_tmp_e );
     588             : 
     589      279609 :                 hMCT->lowE_ch[ch] = 1;
     590      279609 :                 move16();
     591             : 
     592      279609 :                 hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) );
     593      279609 :                 move16();
     594             : 
     595      279609 :                 qratio = shl_sat( div_l( ( (Word32) SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ), 1 ); // Q11
     596             :             }
     597             : 
     598      900933 :             FOR( k = 0; k < nSubframes; k++ )
     599             :             {
     600      455288 :                 sts[ch]->hTcxEnc->spectrum_e[k] = add( sts[ch]->hTcxEnc->spectrum_e[k], 4 ); // Updating exponent of spectrum as q_ratio is in Q11
     601             :             }
     602      445645 :             IF( GT_16( nSubframes, 1 ) )
     603             :             {
     604        9643 :                 sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, 4 );
     605        9643 :                 move16();
     606             :             }
     607             : 
     608      900933 :             FOR( k = 0; k < nSubframes; k++ )
     609             :             {
     610      455288 :                 v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframe ); // sts[ch]->hTcxEnc->spectrum_e
     611      455288 :                 v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframe );                         // sts[ch]->hTcxEnc->spectrum_e
     612             :             }
     613             :         }
     614             :     }
     615             : 
     616             : 
     617       99513 :     return;
     618             : }
     619             : 
     620             : 
     621             : /*--------------------------------------------------------------------*
     622             :  * apply_MCT_enc()
     623             :  *
     624             :  * apply MCT algorithm to input channels
     625             :  *--------------------------------------------------------------------*/
     626       99969 : void apply_MCT_enc_fx(
     627             :     MCT_ENC_HANDLE hMCT,                                 /* i/o: MCT encoder structure               */
     628             :     Encoder_State **sts,                                 /* i/o: encoder state structure             */
     629             :     Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV],     /* i/o: MDST spectrum                       Qx*/
     630             :     Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV],      /* i/o: inverse spectrum                    Qx*/
     631             :     Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum               Qx*/
     632             :     const Word16 nchan                                   /* i  : number of channels                  */
     633             : )
     634             : {
     635             :     Word16 ch, k, ch1, ch2, nSubframes, L_subframeTCX;
     636             :     Word32 max_corr;
     637             :     Word16 forceKeepTree, pair, qratio;
     638             :     Word32 sumCorrDiff, thr;
     639             :     Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS];
     640             :     Word16 currBlockDataCnt;
     641             :     Word16 cpEle[MCT_MAX_CHANNELS];
     642             :     Word16 inactiveBlockDetected;
     643             :     Word16 tmp_ch1, tmp_ch2, tmp;
     644             :     Word32 tmp_max_corr, L_tmp;
     645       99969 :     Word16 count_active_ch = 0;
     646       99969 :     Word16 xCorrMatrix_e = 0, sumCorrDiff_e = 0, L_tmp_e;
     647       99969 :     move16();
     648       99969 :     move16();
     649       99969 :     move16();
     650             : 
     651       99969 :     push_wmops( "mct_core_enc_mct" );
     652             : 
     653       99969 :     forceKeepTree = 1;
     654       99969 :     inactiveBlockDetected = 0;
     655       99969 :     move16();
     656       99969 :     move16();
     657       99969 :     set16_fx( cpEle, 0, MCT_MAX_CHANNELS );
     658             : 
     659             :     /*Determine active channels*/
     660      559666 :     FOR( ch = 0; ch < nchan; ch++ )
     661             :     {
     662      459697 :         IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     663             :         {
     664      445954 :             count_active_ch = add( count_active_ch, 1 );
     665             :         }
     666             :         ELSE
     667             :         {
     668       13743 :             hMCT->mc_global_ild[ch] = 0;
     669       13743 :             move16();
     670             :         }
     671             :     }
     672             : 
     673             :     /*there should be at least one cp*/
     674       99969 :     IF( GE_16( count_active_ch, CPE_CHANNELS ) )
     675             :     {
     676             :         /*Normalize energies with global ILD*/
     677       99513 :         getGlobalILD_fx( sts, hMCT, mdst_spectrum, nchan );
     678       99513 :         getCorrelationMatrix_fx( sts, hMCT, xCorrMatrix, &xCorrMatrix_e );
     679             : 
     680             :         /*check if previous tree should be kept*/
     681       99513 :         sumCorrDiff = 0;
     682       99513 :         move32();
     683             :         // thr = 0.15f * (float) ( count_active_ch ) * ( count_active_ch - 1 ) / 2.0f;
     684       99513 :         thr = Mpy_32_16_1( 161061274, imult1616( count_active_ch, sub( count_active_ch, 1 ) ) ); /* Q16 */ /* 161061274 = 0.15 / 2 in Q31 */
     685             : 
     686      457677 :         FOR( ch2 = 1; ch2 < nchan; ch2++ )
     687             :         {
     688     1334550 :             FOR( ch1 = 0; ch1 < ch2; ch1++ )
     689             :             {
     690      976386 :                 test();
     691      976386 :                 IF( NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) &&
     692             :                     NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     693             :                 {
     694      935280 :                     L_tmp = L_abs( BASOP_Util_Add_Mant32Exp( hMCT->lastxCorrMatrix_fx[ch1][ch2], hMCT->lastxCorrMatrix_e, L_negate( xCorrMatrix[ch1][ch2] ), xCorrMatrix_e, &L_tmp_e ) );
     695      935280 :                     sumCorrDiff = BASOP_Util_Add_Mant32Exp( sumCorrDiff, sumCorrDiff_e, L_tmp, L_tmp_e, &sumCorrDiff_e );
     696             :                 }
     697             :             }
     698             :         }
     699             : 
     700       99513 :         if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( sumCorrDiff, sumCorrDiff_e, thr, 15 ), 1 ) )
     701             :         {
     702       41947 :             forceKeepTree = 0;
     703       41947 :             move16();
     704             :         }
     705             : 
     706             :         /* check if keepTree is applied on unallowed blocks (e.g. channel pairs with different cores) */
     707       99513 :         IF( forceKeepTree )
     708             :         {
     709       57566 :             IF( !hMCT->currBlockDataCnt )
     710             :             {
     711       22049 :                 forceKeepTree = 0;
     712       22049 :                 move16();
     713             :             }
     714             :             ELSE
     715             :             {
     716       98875 :                 FOR( pair = 0; pair < hMCT->currBlockDataCnt; pair++ )
     717             :                 {
     718       63358 :                     if ( xCorrMatrix[hMCT->hBlockData[pair]->ch1][hMCT->hBlockData[pair]->ch2] == 0 )
     719             :                     {
     720         107 :                         forceKeepTree = 0;
     721         107 :                         move16();
     722             :                     }
     723             :                 }
     724             :             }
     725             :         }
     726             : 
     727             :         /*save initial correlation matrix for next frame*/
     728      557190 :         FOR( ch1 = 0; ch1 < nchan; ch1++ )
     729             :         {
     730     1891740 :             FOR( ch2 = ch1; ch2 < nchan; ch2++ )
     731             :             {
     732     1434063 :                 hMCT->lastxCorrMatrix_fx[ch1][ch2] = xCorrMatrix[ch1][ch2];
     733     1434063 :                 move32();
     734             :             }
     735             :         }
     736       99513 :         hMCT->lastxCorrMatrix_e = xCorrMatrix_e;
     737       99513 :         move16();
     738       99513 :         move16();
     739       99513 :         currBlockDataCnt = 0;
     740      193119 :         WHILE( ( currBlockDataCnt < hMCT->nchan_out_woLFE ) )
     741             :         {
     742             :             /* find best fitting channel pair: */
     743      193119 :             ch1 = -1;
     744      193119 :             ch2 = -1;
     745      193119 :             max_corr = 0;
     746      193119 :             move16();
     747      193119 :             move16();
     748      193119 :             move32();
     749             : 
     750      193119 :             IF( !forceKeepTree )
     751             :             {
     752       99511 :                 getNextBestCorrelation_fx( xCorrMatrix, &ch1, &ch2, &max_corr, inactiveBlockDetected, nchan );
     753             :             }
     754             :             ELSE
     755             :             {
     756       93608 :                 getBestCorrelation_fx( hMCT, &tmp_ch1, &tmp_ch2, &tmp_max_corr, xCorrMatrix );
     757             : 
     758       93608 :                 IF( EQ_16( currBlockDataCnt, hMCT->currBlockDataCnt ) )
     759             :                 {
     760       30640 :                     BREAK;
     761             :                 }
     762             :                 ELSE
     763             :                 {
     764       62968 :                     ch1 = hMCT->hBlockData[currBlockDataCnt]->ch1;
     765       62968 :                     ch2 = hMCT->hBlockData[currBlockDataCnt]->ch2;
     766       62968 :                     move16();
     767       62968 :                     move16();
     768             : 
     769             :                     /*don't allow forcing of channel-pair if their correlation is under the  threshold*/
     770       62968 :                     max_corr = xCorrMatrix[ch1][ch2];
     771       62968 :                     move32();
     772             : 
     773       62968 :                     tmp = BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31 /* 0.3 in Q31 */, 0 );
     774       62968 :                     test();
     775       62968 :                     IF( EQ_16( tmp, -1 ) || tmp == 0 )
     776             :                     {
     777        4320 :                         ch1 = tmp_ch1;
     778        4320 :                         ch2 = tmp_ch2;
     779        4320 :                         max_corr = tmp_max_corr;
     780        4320 :                         forceKeepTree = 0;
     781        4320 :                         move16();
     782        4320 :                         move16();
     783        4320 :                         move32();
     784        4320 :                         move16();
     785             :                     }
     786             :                 }
     787             :             }
     788             : 
     789      162479 :             test();
     790      162479 :             test();
     791      162479 :             test();
     792      162479 :             IF( ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31, 0 ), 1 ) && !hMCT->hbr_mct ) || ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, SPAR_CORR_THRES_Q31, 0 ), 1 ) && hMCT->hbr_mct ) )
     793             :             {
     794       93690 :                 IF( !forceKeepTree )
     795             :                 {
     796             :                     /*save channel pair*/
     797       35055 :                     hMCT->hBlockData[currBlockDataCnt]->ch1 = ch1;
     798       35055 :                     hMCT->hBlockData[currBlockDataCnt]->ch2 = ch2;
     799       35055 :                     move16();
     800       35055 :                     move16();
     801             :                 }
     802             : 
     803             :                 /* calculate all related values: */
     804       93690 :                 assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE );
     805             : 
     806       93690 :                 getBlockValues_fx( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum, sub( 31, sts[0]->hTcxEnc->spectrum_e[0] ) );
     807             : 
     808       93690 :                 IF( hMCT->hBlockData[currBlockDataCnt]->isActive == 0 )
     809             :                 {
     810        4077 :                     inactiveBlockDetected = add( inactiveBlockDetected, 1 );
     811        4077 :                     IF( GT_16( inactiveBlockDetected, shr( hMCT->nchan_out_woLFE, 1 ) ) )
     812             :                     {
     813          84 :                         BREAK;
     814             :                     }
     815        3993 :                     forceKeepTree = 0;
     816        3993 :                     move16();
     817             : 
     818        3993 :                     CONTINUE; /* skip inactive blocks where stereo mode is dual-mono */
     819             :                 }
     820             : 
     821       89613 :                 updateCorrelationMatrix_fx( sts, hMCT, ch1, ch2, xCorrMatrix );
     822       89613 :                 cpEle[ch1] = 1;
     823       89613 :                 cpEle[ch2] = 1;
     824       89613 :                 move16();
     825       89613 :                 move16();
     826             : 
     827       89613 :                 currBlockDataCnt = add( currBlockDataCnt, 1 );
     828             :             }
     829             :             ELSE
     830             :             {
     831             :                 BREAK;
     832             :             }
     833             :         }
     834             : 
     835             :         /*save number of blocks for next frame*/
     836       99513 :         hMCT->currBlockDataCnt = currBlockDataCnt;
     837       99513 :         move16();
     838             : 
     839      557190 :         FOR( ch = 0; ch < nchan; ch++ )
     840             :         {
     841      457677 :             IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     842             :             {
     843      445645 :                 test();
     844      445645 :                 IF( ( !cpEle[ch] ) || hMCT->currBlockDataCnt == 0 )
     845             :                 {
     846      266419 :                     IF( EQ_16( sts[ch]->core, TCX_20_CORE ) )
     847             :                     {
     848      260560 :                         nSubframes = 1;
     849      260560 :                         move16();
     850      260560 :                         L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX;
     851      260560 :                         move16();
     852             :                     }
     853             :                     ELSE
     854             :                     {
     855        5859 :                         nSubframes = NB_DIV;
     856        5859 :                         move16();
     857        5859 :                         L_subframeTCX = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 );
     858             :                     }
     859             : 
     860             :                     Word16 exp;
     861      266419 :                     IF( hMCT->lowE_ch[ch] )
     862             :                     {
     863             :                         // qratio = (float) hMCT->mc_global_ild[ch] / SMDCT_ILD_RANGE;
     864      168821 :                         qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE ); // Q10
     865             :                     }
     866             :                     ELSE
     867             :                     {
     868             :                         // qratio = (float) SMDCT_ILD_RANGE / hMCT->mc_global_ild[ch];
     869       97598 :                         qratio = div_l( ( SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ); // Q10
     870             :                     }
     871      266419 :                     exp = norm_s( qratio );
     872      266419 :                     qratio = shl( qratio, exp );
     873      266419 :                     exp = sub( 5, exp ); // Q = 10 + exp
     874             : 
     875      538697 :                     FOR( k = 0; k < nSubframes; k++ )
     876             :                     {
     877      272278 :                         v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframeTCX );
     878      272278 :                         v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframeTCX );
     879      272278 :                         set32_fx( inv_spectrum[ch][k], 0, L_subframeTCX );
     880             :                     }
     881      266419 :                     sts[ch]->hTcxEnc->spectrum_e[1] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
     882      266419 :                     sts[ch]->hTcxEnc->spectrum_e[0] = add( sts[ch]->hTcxEnc->spectrum_e[0], exp );
     883      266419 :                     sts[ch]->hTcxEnc->spectrum_long_e = add( sts[ch]->hTcxEnc->spectrum_long_e, exp );
     884      266419 :                     hMCT->mc_global_ild[ch] = 0;
     885      266419 :                     move16();
     886      266419 :                     move16();
     887      266419 :                     move16();
     888      266419 :                     move16();
     889             :                 }
     890             :             }
     891             :         }
     892             :     }
     893             :     ELSE
     894             :     {
     895         456 :         hMCT->currBlockDataCnt = 0;
     896         456 :         move16();
     897        2476 :         FOR( ch = 0; ch < nchan; ch++ )
     898             :         {
     899        2020 :             hMCT->mc_global_ild[ch] = 0;
     900        2020 :             move16();
     901             :         }
     902             :     }
     903             : 
     904       99969 :     pop_wmops();
     905             : 
     906       99969 :     return;
     907             : }
     908             : 
     909             : /*--------------------------------------------------------------------*
     910             :  * write_mct_bitstream()
     911             :  *
     912             :  * write mct metadata to bitstream
     913             :  *--------------------------------------------------------------------*/
     914       99969 : void write_mct_bitstream_fx(
     915             :     Encoder_State **sts, /* i/o: encoder state structure     */
     916             :     MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure       */
     917             :     const Word16 nchan   /* i  : number of channels          */
     918             : )
     919             : {
     920             :     Word16 pair, ch;
     921             :     Word16 channelPairIndex;
     922             :     Word16 nbits_start;
     923             :     MCT_BLOCK_DATA_HANDLE hBlock;
     924             :     Encoder_State *p_st[2];
     925       99969 :     BSTR_ENC_HANDLE hBstr = sts[0]->hBstr;
     926             : 
     927       99969 :     nbits_start = hBstr->nb_bits_tot;
     928       99969 :     move16();
     929             : 
     930       99969 :     push_next_indice( hBstr, hMCT->currBlockDataCnt, MCT_NUM_BLOCK_DATA_BITS );
     931             : 
     932             :     /* first write core info and overlap mode for all channels */
     933      559666 :     FOR( ch = 0; ch < nchan; ch++ )
     934             :     {
     935      459697 :         test();
     936      459697 :         IF( hMCT->currBlockDataCnt && NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     937             :         {
     938      272784 :             push_next_indice( hBstr, hMCT->mc_global_ild[ch], SMDCT_GLOBAL_ILD_BITS );
     939             :         }
     940             :     }
     941             : 
     942       99969 :     IF( hMCT->currBlockDataCnt )
     943             :     {
     944      332890 :         FOR( ch = 0; ch < nchan; ch++ )
     945             :         {
     946      278096 :             IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
     947             :             {
     948      272784 :                 push_next_indice( hBstr, hMCT->lowE_ch[ch], 1 );
     949             :             }
     950             :         }
     951             :     }
     952             : 
     953             :     /* Do for each stereo block */
     954      189582 :     FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- )
     955             :     {
     956       89613 :         hBlock = hMCT->hBlockData[pair];
     957             : 
     958             :         /*calculate channel pair index and write it to BS*/
     959       89613 :         channelPairIndex = channelPairToIndex_fx( hBlock->ch1, hBlock->ch2, nchan );
     960       89613 :         push_next_indice( hBstr, channelPairIndex, hMCT->bitsChannelPairIndex );
     961             : 
     962             :         /*point to encoder states of actual channels to write block pair bits*/
     963       89613 :         p_st[0] = sts[hBlock->ch1];
     964       89613 :         p_st[1] = sts[hBlock->ch2];
     965             : 
     966             :         /*then business as usual for each block pair */
     967       89613 :         write_stereo_to_bitstream_fx( hMCT->hBlockData[pair]->hStereoMdct, p_st, hBlock->mask, 1, hBstr );
     968             :     }
     969             : 
     970       99969 :     hMCT->nBitsMCT = sub( hBstr->nb_bits_tot, nbits_start );
     971       99969 :     move16();
     972             : 
     973       99969 :     return;
     974             : }
     975             : 
     976             : /*--------------------------------------------------------------------*
     977             :  * mctStereoIGF_enc()
     978             :  *
     979             :  * IGF analysis of channels after MCT processing
     980             :  *--------------------------------------------------------------------*/
     981       34621 : void mctStereoIGF_enc_fx(
     982             :     MCT_ENC_HANDLE hMCT,                                 /* i/o: MCT encoder structure                      */
     983             :     Encoder_State **sts,                                 /* i/o: encoder state structure                    */
     984             :     Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2],       /* i  : MDCT spectrum for ITF                      */
     985             :     Word16 q_origSpec,                                   /* i  : Q for MDCT spectrum                        */
     986             :     Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k],   /* i/o: MDCT^2 + MDST^2 spectrum,or estimate       */
     987             :     Word16 q_powerSpec[MCT_MAX_CHANNELS],                /* i  : Q for powSpec_fx                           */
     988             :     Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i  : same as powerSpec_fx but for inverse spect.*/
     989             :     Word16 q_powerSpecMsInv[MCT_MAX_CHANNELS],           /* i  : Q for powSpecMsInv_fx                      */
     990             :     Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV],   /* i  : inverse spectrum                           */
     991             :     const Word16 sp_aud_decision0[MCT_MAX_CHANNELS]      /* i  : speech audio decision                      */
     992             : )
     993             : {
     994             :     Word32 *p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV];
     995             :     Word32 *p_inv_spectrum_fx[CPE_CHANNELS][NB_DIV];
     996             :     Word32 *p_orig_spectrum_fx[CPE_CHANNELS][NB_DIV];
     997             :     Word32 *p_powerSpec_fx[NB_DIV];
     998             : 
     999             :     Word16 b, nSubframes, L_subframeTCX;
    1000             :     Word16 p_ch[2], n, ch, ch1, ch2;
    1001             :     Word16 q_pSI_ch[2];
    1002             :     Word16 q_pS_ch[2];
    1003             :     Encoder_State *p_st[NB_DIV];
    1004             :     Encoder_State *st;
    1005             :     Word16 singleChEle[MCT_MAX_CHANNELS];
    1006             :     Word16 q_spectrum;
    1007             :     Word16 exp_powerSpec[MCT_MAX_CHANNELS][N_MAX + L_MDCT_OVLP_MAX];
    1008             : 
    1009       34621 :     L_subframeTCX = 0; /* to avoid compilation warning */
    1010       34621 :     move16();
    1011       34621 :     set16_fx( singleChEle, 1, hMCT->nchan_out_woLFE );
    1012             : 
    1013       93543 :     FOR( b = 0; b < hMCT->currBlockDataCnt; b++ )
    1014             :     {
    1015       58922 :         ch1 = hMCT->hBlockData[b]->ch1;
    1016       58922 :         ch2 = hMCT->hBlockData[b]->ch2;
    1017       58922 :         move16();
    1018       58922 :         move16();
    1019             : 
    1020       58922 :         p_ch[0] = ch1;
    1021       58922 :         p_ch[1] = ch2;
    1022       58922 :         move16();
    1023       58922 :         move16();
    1024             : 
    1025       58922 :         singleChEle[hMCT->hBlockData[b]->ch1] = 0;
    1026       58922 :         singleChEle[hMCT->hBlockData[b]->ch2] = 0;
    1027       58922 :         move16();
    1028       58922 :         move16();
    1029             : 
    1030             :         /* point to encoder states of actual channels to write block pair bits */
    1031       58922 :         p_st[0] = sts[ch1];
    1032       58922 :         p_st[1] = sts[ch2];
    1033             : 
    1034       58922 :         IF( ch1 > 0 )
    1035             :         {
    1036       34411 :             sts[ch1]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
    1037             :         }
    1038             : 
    1039       58922 :         IF( ch2 > 0 )
    1040             :         {
    1041       58922 :             sts[ch2]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
    1042             :         }
    1043             : 
    1044       58922 :         p_powerSpec_fx[0] = powerSpec_fx[ch1]; // q_powerSpec
    1045       58922 :         p_powerSpec_fx[1] = powerSpec_fx[ch2];
    1046             : 
    1047             :         /* Band-wise M/S for MDST */
    1048       58922 :         nSubframes = NB_DIV;
    1049       58922 :         move16();
    1050       58922 :         if ( EQ_16( p_st[0]->hTcxEnc->tcxMode, TCX_20 ) )
    1051             :         {
    1052       57497 :             nSubframes = 1;
    1053       57497 :             move16();
    1054             :         }
    1055             : 
    1056      119269 :         FOR( n = 0; n < nSubframes; n++ )
    1057             :         {
    1058       60347 :             p_orig_spectrum_fx[0][n] = orig_spectrum_fx[ch1][n]; // q_origSpec
    1059       60347 :             p_orig_spectrum_fx[1][n] = orig_spectrum_fx[ch2][n];
    1060       60347 :             p_powerSpecMsInv_fx[0][n] = powerSpecMsInv_fx[ch1][n]; // q_powerSpec
    1061       60347 :             p_powerSpecMsInv_fx[1][n] = powerSpecMsInv_fx[ch2][n];
    1062       60347 :             p_inv_spectrum_fx[0][n] = inv_spectrum_fx[ch1][n];
    1063       60347 :             p_inv_spectrum_fx[1][n] = inv_spectrum_fx[ch2][n];
    1064       60347 :             q_pS_ch[0] = q_powerSpec[ch1];
    1065       60347 :             q_pSI_ch[0] = q_powerSpecMsInv[ch1];
    1066       60347 :             q_pS_ch[1] = q_powerSpec[ch2];
    1067       60347 :             q_pSI_ch[1] = q_powerSpecMsInv[ch2];
    1068       60347 :             move16();
    1069       60347 :             move16();
    1070             : 
    1071       60347 :             test();
    1072       60347 :             IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] ) ||
    1073             :                 EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) )
    1074       31546 :             {
    1075             :                 Word16 exp_powerSpec_fx[CPE_CHANNELS], exp_powerSpecMsInv_fx[CPE_CHANNELS], exp_inv_spectrum_fx[CPE_CHANNELS];
    1076             : 
    1077       94638 :                 FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
    1078             :                 {
    1079       63092 :                     exp_powerSpec_fx[ch] = sub( Q31, q_pS_ch[ch] );
    1080       63092 :                     exp_powerSpecMsInv_fx[ch] = sub( Q31, q_pSI_ch[ch] );
    1081       63092 :                     exp_inv_spectrum_fx[ch] = p_st[ch]->hTcxEnc->spectrum_e[n];
    1082       63092 :                     move16();
    1083       63092 :                     move16();
    1084       63092 :                     move16();
    1085             :                 }
    1086             : 
    1087       31546 :                 ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, q_origSpec, q_origSpec, p_powerSpec_fx, exp_powerSpec_fx,
    1088       31546 :                                      p_powerSpecMsInv_fx, exp_powerSpecMsInv_fx, p_inv_spectrum_fx, exp_inv_spectrum_fx, n, sp_aud_decision0[ch1], p_st[0]->total_brate, 1 );
    1089             :             }
    1090             :             ELSE
    1091             :             {
    1092       86403 :                 FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
    1093             :                 {
    1094       57602 :                     st = p_st[ch];
    1095             : 
    1096       57602 :                     L_subframeTCX = shr( st->hTcxEnc->L_frameTCX, 1 );
    1097       57602 :                     if ( EQ_16( nSubframes, 1 ) )
    1098             :                     {
    1099       54200 :                         L_subframeTCX = st->hTcxEnc->L_frameTCX;
    1100       54200 :                         move16();
    1101             :                     }
    1102             : 
    1103       57602 :                     q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
    1104             : 
    1105       57602 :                     set16_fx( exp_powerSpec[p_ch[ch]], sub( Q31, q_powerSpec[p_ch[ch]] ), N_MAX + L_MDCT_OVLP_MAX );
    1106       57602 :                     ProcessIGF_ivas_fx( st, L_FRAME48k, st->hTcxEnc->spectrum_fx[n], &q_spectrum, orig_spectrum_fx[p_ch[ch]][n], q_origSpec, &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], &exp_powerSpec[p_ch[ch]][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 );
    1107             : 
    1108       57602 :                     st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
    1109       57602 :                     move16();
    1110             :                 }
    1111             :             }
    1112             :         }
    1113             :     }
    1114             : 
    1115             :     /* channel elements that are coded separately detected */
    1116       34621 :     IF( sum16_fx( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 )
    1117             :     {
    1118      197877 :         FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ )
    1119             :         {
    1120      163261 :             IF( singleChEle[ch] )
    1121             :             {
    1122       45439 :                 st = sts[ch];
    1123             : 
    1124       45439 :                 IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
    1125             :                 {
    1126        2828 :                     CONTINUE;
    1127             :                 }
    1128             : 
    1129       42611 :                 IF( ch > 0 )
    1130             :                 {
    1131       32501 :                     st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
    1132             :                 }
    1133             : 
    1134       42611 :                 nSubframes = NB_DIV;
    1135       42611 :                 move16();
    1136       42611 :                 if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
    1137             :                 {
    1138       41341 :                     nSubframes = 1;
    1139       41341 :                     move16();
    1140             :                 }
    1141             : 
    1142       86492 :                 FOR( n = 0; n < nSubframes; n++ )
    1143             :                 {
    1144       43881 :                     q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] );
    1145             : 
    1146       43881 :                     set16_fx( exp_powerSpec[ch], sub( Q31, q_powerSpec[ch] ), N_MAX + L_MDCT_OVLP_MAX );
    1147       43881 :                     ProcessIGF_ivas_fx( st, L_FRAME48k, st->hTcxEnc->spectrum_fx[n], &q_spectrum, orig_spectrum_fx[ch][n], q_origSpec, &powerSpec_fx[ch][n * L_subframeTCX], &exp_powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 );
    1148             : 
    1149       43881 :                     st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum );
    1150       43881 :                     move16();
    1151             :                 }
    1152             :             }
    1153             :         }
    1154             :     }
    1155             : 
    1156       34621 :     return;
    1157             : }

Generated by: LCOV version 1.14