LCOV - code coverage report
Current view: top level - lib_isar - isar_RMSEnvGrouping.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 388 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 11 0.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             : /* Double check cost function calculation */
      34             : 
      35             : #include <stdlib.h>
      36             : #include "options.h"
      37             : #include <math.h>
      38             : #include "prot_fx.h"
      39             : #include "isar_lcld_prot.h"
      40             : #include "isar_rom_lcld_tables.h"
      41             : #include "wmc_auto.h"
      42             : #include "prot_fx.h"
      43             : #include "basop_util.h"
      44             : #include "enh64.h"
      45             : 
      46             : 
      47             : /*-------------------------------------------------------------------*
      48             :  * Local ROM tables
      49             :  *
      50             :  *
      51             :  *-------------------------------------------------------------------*/
      52             : 
      53             : Word32 Inv_grp_length[17] = {
      54             :     // Q31
      55             :     0,
      56             :     2147483647,
      57             :     1073741823,
      58             :     715827882,
      59             :     536870911,
      60             :     429496729,
      61             :     357913941,
      62             :     306783378,
      63             :     268435455,
      64             :     238609294,
      65             :     214748364,
      66             :     195225786,
      67             :     178956970,
      68             :     165191049,
      69             :     153391689,
      70             :     143165576,
      71             :     134217727,
      72             : 
      73             : };
      74             : 
      75             : static const Word32 c_afThreshQuiet48_fx[23] = {
      76             :     // Q23
      77             :     -705191424,
      78             :     -705191424,
      79             :     -705191424,
      80             :     -705191424,
      81             :     -705191424,
      82             :     -705191424,
      83             :     -705191424,
      84             :     -705191424,
      85             :     -703021824,
      86             :     -694920256,
      87             :     -685375488,
      88             :     -662531840,
      89             :     -646432768,
      90             :     -636262784,
      91             :     -627448000,
      92             :     -618652544,
      93             :     -598245120,
      94             :     -575579520,
      95             :     -550540736,
      96             :     -508787360,
      97             :     -264583456,
      98             :     -161516096,
      99             :     -158042848,
     100             : };
     101             : static const Word32 c_fiDefaultTheta48_fx[MAX_BANDS_48] = {
     102             :     // Q31
     103             :     939524096,
     104             :     939524096,
     105             :     805306368,
     106             :     671088640,
     107             :     671088640,
     108             :     536870912,
     109             :     536870912,
     110             :     536870912,
     111             :     536870912,
     112             :     536870912,
     113             :     536870912,
     114             :     536870912,
     115             :     536870912,
     116             :     536870912,
     117             :     536870912,
     118             :     536870912,
     119             :     536870912,
     120             :     536870912,
     121             :     536870912,
     122             :     536870912,
     123             :     536870912,
     124             :     536870912,
     125             :     536870912,
     126             : };
     127             : typedef struct GMNODE
     128             : {
     129             :     Word32 iGroupStart;
     130             :     Word32 iGroupLength;
     131             :     Word32 *pfMergedEnergydB_fx;
     132             :     Word32 *piQRMSEnvelope;
     133             : 
     134             :     Word32 iGroupRMSEnvelopeCost;
     135             :     Word32 fGroupSNRPenalty_fx;
     136             :     Word16 fGroupSNRPenalty_exp;
     137             :     struct GMNODE *psNext;
     138             : } GMNode;
     139             : 
     140             : struct RMS_ENVELOPE_GROUPING
     141             : {
     142             :     Word32 iNumBlocks;
     143             :     Word32 iMaxGroups;
     144             :     Word32 **ppfWeight_man;
     145             :     Word16 **ppfWeight_exp;
     146             :     Word32 **ppfBandEnergy_man;
     147             :     Word16 **ppfBandEnergy_exp;
     148             :     Word32 **ppfBandEnergydB_fx;
     149             :     // Word32 **ppfWeight_fx;
     150             :     GMNode *psGMNodes;
     151             : };
     152             : 
     153             : 
     154             : /*-------------------------------------------------------------------*
     155             :  * Function CreateRMSEnvelopeGrouping()
     156             :  *
     157             :  *
     158             :  *-------------------------------------------------------------------*/
     159             : 
     160           0 : RMSEnvelopeGrouping *CreateRMSEnvelopeGrouping(
     161             :     const Word32 iNumBlocks )
     162             : {
     163             :     Word32 n;
     164             : 
     165             :     RMSEnvelopeGrouping *psRMSEnvelopeGrouping;
     166             : 
     167           0 :     psRMSEnvelopeGrouping = (RMSEnvelopeGrouping *) malloc( sizeof( RMSEnvelopeGrouping ) );
     168           0 :     psRMSEnvelopeGrouping->iNumBlocks = iNumBlocks;
     169             : 
     170           0 :     psRMSEnvelopeGrouping->iMaxGroups = iNumBlocks >> 1;
     171           0 :     psRMSEnvelopeGrouping->ppfBandEnergy_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
     172           0 :     psRMSEnvelopeGrouping->ppfBandEnergy_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) );
     173           0 :     psRMSEnvelopeGrouping->ppfBandEnergydB_fx = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
     174           0 :     psRMSEnvelopeGrouping->ppfWeight_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
     175           0 :     psRMSEnvelopeGrouping->ppfWeight_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) );
     176             : 
     177           0 :     FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
     178             :     {
     179           0 :         psRMSEnvelopeGrouping->ppfBandEnergy_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) ); /* 2 for stereo joint group calc */
     180           0 :         psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) ); /* 2 for stereo joint group calc */
     181           0 :         psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
     182           0 :         psRMSEnvelopeGrouping->ppfWeight_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
     183           0 :         psRMSEnvelopeGrouping->ppfWeight_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) );
     184             :     }
     185             : 
     186           0 :     psRMSEnvelopeGrouping->psGMNodes = (GMNode *) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( GMNode ) );
     187             : 
     188           0 :     for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
     189             :     {
     190           0 :         psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
     191           0 :         psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
     192           0 :         psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
     193           0 :         psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
     194           0 :         psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1;
     195             :     }
     196             : 
     197           0 :     return psRMSEnvelopeGrouping;
     198             : }
     199             : 
     200             : 
     201             : /*-------------------------------------------------------------------*
     202             :  * Function DeleteRMSEnvelopeGrouping()
     203             :  *
     204             :  *
     205             :  *-------------------------------------------------------------------*/
     206             : 
     207           0 : void DeleteRMSEnvelopeGrouping(
     208             :     RMSEnvelopeGrouping *psRMSEnvelopeGrouping )
     209             : {
     210             :     Word32 n;
     211             : 
     212           0 :     FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
     213             :     {
     214           0 :         free( psRMSEnvelopeGrouping->ppfBandEnergy_man[n] );
     215           0 :         free( psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] );
     216           0 :         free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] );
     217           0 :         free( psRMSEnvelopeGrouping->ppfWeight_man[n] );
     218           0 :         free( psRMSEnvelopeGrouping->ppfWeight_exp[n] );
     219             :     }
     220           0 :     free( psRMSEnvelopeGrouping->ppfBandEnergy_man );
     221           0 :     free( psRMSEnvelopeGrouping->ppfBandEnergy_exp );
     222           0 :     free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx );
     223           0 :     free( psRMSEnvelopeGrouping->ppfWeight_man );
     224           0 :     free( psRMSEnvelopeGrouping->ppfWeight_exp );
     225             : 
     226           0 :     FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
     227             :     {
     228           0 :         free( psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx );
     229           0 :         free( psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope );
     230             :     }
     231           0 :     free( psRMSEnvelopeGrouping->psGMNodes );
     232             : 
     233           0 :     free( psRMSEnvelopeGrouping );
     234             : 
     235           0 :     return;
     236             : }
     237             : 
     238             : 
     239             : /*-------------------------------------------------------------------*
     240             :  * Function ComputeBandEnergy()
     241             :  *
     242             :  *
     243             :  *-------------------------------------------------------------------*/
     244             : 
     245           0 : static void ComputeBandEnergy(
     246             :     const Word32 iChannels,
     247             :     const Word32 iNumBlocks,
     248             :     const Word32 iNumBands,
     249             :     const Word32 *piBandwidths,
     250             :     Word32 ***pppfReal_fx,
     251             :     Word32 ***pppfImag_fx,
     252             :     Word32 **ppfBandEnergy_man,
     253             :     Word16 **ppfBandEnergy_exp,
     254             :     Word32 **ppfBandEnergydB_fx,
     255             :     Word32 **ppfWeight_man,
     256             :     Word16 **ppfWeight_exp,
     257             :     Word16 q_final )
     258             : {
     259             :     Word32 n;
     260           0 :     Word32 constant = 1616142483; // Q29  of(1/log2(10))*10
     261             :     Word32 const_comp3, const_comp1;
     262           0 :     Word16 exp3 = 0, exp1 = 0, Flag1, Flag2, Flag3;
     263             :     Word16 div_exp;
     264             :     /*For 0.33f*/
     265           0 :     const_comp3 = 1417339264;
     266           0 :     move32();
     267           0 :     exp3 = -1;
     268           0 :     move16();
     269             :     // f2me( 0.33, &const_comp3, &exp3 );//
     270             :     // f2me( 1.0, &const_comp1, &exp1 );//
     271             :     /*For 1.0f*/
     272             :     Word32 mul_32;
     273             :     Word16 mul_exp;
     274           0 :     const_comp1 = 1073741824;
     275           0 :     move32();
     276           0 :     exp1 = 1;
     277           0 :     move16();
     278           0 :     FOR( n = 0; n < iChannels; n++ )
     279             :     {
     280             :         Word32 k;
     281             :         Word32 iChanOffset;
     282             : 
     283           0 :         iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) );
     284           0 :         FOR( k = 0; k < iNumBlocks; k++ )
     285             :         {
     286             :             Word32 b;
     287             :             Word32 iFBOffset;
     288           0 :             Word32 fMaxWeight_fx = 0;
     289           0 :             move32();
     290           0 :             Word16 fMaxWeight_exp = 0;
     291           0 :             move16();
     292           0 :             iFBOffset = 0;
     293           0 :             move32();
     294           0 :             FOR( b = 0; b < iNumBands; b++ )
     295             :             {
     296             :                 Word32 m;
     297             :                 Word16 fEnergy_exp;
     298             :                 Word32 fEnergy_fx, fWeight_temp;
     299             :                 Word16 shift_value;
     300             :                 Word32 fEnergy_log_fx, fEnergy_log_fx1;
     301           0 :                 fEnergy_exp = 0;
     302           0 :                 move16();
     303             :                 /*For 1e-12f  in Q63*/
     304             :                 Word32 fWeight_fx;
     305             :                 Word64 Wmult_value;
     306           0 :                 Word16 exp_pow = 0;
     307           0 :                 move16();
     308           0 :                 Word16 guard_bits = find_guarded_bits_fx( piBandwidths[b] + 1 );
     309             :                 // fEnergy_f64 = W_shr( fEnergy_f64, ( 63 - ( 2 * ( q_final - guard_bits ) + 1 ) ) );
     310           0 :                 fEnergy_fx = 1180591616;
     311           0 :                 fEnergy_exp = -39;
     312           0 :                 FOR( m = 0; m < piBandwidths[b]; m++ )
     313             :                 {
     314           0 :                     Wmult_value = W_add( W_mult_32_32( L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ) ), W_mult_32_32( L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ) ) );
     315           0 :                     shift_value = W_norm( Wmult_value );
     316           0 :                     mul_32 = W_extract_h( W_shl( Wmult_value, shift_value ) );
     317           0 :                     mul_exp = 31 - ( 2 * ( q_final - guard_bits ) + 1 + shift_value - 32 );
     318           0 :                     fEnergy_fx = BASOP_Util_Add_Mant32Exp( fEnergy_fx, fEnergy_exp, mul_32, mul_exp, &fEnergy_exp ); // Some large number to prevent clipping
     319           0 :                     iFBOffset++;
     320             :                 }
     321           0 :                 IF( EQ_32( fEnergy_fx, 0 ) )
     322             :                 {
     323             :                     // f2me( 1e-12f, &fEnergy_fx, &fEnergy_exp ); //
     324           0 :                     fEnergy_fx = 1180591616;
     325           0 :                     fEnergy_exp = -39;
     326           0 :                     fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
     327           0 :                     ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
     328           0 :                     move32();
     329           0 :                     ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
     330           0 :                     move16();
     331           0 :                     fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
     332           0 :                     ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
     333           0 :                     move32();
     334           0 :                     ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
     335           0 :                     move16();
     336           0 :                     fEnergy_log_fx1 = -1006632960; // Q23
     337           0 :                     fWeight_fx = 403727488;        // Q31
     338           0 :                     exp_pow = 0;
     339             :                 }
     340             :                 ELSE
     341             :                 {
     342           0 :                     fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
     343           0 :                     ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
     344           0 :                     move32();
     345           0 :                     ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
     346           0 :                     move16();
     347           0 :                     fEnergy_fx = BASOP_Util_Log2( fEnergy_fx );
     348           0 :                     move32();
     349           0 :                     fEnergy_log_fx = L_add( fEnergy_fx, L_shl( L_deposit_l( fEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ // log2f( fEnergy )
     350           0 :                     fEnergy_log_fx1 = Mpy_32_32( fEnergy_log_fx, constant );
     351           0 :                     fEnergy_log_fx = L_sub( fEnergy_log_fx1, c_afThreshQuiet48_fx[b] ); // Q23 of ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) )
     352           0 :                     fWeight_fx = Mpy_32_32( 48509336, fEnergy_log_fx );                 //  0.0068f*3.3219  in Q31, result in Q23
     353           0 :                     fWeight_temp = BASOP_util_Pow2( fWeight_fx, 8, &exp_pow );
     354           0 :                     fWeight_fx = Mpy_32_32( 708669604, fWeight_temp ); // 708669604 = Q31 0f 0.33
     355             :                 }
     356           0 :                 Flag1 = BASOP_Util_Cmp_Mant32Exp( fWeight_fx, exp_pow, const_comp3, exp3 );
     357           0 :                 IF( NE_16( Flag1, 1 ) )
     358             :                 {
     359           0 :                     fWeight_fx = const_comp3;
     360           0 :                     move32();
     361           0 :                     exp_pow = exp3;
     362           0 :                     move16();
     363             :                 }
     364           0 :                 Flag2 = BASOP_Util_Cmp_Mant32Exp( const_comp1, exp1, fWeight_fx, exp_pow );
     365           0 :                 IF( NE_16( Flag2, 1 ) )
     366             :                 {
     367           0 :                     fWeight_fx = const_comp1;
     368           0 :                     move32();
     369           0 :                     exp_pow = exp1;
     370           0 :                     move16();
     371             :                 }
     372           0 :                 Flag3 = BASOP_Util_Cmp_Mant32Exp( fMaxWeight_fx, fMaxWeight_exp, fWeight_fx, exp_pow );
     373           0 :                 IF( NE_16( Flag3, 1 ) )
     374             :                 {
     375           0 :                     fMaxWeight_fx = fWeight_fx;
     376           0 :                     move32();
     377           0 :                     fMaxWeight_exp = exp_pow;
     378           0 :                     move16();
     379             :                 }
     380             : #ifdef APPLY_TEMPORAL_SMOOTHING
     381             :                 if ( k > 0 )
     382             :                 {
     383             :                     float fSmoothEnergy;
     384             :                     fSmoothEnergy = 0.7f * ppfBandEnergy[k - 1][iChanOffset + b] + 0.3f * fEnergy;
     385             : 
     386             :                     fEnergy = ( fEnergy > fSmoothEnergy ) ? fEnergy : fSmoothEnergy;
     387             :                 }
     388             : #endif
     389           0 :                 ppfWeight_man[k][iChanOffset + b] = fWeight_fx;
     390           0 :                 ppfWeight_exp[k][iChanOffset + b] = exp_pow;
     391           0 :                 ppfBandEnergydB_fx[k][iChanOffset + b] = fEnergy_log_fx1; // Q23
     392             :             }
     393           0 :             FOR( b = 0; b < iNumBands; b++ )
     394             :             {
     395           0 :                 ppfWeight_man[k][iChanOffset + b] = L_deposit_h( BASOP_Util_Divide3232_Scale( ppfWeight_man[k][iChanOffset + b], fMaxWeight_fx, &div_exp ) );
     396           0 :                 ppfWeight_exp[k][iChanOffset + b] = div_exp + ppfWeight_exp[k][iChanOffset + b] - fMaxWeight_exp;
     397             :             }
     398             :         }
     399             :     }
     400             : 
     401           0 :     return;
     402             : }
     403             : 
     404             : 
     405             : /*-------------------------------------------------------------------*
     406             :  * Function ComputeMergeRMS()
     407             :  *
     408             :  *
     409             :  *-------------------------------------------------------------------*/
     410             : 
     411           0 : static void ComputeMergeRMS(
     412             :     const Word32 iNumBands,
     413             :     const Word32 iStartBlock,
     414             :     const Word32 iGroupLength,
     415             :     Word32 *pfMergedEnergydB,
     416             :     Word32 *piQRMSEnvelope,
     417             :     Word32 **ppfBandEnergy_man,
     418             :     Word16 **ppfBandEnergy_exp )
     419             : {
     420             :     Word32 b;
     421           0 :     Word32 constant = 1616142483; // Q29  of(1/log2(10))*10    // Note epsolon was added when computing BandEnergy;
     422           0 :     move32();
     423             :     Word32 fGroupEnergy32_fx;
     424             : 
     425           0 :     FOR( b = 0; b < iNumBands; b++ )
     426             :     {
     427             :         Word32 n;
     428           0 :         Word32 fGroupEnergy_fx = 0;
     429           0 :         move32();
     430           0 :         Word16 fGroupEnergy_exp = 0;
     431           0 :         move16();
     432             :         Word32 fRMSEnvelope_fx;
     433             :         Word32 iQRMSEnvelope_fx;
     434           0 :         FOR( n = iStartBlock; n < ( iStartBlock + iGroupLength ); n++ )
     435             :         {
     436           0 :             fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[n][b], ppfBandEnergy_exp[n][b], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp );
     437             :         }
     438           0 :         fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[iGroupLength] ); // Division by iGroupLength
     439           0 :         move32();
     440           0 :         IF( NE_32( fGroupEnergy_fx, 0 ) )
     441             :         {
     442           0 :             fRMSEnvelope_fx = BASOP_Util_Log2( fGroupEnergy_fx );
     443           0 :             move32();
     444           0 :             fRMSEnvelope_fx = L_add( fRMSEnvelope_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/
     445             :         }
     446             :         ELSE
     447             :         {
     448           0 :             fRMSEnvelope_fx = 0;
     449           0 :             fGroupEnergy_exp = 0;
     450             :         }
     451           0 :         iQRMSEnvelope_fx = ( fRMSEnvelope_fx > 0 ) ? L_add( fRMSEnvelope_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fRMSEnvelope_fx ), ONE_IN_Q24 ) );
     452           0 :         iQRMSEnvelope_fx = L_shr( iQRMSEnvelope_fx, 25 );
     453             : 
     454           0 :         fGroupEnergy32_fx = fRMSEnvelope_fx; /*Q25*/                  // BASOP_Util_Log2( fGroupEnergy_fx );
     455           0 :         fGroupEnergy32_fx = Mpy_32_32( fGroupEnergy32_fx, constant ); // Q23
     456           0 :         pfMergedEnergydB[b] = fGroupEnergy32_fx;                      // Q23
     457           0 :         piQRMSEnvelope[b] = iQRMSEnvelope_fx;                         // Q25
     458             :     }
     459             : 
     460           0 :     return;
     461             : }
     462             : 
     463             : 
     464             : /*-------------------------------------------------------------------*
     465             :  * Function ComputeRMSEnvelopeBits()
     466             :  *
     467             :  *
     468             :  *-------------------------------------------------------------------*/
     469             : 
     470           0 : static Word32 ComputeRMSEnvelopeBits(
     471             :     const Word32 iChannels,
     472             :     const Word32 iNumBands,
     473             :     const Word32 *piQRMSEnevelope )
     474             : {
     475             :     Word32 n;
     476           0 :     Word32 iRMSEnvelopeBits = 0;
     477           0 :     move32();
     478           0 :     Word32 iChanOffset = 0;
     479           0 :     move32();
     480             : 
     481           0 :     FOR( n = 0; n < iChannels; n++ )
     482             :     {
     483             :         Word32 b;
     484             :         Word32 iLastRMSVal;
     485             : 
     486           0 :         iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, ENV0_BITS );
     487           0 :         iLastRMSVal = piQRMSEnevelope[iChanOffset];
     488           0 :         move32();
     489           0 :         FOR( b = 1; b < iNumBands; b++ )
     490             :         {
     491             :             Word32 iDelta;
     492             : 
     493           0 :             iDelta = L_sub( piQRMSEnevelope[iChanOffset + b], iLastRMSVal );
     494           0 :             iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN;
     495           0 :             iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX;
     496           0 :             iDelta = L_sub( iDelta, ENV_DELTA_MIN );
     497           0 :             iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, c_aaiRMSEnvHuffEnc[iDelta][0] );
     498             : 
     499           0 :             iLastRMSVal = piQRMSEnevelope[iChanOffset + b];
     500           0 :             move32();
     501             :         }
     502             : 
     503           0 :         iChanOffset = L_add( iChanOffset, iNumBands );
     504             :     }
     505             : 
     506           0 :     return iRMSEnvelopeBits;
     507             : }
     508             : 
     509             : 
     510             : /*-------------------------------------------------------------------*
     511             :  * Function ComputeSNRPenalty()
     512             :  *
     513             :  *
     514             :  *-------------------------------------------------------------------*/
     515             : 
     516           0 : static Word32 ComputeSNRPenalty(
     517             :     const Word32 iChannels,
     518             :     const Word32 iNumBands,
     519             :     const Word32 *piBandwidths,
     520             :     const Word32 iStartBlock,
     521             :     const Word32 iGroupLength,
     522             :     Word32 **ppfBandEnergy_dB_fx,
     523             :     const Word32 *piRMSEnvelope,
     524             :     Word16 *fSNRPenalty_exp )
     525             : {
     526             :     Word32 n;
     527             :     Word32 iChanOffset;
     528             :     Word32 temp;
     529           0 :     Word32 fSNRPenalty_fx = 0;
     530           0 :     move32();
     531           0 :     Word32 fSNRPenaltyconst_fx = 0;
     532           0 :     move32();
     533             :     Word32 mul_temp;
     534           0 :     Word16 fSNRPenaltycnst_exp = 0, exp = 0;
     535             : 
     536           0 :     fSNRPenaltyconst_fx = 1250000000;
     537           0 :     fSNRPenaltycnst_exp = 34;
     538           0 :     iChanOffset = 0;
     539           0 :     move32();
     540           0 :     FOR( n = 0; n < iChannels; n++ )
     541             :     {
     542             :         Word32 b;
     543           0 :         FOR( b = 0; b < iNumBands; b++ )
     544             :         {
     545             :             Word32 k;
     546             :             Word32 fRMSVal_fx;
     547             :             Word32 RMS_value_fx;
     548             :             // RMS_value =  piRMSEnvelope[iChanOffset + b];
     549           0 :             RMS_value_fx = L_shl( piRMSEnvelope[iChanOffset + b], 25 );
     550           0 :             move32();
     551             :             //  fRMSVal = 3.0103f * (float) RMS_value;
     552           0 :             fRMSVal_fx = Mpy_32_32( 1616142506, RMS_value_fx ); // Q23
     553           0 :             move32();
     554           0 :             FOR( k = iStartBlock; k < ( iStartBlock + iGroupLength ); k++ )
     555             :             {
     556             :                 Word32 fDeltadB_fx;
     557           0 :                 fDeltadB_fx = L_sub( fRMSVal_fx, ppfBandEnergy_dB_fx[k][iChanOffset + b] );
     558           0 :                 IF( LT_32( fDeltadB_fx, -75756680 ) )
     559             :                 {
     560           0 :                     fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, fSNRPenaltyconst_fx, fSNRPenaltycnst_exp, fSNRPenalty_exp ); // Some large number to prevent clipping
     561             :                 }
     562             :                 ELSE
     563             :                 {
     564           0 :                     mul_temp = L_abs( L_sub( Mpy_32_32( c_fiDefaultTheta48_fx[b], fDeltadB_fx ), fDeltadB_fx ) );
     565           0 :                     temp = Mpy_32_32( mul_temp, Mpy_32_32( 715827883, L_shl( piBandwidths[b], 27 ) ) ); // Q27+23 -31=19
     566           0 :                     exp = Q12;                                                                          // Q31 - Q19
     567           0 :                     fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, temp, exp, fSNRPenalty_exp );
     568             :                 }
     569             :             }
     570             :         }
     571             : 
     572           0 :         iChanOffset = L_add( iChanOffset, iNumBands );
     573             :     }
     574             : 
     575           0 :     return fSNRPenalty_fx;
     576             : }
     577             : 
     578             : 
     579             : /*-------------------------------------------------------------------*
     580             :  * Function TryMerge2()
     581             :  *
     582             :  *
     583             :  *-------------------------------------------------------------------*/
     584             : 
     585           0 : static Word32 TryMerge2(
     586             :     const Word32 iChannels,
     587             :     const Word32 iNumBands,
     588             :     const Word32 *piBandwidths,
     589             :     Word32 **ppfBandEnergy_man,
     590             :     Word16 **ppfBandEnergy_exp,
     591             :     Word32 **ppfBandEnergydB_fx,
     592             :     GMNode *psGMNode1,
     593             :     GMNode *psGMNode2,
     594             :     Word16 *fMergedCost_exp )
     595             : {
     596             :     Word32 iRMSEnvBits1;
     597             :     Word32 iRMSEnvBits2;
     598             :     Word32 iRMSEnvBitsMerged;
     599           0 :     Word32 temp = 0;
     600           0 :     move32();
     601           0 :     Word16 temp_exp = 0;
     602           0 :     move16();
     603           0 :     Word32 fMergedCost_fx = 0;
     604           0 :     move32();
     605             :     Word32 RMSEnvBits_fx;
     606             :     Word32 fSNRPenalty1_fx;
     607             :     Word32 fSNRPenalty2_fx;
     608             :     Word32 fSNRPenaltyMerged_fx;
     609           0 :     Word16 fSNRPenalty1_exp = 0;
     610           0 :     move16();
     611           0 :     Word16 fSNRPenalty2_exp = 0;
     612           0 :     move16();
     613           0 :     Word16 fSNRPenaltyMerged_exp = 0;
     614           0 :     move16();
     615           0 :     Word32 one_in_mant = L_negate( ONE_IN_Q30 );
     616           0 :     Word16 one_in_exp = 1;
     617           0 :     move16();
     618           0 :     *fMergedCost_exp = 0;
     619           0 :     move16();
     620           0 :     Word16 flag = 0;
     621           0 :     move16();
     622             : 
     623           0 :     IF( EQ_32( psGMNode1->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode1->fGroupSNRPenalty_exp, one_in_exp ) )
     624             :     {
     625           0 :         flag = 1;
     626           0 :         move16();
     627             :     }
     628             : 
     629             :     /* First compute current RMS Envelope for each group */
     630           0 :     IF( EQ_32( psGMNode1->iGroupRMSEnvelopeCost, -1 ) || flag )
     631             :     {
     632           0 :         ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
     633           0 :         iRMSEnvBits1 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
     634           0 :         fSNRPenalty1_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenalty1_exp );
     635           0 :         psGMNode1->iGroupRMSEnvelopeCost = iRMSEnvBits1;
     636           0 :         move32();
     637           0 :         psGMNode1->fGroupSNRPenalty_fx = fSNRPenalty1_fx;
     638           0 :         move32();
     639           0 :         psGMNode1->fGroupSNRPenalty_exp = fSNRPenalty1_exp;
     640           0 :         move16();
     641             :     }
     642             :     ELSE
     643             :     {
     644           0 :         iRMSEnvBits1 = psGMNode1->iGroupRMSEnvelopeCost;
     645           0 :         move32();
     646           0 :         fSNRPenalty1_fx = psGMNode1->fGroupSNRPenalty_fx;
     647           0 :         move32();
     648           0 :         fSNRPenalty1_exp = psGMNode1->fGroupSNRPenalty_exp;
     649           0 :         move16();
     650             :     }
     651           0 :     IF( EQ_32( psGMNode2->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode2->fGroupSNRPenalty_exp, one_in_exp ) )
     652             :     {
     653           0 :         flag = 1;
     654           0 :         move16();
     655             :     }
     656             : 
     657           0 :     IF( EQ_32( psGMNode2->iGroupRMSEnvelopeCost, -1 ) || flag )
     658             :     {
     659             : 
     660           0 :         ComputeMergeRMS( iNumBands * iChannels, psGMNode2->iGroupStart, psGMNode2->iGroupLength, psGMNode2->pfMergedEnergydB_fx, psGMNode2->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
     661           0 :         iRMSEnvBits2 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode2->piQRMSEnvelope );
     662           0 :         fSNRPenalty2_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode2->iGroupStart, psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode2->piQRMSEnvelope, &fSNRPenalty2_exp );
     663           0 :         psGMNode2->iGroupRMSEnvelopeCost = iRMSEnvBits2;
     664           0 :         move32();
     665           0 :         psGMNode2->fGroupSNRPenalty_fx = fSNRPenalty2_fx;
     666           0 :         move32();
     667           0 :         psGMNode2->fGroupSNRPenalty_exp = fSNRPenalty2_exp;
     668           0 :         move16();
     669             :     }
     670             :     ELSE
     671             :     {
     672           0 :         iRMSEnvBits2 = psGMNode2->iGroupRMSEnvelopeCost;
     673           0 :         move32();
     674           0 :         fSNRPenalty2_fx = psGMNode2->fGroupSNRPenalty_fx;
     675           0 :         move32();
     676           0 :         fSNRPenalty2_exp = psGMNode2->fGroupSNRPenalty_exp;
     677           0 :         move16();
     678             :     }
     679             : 
     680           0 :     ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
     681             : 
     682             :     /* Compute the RMS Envelope cost for merged group */
     683           0 :     iRMSEnvBitsMerged = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
     684             :     // fSNRPenalty_exp = 0;
     685             :     /* Compute an approximation of the bit cost based on SNR increase/decrease due to merging */
     686           0 :     fSNRPenaltyMerged_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenaltyMerged_exp );
     687           0 :     RMSEnvBits_fx = L_sub( L_sub( iRMSEnvBitsMerged, iRMSEnvBits1 ), iRMSEnvBits2 );
     688           0 :     RMSEnvBits_fx = L_shl( RMSEnvBits_fx, 10 ); // Converting to Q10
     689           0 :     temp = BASOP_Util_Add_Mant32Exp( fSNRPenaltyMerged_fx, fSNRPenaltyMerged_exp, L_negate( fSNRPenalty1_fx ), fSNRPenalty1_exp, &temp_exp );
     690           0 :     fMergedCost_fx = BASOP_Util_Add_Mant32Exp( temp, temp_exp, L_negate( fSNRPenalty2_fx ), fSNRPenalty2_exp, fMergedCost_exp );
     691           0 :     fMergedCost_fx = BASOP_Util_Add_Mant32Exp( fMergedCost_fx, *fMergedCost_exp, RMSEnvBits_fx, 21, fMergedCost_exp );
     692             :     // fMergedCost = fSNRPenaltyMerged - fSNRPenalty1 - fSNRPenalty2 + (float) iRMSEnvBitsMerged - (float) iRMSEnvBits1 - (float) iRMSEnvBits2;
     693             : 
     694           0 :     return fMergedCost_fx;
     695             : }
     696             : 
     697             : 
     698             : /*-------------------------------------------------------------------*
     699             :  * Function ComputeGreedyGroups3()
     700             :  *
     701             :  *
     702             :  *-------------------------------------------------------------------*/
     703             : 
     704           0 : static void ComputeGreedyGroups3(
     705             :     RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
     706             :     const Word32 iChannels,
     707             :     const Word32 iNumBands,
     708             :     const Word32 *piBandwidths,
     709             :     const Word32 iMaxGroups )
     710             : {
     711             : 
     712           0 :     Word32 iDone = 0;
     713           0 :     Word32 iNumGroups = psRMSEnvelopeGrouping->iMaxGroups;
     714           0 :     WHILE( EQ_32( iDone, 0 ) )
     715             :     {
     716             :         GMNode *psGMNode;
     717             :         GMNode *psBestGMNode;
     718             :         /* Instead of 1e20f*/
     719           0 :         Word32 fBestMergeCost_fx = 1455191552; // mantissa of 1e20f
     720           0 :         move32();
     721           0 :         Word16 fBestMergeCost_exp = 67; // exp of 1e20f
     722           0 :         move16();
     723           0 :         Word16 Flag = 0;
     724           0 :         move16();
     725           0 :         psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
     726           0 :         psBestGMNode = NULL;
     727           0 :         WHILE( psGMNode->psNext != NULL )
     728             :         {
     729           0 :             Word32 fMergeCost_fx = 0;
     730           0 :             move32();
     731           0 :             Word16 fMergeCost_exp = 0;
     732           0 :             move16();
     733           0 :             fMergeCost_fx = TryMerge2( iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psGMNode, psGMNode->psNext, &fMergeCost_exp );
     734           0 :             IF( LT_32( fMergeCost_fx, 0 ) && ( GT_32( fBestMergeCost_fx, 0 ) ) )
     735             :             {
     736             : 
     737           0 :                 Flag = 1;
     738           0 :                 move16();
     739             :             }
     740           0 :             ELSE IF( ( GT_32( fMergeCost_fx, 0 ) && ( LT_32( fBestMergeCost_fx, 0 ) ) ) )
     741             :             {
     742           0 :                 Flag = -1;
     743           0 :                 move16();
     744             :             }
     745             :             ELSE
     746             :             {
     747           0 :                 Flag = BASOP_Util_Cmp_Mant32Exp( fBestMergeCost_fx, fBestMergeCost_exp, fMergeCost_fx, fMergeCost_exp );
     748             :             }
     749           0 :             IF( EQ_32( Flag, 1 ) )
     750             :             {
     751           0 :                 fBestMergeCost_fx = fMergeCost_fx;
     752           0 :                 move32();
     753           0 :                 fBestMergeCost_exp = fMergeCost_exp;
     754           0 :                 move16();
     755           0 :                 psBestGMNode = psGMNode;
     756             :             }
     757             : 
     758           0 :             psGMNode = psGMNode->psNext;
     759             :         }
     760             : 
     761           0 :         IF( ( GT_32( fBestMergeCost_fx, 0 ) && ( LE_32( iNumGroups, iMaxGroups ) ) ) )
     762             :         {
     763           0 :             iDone++;
     764             :         }
     765           0 :         ELSE IF( ( psBestGMNode != NULL ) && ( psBestGMNode->psNext != NULL ) )
     766             :         {
     767           0 :             psBestGMNode->iGroupLength = L_add( psBestGMNode->psNext->iGroupLength, psBestGMNode->iGroupLength );
     768           0 :             psBestGMNode->fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
     769           0 :             psBestGMNode->fGroupSNRPenalty_exp = 1;
     770           0 :             move16();
     771           0 :             psBestGMNode->psNext = psBestGMNode->psNext->psNext;
     772           0 :             iNumGroups--;
     773             :         }
     774             :         ELSE
     775             :         {
     776           0 :             iDone++; // This only catches a problem
     777             :         }
     778             :     }
     779             : 
     780           0 :     return;
     781             : }
     782             : 
     783             : 
     784             : /*-------------------------------------------------------------------*
     785             :  * Function ComputeRMSEnvelope()
     786             :  *
     787             :  *
     788             :  *-------------------------------------------------------------------*/
     789             : 
     790           0 : static void ComputeRMSEnvelope(
     791             :     const Word32 iChannels,
     792             :     const Word32 iNumBands,
     793             :     const Word32 iNumGroups,
     794             :     const Word32 *piGroupLengths,
     795             :     Word32 **ppfBandEnergy_man,
     796             :     Word16 **ppfBandEnergy_exp,
     797             :     Word32 ***pppiRMSEnvelope )
     798             : {
     799             :     Word32 n;
     800             :     Word32 fGroupEnergy_fx;
     801             :     Word16 fGroupEnergy_exp;
     802             :     Word32 temp;
     803             : 
     804           0 :     FOR( n = 0; n < iChannels; n++ )
     805             :     {
     806             :         Word32 b;
     807             :         Word32 iChanOffset;
     808             : 
     809           0 :         iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) );
     810             : 
     811           0 :         FOR( b = 0; b < iNumBands; b++ )
     812             :         {
     813             :             Word32 k;
     814             :             Word32 iBlockOffset;
     815           0 :             iBlockOffset = 0;
     816           0 :             FOR( k = 0; k < iNumGroups; k++ )
     817             :             {
     818             :                 Word32 m;
     819           0 :                 fGroupEnergy_exp = 0;
     820           0 :                 move16();
     821           0 :                 fGroupEnergy_fx = 0;
     822           0 :                 move32();
     823           0 :                 FOR( m = 0; m < piGroupLengths[k]; m++ )
     824             :                 {
     825           0 :                     fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[iBlockOffset][b + iChanOffset], ppfBandEnergy_exp[iBlockOffset][b + iChanOffset], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp );
     826           0 :                     iBlockOffset++;
     827             :                 }
     828           0 :                 fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[piGroupLengths[k]] ); // Division by iGroupLength
     829           0 :                 fGroupEnergy_fx = BASOP_Util_Log2( fGroupEnergy_fx );
     830           0 :                 move32();
     831           0 :                 fGroupEnergy_fx = L_add( fGroupEnergy_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) );                /*Q25*/
     832           0 :                 temp = ( fGroupEnergy_fx > 0 ) ? L_add( fGroupEnergy_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fGroupEnergy_fx ), ONE_IN_Q24 ) ); // Q25
     833           0 :                 temp = L_shr( temp, 25 );
     834           0 :                 temp = ( temp > ENV_MIN ) ? temp : ENV_MIN;
     835           0 :                 temp = ( temp < ENV_MAX ) ? temp : ENV_MAX;
     836           0 :                 pppiRMSEnvelope[n][k][b] = temp;
     837             :             }
     838             :         }
     839             :     }
     840             : 
     841           0 :     return;
     842             : }
     843             : 
     844             : 
     845             : /*-------------------------------------------------------------------*
     846             :  * Function LimitRMSEnvelope()
     847             :  *
     848             :  *
     849             :  *-------------------------------------------------------------------*/
     850             : 
     851           0 : static void LimitRMSEnvelope(
     852             :     const Word32 iBandCount,
     853             :     const Word32 iRMSDeltaMax,
     854             :     const Word32 iRMSDeltaMin,
     855             :     Word32 *piRMSEnvelope )
     856             : {
     857             :     Word32 iBand;
     858             :     Word32 iLastSCF;
     859             : 
     860             :     /* Increase low envelope values to ensure that the scale factors traces the large values correctly (checking for max deltas) */
     861           0 :     iLastSCF = piRMSEnvelope[iBandCount - 1];
     862           0 :     move32();
     863           0 :     for ( iBand = iBandCount - 2; iBand > -1; iBand-- )
     864             :     {
     865             :         Word32 iDelta;
     866             : 
     867           0 :         iDelta = L_sub( iLastSCF, piRMSEnvelope[iBand] );
     868             : 
     869           0 :         IF( GT_32( iDelta, iRMSDeltaMax ) )
     870             :         {
     871             : #ifdef DEBUG_VERBOSE
     872             :             printf( "WARNING RMS envelope delta limited\n" );
     873             : #endif
     874           0 :             piRMSEnvelope[iBand] = L_add( L_sub( iDelta, iRMSDeltaMax ), piRMSEnvelope[iBand] );
     875             :         }
     876             : 
     877           0 :         iLastSCF = piRMSEnvelope[iBand];
     878           0 :         move32();
     879             :     }
     880             : 
     881             :     /* Increase low envelope values to ensure that the envelope traces the large values correctly (checking for min deltas)*/
     882           0 :     iLastSCF = piRMSEnvelope[0];
     883           0 :     FOR( iBand = 1; iBand < iBandCount; iBand++ )
     884             :     {
     885             :         Word32 iDelta;
     886             : 
     887           0 :         iDelta = L_sub( piRMSEnvelope[iBand], iLastSCF );
     888             : 
     889           0 :         IF( LT_32( iDelta, iRMSDeltaMin ) )
     890             :         {
     891             : #ifdef DEBUG_VERBOSE
     892             :             printf( "WARNING RMS envelope delta limited\n" );
     893             : #endif
     894           0 :             piRMSEnvelope[iBand] = L_add( piRMSEnvelope[iBand], L_sub( iRMSDeltaMin, iDelta ) );
     895             :         }
     896             : 
     897           0 :         iLastSCF = piRMSEnvelope[iBand];
     898           0 :         move32();
     899             :     }
     900             : 
     901           0 :     return;
     902             : }
     903             : 
     904             : 
     905             : /*-------------------------------------------------------------------*
     906             :  * Function ComputeEnvelopeGrouping()
     907             :  *
     908             :  *
     909             :  *-------------------------------------------------------------------*/
     910             : 
     911           0 : void ComputeEnvelopeGrouping(
     912             :     RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
     913             :     const Word32 iChannels,
     914             :     const Word32 iNumBands,
     915             :     const Word32 *piBandwidths,
     916             :     Word32 ***pppfReal_fx,
     917             :     Word32 ***pppfImag_fx,
     918             :     Word32 *piNumGroups,
     919             :     Word32 *piGroupLengths,
     920             :     Word32 ***pppiRMSEnvelope,
     921             :     Word16 q_final )
     922             : {
     923             :     Word32 n;
     924             :     GMNode *psGMNode;
     925             : 
     926             :     /* Compute Band Energies */
     927           0 :     ComputeBandEnergy( iChannels, psRMSEnvelopeGrouping->iNumBlocks, iNumBands, piBandwidths, pppfReal_fx, pppfImag_fx, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psRMSEnvelopeGrouping->ppfWeight_man, psRMSEnvelopeGrouping->ppfWeight_exp, q_final );
     928             :     /* Init GMNodes */
     929           0 :     psRMSEnvelopeGrouping->psGMNodes[0].iGroupStart = 0;
     930           0 :     move32();
     931           0 :     psRMSEnvelopeGrouping->psGMNodes[0].iGroupLength = 2;
     932           0 :     move32();
     933           0 :     psRMSEnvelopeGrouping->psGMNodes[0].psNext = NULL;
     934           0 :     psRMSEnvelopeGrouping->psGMNodes[0].iGroupRMSEnvelopeCost = -1;
     935           0 :     move32();
     936           0 :     psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
     937           0 :     psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_exp = 1;
     938           0 :     move16();
     939           0 :     FOR( n = 1; n < psRMSEnvelopeGrouping->iMaxGroups; n++ )
     940             :     {
     941           0 :         psRMSEnvelopeGrouping->psGMNodes[n - 1].psNext = &psRMSEnvelopeGrouping->psGMNodes[n];
     942           0 :         psRMSEnvelopeGrouping->psGMNodes[n].iGroupStart = L_shl( n, 1 );
     943           0 :         move32();
     944           0 :         psRMSEnvelopeGrouping->psGMNodes[n].iGroupLength = 2;
     945           0 :         move32();
     946           0 :         psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
     947           0 :         move32();
     948           0 :         psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
     949           0 :         psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1;
     950           0 :         move16();
     951           0 :         psRMSEnvelopeGrouping->psGMNodes[n].psNext = NULL;
     952             :     }
     953             :     /* Perform grouping via Greedy Merge */
     954             :     /* Allows control over max groups can call using 16 if want same as previous call */
     955           0 :     ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->iNumBlocks );
     956             :     /* Calc Groups from Merge Results */
     957           0 :     *piNumGroups = 0;
     958           0 :     move32();
     959           0 :     psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
     960           0 :     WHILE( psGMNode != NULL )
     961             :     {
     962           0 :         piGroupLengths[*piNumGroups] = psGMNode->iGroupLength;
     963           0 :         move32();
     964           0 :         *piNumGroups = L_add( *piNumGroups, 1 );
     965           0 :         psGMNode = psGMNode->psNext;
     966             :     }
     967             :     /* Compute RMS Envelope given group lengths */
     968           0 :     ComputeRMSEnvelope( iChannels, iNumBands, *piNumGroups, piGroupLengths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, pppiRMSEnvelope );
     969             : 
     970             :     /* Envelope Tenting */
     971           0 :     FOR( n = 0; n < iChannels; n++ )
     972             :     {
     973             :         Word32 k;
     974           0 :         FOR( k = 0; k < *piNumGroups; k++ )
     975             :         {
     976           0 :             LimitRMSEnvelope( iNumBands, ENV_DELTA_MAX, ENV_DELTA_MIN, pppiRMSEnvelope[n][k] );
     977             :         }
     978             :     }
     979             : 
     980           0 :     return;
     981             : }

Generated by: LCOV version 1.14