Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung der angewandten
      5 Forschung e.V. All rights reserved.
      6 
      7  1.    INTRODUCTION
      8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
      9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
     10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
     11 a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
     14 general perceptual audio codecs. AAC-ELD is considered the best-performing
     15 full-bandwidth communications codec by independent studies and is widely
     16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
     17 specifications.
     18 
     19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
     20 those of Fraunhofer) may be obtained through Via Licensing
     21 (www.vialicensing.com) or through the respective patent owners individually for
     22 the purpose of encoding or decoding bit streams in products that are compliant
     23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
     24 Android devices already license these patent claims through Via Licensing or
     25 directly from the patent owners, and therefore FDK AAC Codec software may
     26 already be covered under those patent licenses when it is used for those
     27 licensed purposes only.
     28 
     29 Commercially-licensed AAC software libraries, including floating-point versions
     30 with enhanced sound quality, are also available from Fraunhofer. Users are
     31 encouraged to check the Fraunhofer website for additional applications
     32 information and documentation.
     33 
     34 2.    COPYRIGHT LICENSE
     35 
     36 Redistribution and use in source and binary forms, with or without modification,
     37 are permitted without payment of copyright license fees provided that you
     38 satisfy the following conditions:
     39 
     40 You must retain the complete text of this software license in redistributions of
     41 the FDK AAC Codec or your modifications thereto in source code form.
     42 
     43 You must retain the complete text of this software license in the documentation
     44 and/or other materials provided with redistributions of the FDK AAC Codec or
     45 your modifications thereto in binary form. You must make available free of
     46 charge copies of the complete source code of the FDK AAC Codec and your
     47 modifications thereto to recipients of copies in binary form.
     48 
     49 The name of Fraunhofer may not be used to endorse or promote products derived
     50 from this library without prior written permission.
     51 
     52 You may not charge copyright license fees for anyone to use, copy or distribute
     53 the FDK AAC Codec software or your modifications thereto.
     54 
     55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
     56 that you changed the software and the date of any change. For modified versions
     57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
     58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
     59 AAC Codec Library for Android."
     60 
     61 3.    NO PATENT LICENSE
     62 
     63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
     64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
     65 Fraunhofer provides no warranty of patent non-infringement with respect to this
     66 software.
     67 
     68 You may use this FDK AAC Codec software or modifications thereto only for
     69 purposes that are authorized by appropriate patent licenses.
     70 
     71 4.    DISCLAIMER
     72 
     73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
     74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     75 including but not limited to the implied warranties of merchantability and
     76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
     78 or consequential damages, including but not limited to procurement of substitute
     79 goods or services; loss of use, data, or profits, or business interruption,
     80 however caused and on any theory of liability, whether in contract, strict
     81 liability, or tort (including negligence), arising in any way out of the use of
     82 this software, even if advised of the possibility of such damage.
     83 
     84 5.    CONTACT INFORMATION
     85 
     86 Fraunhofer Institute for Integrated Circuits IIS
     87 Attention: Audio and Multimedia Departments - FDK AAC LL
     88 Am Wolfsmantel 33
     89 91058 Erlangen, Germany
     90 
     91 www.iis.fraunhofer.de/amm
     92 amm-info (at) iis.fraunhofer.de
     93 ----------------------------------------------------------------------------- */
     94 
     95 /*********************** MPEG surround decoder library *************************
     96 
     97    Author(s):
     98 
     99    Description: SAC Dec subband processing
    100 
    101 *******************************************************************************/
    102 
    103 #include "sac_stp.h"
    104 #include "sac_calcM1andM2.h"
    105 #include "sac_bitdec.h"
    106 #include "FDK_matrixCalloc.h"
    107 #include "sac_rom.h"
    108 
    109 #define BP_GF_START 6
    110 #define BP_GF_SIZE 25
    111 #define HP_SIZE 9
    112 #define STP_UPDATE_ENERGY_RATE 32
    113 
    114 #define SF_WET 5
    115 #define SF_DRY \
    116   3 /* SF_DRY == 2 would produce good conformance test results as well */
    117 #define SF_PRODUCT_BP_GF 13
    118 #define SF_PRODUCT_BP_GF_GF 26
    119 #define SF_SCALE 2
    120 
    121 #define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125)      /* LD64((1<<SF_SCALE))*/
    122 #define STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.950f) /* 0.95 */
    123 #define ONE_MINUS_STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.05f) /* 1.0 - 0.95 */
    124 #define STP_LPF_COEFF2__FDK FL2FXCONST_DBL(0.450f)          /* 0.45 */
    125 #define ONE_MINUS_STP_LPF_COEFF2__FDK \
    126   FL2FXCONST_DBL(1.0f - 0.450f) /* 1.0 - 0.45 */
    127 #define STP_SCALE_LIMIT__FDK \
    128   FL2FXCONST_DBL(2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE */
    129 #define ONE_DIV_STP_SCALE_LIMIT__FDK                                          \
    130   FL2FXCONST_DBL(1.0f / 2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE \
    131                                                          */
    132 #define ABS_THR__FDK       \
    133   FL2FXCONST_DBL(ABS_THR / \
    134                  ((float)(1 << (22 + 22 - 26)))) /* scaled by 18 bits */
    135 #define ABS_THR2__FDK                      \
    136   FL2FXCONST_DBL(ABS_THR * 32.0f * 32.0f / \
    137                  ((float)(1 << (22 + 22 - 26)))) /* scaled by 10 bits */
    138 #define STP_SCALE_LIMIT_HI \
    139   FL2FXCONST_DBL(3.02222222222 / (1 << SF_SCALE)) /* see 4. below */
    140 #define STP_SCALE_LIMIT_LO \
    141   FL2FXCONST_DBL(0.28289992119 / (1 << SF_SCALE)) /* see 4. below */
    142 #define STP_SCALE_LIMIT_HI_LD64                 \
    143   FL2FXCONST_DBL(0.04986280452) /* see 4. below \
    144                                  */
    145 #define STP_SCALE_LIMIT_LO_LD64                 \
    146   FL2FXCONST_DBL(0.05692613500) /* see 4. below \
    147                                  */
    148 
    149 /*  Scale factor calculation for the diffuse signal needs adapted thresholds
    150     for STP_SCALE_LIMIT and 1/STP_SCALE_LIMIT:
    151 
    152     1. scale = sqrt(DryNrg/WetNrg)
    153 
    154     2. Damping of scale factor
    155        scale2 = 0.1 + 0.9 * scale
    156 
    157     3. Limiting of scale factor
    158           STP_SCALE_LIMIT           >=        scale2        >= 1/STP_SCALE_LIMIT
    159        => STP_SCALE_LIMIT           >=  (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT
    160        => (STP_SCALE_LIMIT-0.1)/0.9 >=        scale         >=
    161    (1/STP_SCALE_LIMIT-0.1)/0.9
    162 
    163     3. Limiting of scale factor before sqrt calculation
    164        ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >=
    165    ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2        >= (scale^2) >=
    166    (STP_SCALE_LIMIT_LO)^2
    167 
    168     4. Thresholds for limiting of scale factor
    169        STP_SCALE_LIMIT_HI      = ((2.82-0.1)/0.9)
    170        STP_SCALE_LIMIT_LO      = (((1.0/2.82)-0.1)/0.9)
    171        STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI)
    172        STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
    173 */
    174 
    175 #define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx
    176 
    177 #define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx
    178 
    179 #define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \
    180   DryEner +=                                   \
    181       fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2)
    182 
    183 #define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \
    184   DryEner += fMultDiv2(                                 \
    185       fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n])
    186 
    187 #define CALC_WET_SCALE(dryIdx, wetIdx)                                         \
    188   if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \
    189     scale[wetIdx] = STP_SCALE_LIMIT_HI;                                        \
    190   } else if (DryEnerLD64[dryIdx] <                                             \
    191              (WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) {                \
    192     scale[wetIdx] = STP_SCALE_LIMIT_LO;                                        \
    193   } else {                                                                     \
    194     tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64;  \
    195     scale[wetIdx] = CalcInvLdData(tmp);                                        \
    196   }
    197 
    198 struct STP_DEC {
    199   FIXP_DBL runDryEner[MAX_INPUT_CHANNELS];
    200   FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS];
    201   FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS];
    202   FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS];
    203   FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS];
    204   const FIXP_CFG *BP;
    205   const FIXP_CFG *BP_GF;
    206   int update_old_ener;
    207 };
    208 
    209 inline void combineSignalReal(FIXP_DBL *hybOutputRealDry,
    210                               FIXP_DBL *hybOutputRealWet, int bands) {
    211   int n;
    212 
    213   for (n = bands - 1; n >= 0; n--) {
    214     *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
    215     hybOutputRealDry++, hybOutputRealWet++;
    216   }
    217 }
    218 
    219 inline void combineSignalRealScale1(FIXP_DBL *hybOutputRealDry,
    220                                     FIXP_DBL *hybOutputRealWet, FIXP_DBL scaleX,
    221                                     int bands) {
    222   int n;
    223 
    224   for (n = bands - 1; n >= 0; n--) {
    225     *hybOutputRealDry =
    226         *hybOutputRealDry +
    227         (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
    228     hybOutputRealDry++, hybOutputRealWet++;
    229   }
    230 }
    231 
    232 inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry,
    233                               FIXP_DBL *hybOutputImagDry,
    234                               FIXP_DBL *hybOutputRealWet,
    235                               FIXP_DBL *hybOutputImagWet, int bands) {
    236   int n;
    237 
    238   for (n = bands - 1; n >= 0; n--) {
    239     *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
    240     *hybOutputImagDry = *hybOutputImagDry + *hybOutputImagWet;
    241     hybOutputRealDry++, hybOutputRealWet++;
    242     hybOutputImagDry++, hybOutputImagWet++;
    243   }
    244 }
    245 
    246 inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
    247                                     FIXP_DBL *hybOutputImagDry,
    248                                     FIXP_DBL *hybOutputRealWet,
    249                                     FIXP_DBL *hybOutputImagWet,
    250                                     const FIXP_CFG *pBP, FIXP_DBL scaleX,
    251                                     int bands) {
    252   int n;
    253   FIXP_DBL scaleY;
    254   for (n = bands - 1; n >= 0; n--) {
    255     scaleY = fMultDiv2(scaleX, *pBP);
    256     *hybOutputRealDry =
    257         *hybOutputRealDry +
    258         (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 2));
    259     *hybOutputImagDry =
    260         *hybOutputImagDry +
    261         (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 2));
    262     hybOutputRealDry++, hybOutputRealWet++;
    263     hybOutputImagDry++, hybOutputImagWet++;
    264     pBP++;
    265   }
    266 }
    267 
    268 inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
    269                                     FIXP_DBL *hybOutputImagDry,
    270                                     FIXP_DBL *hybOutputRealWet,
    271                                     FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
    272                                     int bands) {
    273   int n;
    274 
    275   for (n = bands - 1; n >= 0; n--) {
    276     *hybOutputRealDry =
    277         *hybOutputRealDry +
    278         (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
    279     *hybOutputImagDry =
    280         *hybOutputImagDry +
    281         (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
    282     hybOutputRealDry++, hybOutputRealWet++;
    283     hybOutputImagDry++, hybOutputImagWet++;
    284   }
    285 }
    286 
    287 /*******************************************************************************
    288  Functionname: subbandTPCreate
    289  ******************************************************************************/
    290 SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
    291   HANDLE_STP_DEC self = NULL;
    292   FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
    293   if (hStpDec != NULL) {
    294     *hStpDec = self;
    295   }
    296 
    297   return MPS_OK;
    298 bail:
    299   return MPS_OUTOFMEMORY;
    300 }
    301 
    302 SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
    303   SACDEC_ERROR err = MPS_OK;
    304   int ch;
    305 
    306   for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
    307     self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
    308     self->oldWetEnerLD64[ch] =
    309         FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */
    310   }
    311   for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
    312     self->oldDryEnerLD64[ch] =
    313         FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */
    314   }
    315 
    316   self->BP = BP__FDK;
    317   self->BP_GF = BP_GF__FDK;
    318 
    319   self->update_old_ener = 0;
    320 
    321   return err;
    322 }
    323 
    324 /*******************************************************************************
    325  Functionname: subbandTPDestroy
    326  ******************************************************************************/
    327 void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
    328   if (hStpDec != NULL) {
    329     FDK_FREE_MEMORY_1D(*hStpDec);
    330   }
    331 }
    332 
    333 /*******************************************************************************
    334  Functionname: subbandTPApply
    335  ******************************************************************************/
    336 SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
    337   FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
    338   FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
    339   FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
    340   FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
    341 
    342   FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
    343   FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
    344 
    345   FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
    346   FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
    347 
    348   FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
    349   FIXP_DBL WetEnerX, damp, tmp;
    350   FIXP_DBL dmxReal0, dmxImag0;
    351   int skipChannels[MAX_OUTPUT_CHANNELS];
    352   int n, ch, cplxBands, cplxHybBands;
    353   int dry_scale_dmx, wet_scale_dmx;
    354   int i_LF, i_RF;
    355   HANDLE_STP_DEC hStpDec;
    356   const FIXP_CFG *pBP;
    357 
    358   int nrgScale = (2 * self->clipProtectGainSF__FDK);
    359 
    360   hStpDec = self->hStpDec;
    361 
    362   /* set scalefactor and loop counter */
    363   FDK_ASSERT(SF_DRY >= 1);
    364   {
    365     cplxBands = BP_GF_SIZE;
    366     cplxHybBands = self->hybridBands;
    367     dry_scale_dmx = (2 * SF_DRY) - 2;
    368     wet_scale_dmx = 2;
    369   }
    370 
    371   /* setup pointer for forming the direct downmix signal */
    372   for (ch = 0; ch < self->numOutputChannels; ch++) {
    373     qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
    374     qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
    375     qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
    376     qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
    377   }
    378 
    379   /* clear skipping flag for all output channels */
    380   FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
    381 
    382   /* set scale values to zero */
    383   FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
    384 
    385   /* update normalisation energy with latest smoothed energy */
    386   if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
    387     hStpDec->update_old_ener = 1;
    388     for (ch = 0; ch < self->numInputChannels; ch++) {
    389       hStpDec->oldDryEnerLD64[ch] =
    390           CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
    391     }
    392     for (ch = 0; ch < self->numOutputChannels; ch++) {
    393       hStpDec->oldWetEnerLD64[ch] =
    394           CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
    395     }
    396   } else {
    397     hStpDec->update_old_ener++;
    398   }
    399 
    400   /* get channel configuration */
    401   switch (self->treeConfig) {
    402     case TREE_212:
    403       i_LF = 0;
    404       i_RF = 1;
    405       break;
    406     default:
    407       return MPS_WRONG_TREECONFIG;
    408   }
    409 
    410   /* form the 'direct' downmix signal */
    411   pBP = hStpDec->BP_GF - BP_GF_START;
    412   switch (self->treeConfig) {
    413     case TREE_212:
    414       for (n = BP_GF_START; n < cplxBands; n++) {
    415         dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n];
    416         dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n];
    417         DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n);
    418       }
    419       DRY_ENER_WEIGHT(DryEner0);
    420       break;
    421     default:;
    422   }
    423   DryEner[0] = DryEner0;
    424 
    425   /* normalise the 'direct' signals */
    426   for (ch = 0; ch < self->numInputChannels; ch++) {
    427     DryEner[ch] = DryEner[ch] << (nrgScale);
    428     hStpDec->runDryEner[ch] =
    429         fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
    430         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
    431     if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
    432       DryEnerLD64[ch] =
    433           fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
    434                  FL2FXCONST_DBL(-0.484375f));
    435     } else {
    436       DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
    437     }
    438   }
    439   if (self->treeConfig == TREE_212) {
    440     for (; ch < MAX_INPUT_CHANNELS; ch++) {
    441       DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
    442     }
    443   }
    444 
    445   /* normalise the 'diffuse' signals */
    446   pBP = hStpDec->BP_GF - BP_GF_START;
    447   for (ch = 0; ch < self->numOutputChannels; ch++) {
    448     if (skipChannels[ch]) {
    449       continue;
    450     }
    451 
    452     WetEnerX = FL2FXCONST_DBL(0.0f);
    453     for (n = BP_GF_START; n < cplxBands; n++) {
    454       tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET);
    455       tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET);
    456       WetEnerX += fMultDiv2(tmp, pBP[n]);
    457     }
    458     WET_ENER_WEIGHT(WetEnerX);
    459 
    460     WetEnerX = WetEnerX << (nrgScale);
    461     hStpDec->runWetEner[ch] =
    462         fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
    463         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
    464 
    465     if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
    466       WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
    467     } else {
    468       WetEnerLD64[ch] =
    469           fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
    470                  FL2FXCONST_DBL(-0.484375f));
    471     }
    472   }
    473 
    474   /* compute scale factor for the 'diffuse' signals */
    475   switch (self->treeConfig) {
    476     case TREE_212:
    477       if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
    478         CALC_WET_SCALE(0, i_LF);
    479         CALC_WET_SCALE(0, i_RF);
    480       }
    481       break;
    482     default:;
    483   }
    484 
    485   damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
    486   for (ch = 0; ch < self->numOutputChannels; ch++) {
    487     /* damp the scaling factor */
    488     scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
    489 
    490     /* limiting the scale factor */
    491     if (scale[ch] > STP_SCALE_LIMIT__FDK) {
    492       scale[ch] = STP_SCALE_LIMIT__FDK;
    493     }
    494     if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
    495       scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
    496     }
    497 
    498     /* low pass filter the scaling factor */
    499     scale[ch] =
    500         fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
    501         fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
    502     hStpDec->prev_tp_scale[ch] = scale[ch];
    503   }
    504 
    505   /* combine 'direct' and scaled 'diffuse' signal */
    506   FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
    507   const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
    508 
    509   for (ch = 0; ch < self->numOutputChannels; ch++) {
    510     int no_scaling;
    511 
    512     no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
    513     if (no_scaling) {
    514       combineSignalCplx(
    515           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
    516           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
    517           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
    518           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
    519           cplxHybBands - self->tp_hybBandBorder);
    520 
    521     } else {
    522       FIXP_DBL scaleX;
    523       scaleX = scale[ch];
    524       pBP = hStpDec->BP - self->tp_hybBandBorder;
    525       /* Band[HP_SIZE-3+10-1] needs not to be processed in
    526          combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
    527       combineSignalCplxScale1(
    528           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
    529           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
    530           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
    531           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
    532           &pBP[self->tp_hybBandBorder], scaleX,
    533           (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
    534 
    535       {
    536         combineSignalCplxScale2(
    537             &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
    538             &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
    539             &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
    540             &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
    541             cplxHybBands - (HP_SIZE - 3 + 10 - 1));
    542       }
    543     }
    544   }
    545 
    546   return (SACDEC_ERROR)MPS_OK;
    547   ;
    548 }
    549