• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung 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@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 
combineSignalReal(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputRealWet,int bands)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 
combineSignalRealScale1(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL scaleX,int bands)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 
combineSignalCplx(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,int bands)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 
combineSignalCplxScale1(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,const FIXP_CFG * pBP,FIXP_DBL scaleX,int bands)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 
combineSignalCplxScale2(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,FIXP_DBL scaleX,int bands)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  ******************************************************************************/
subbandTPCreate(HANDLE_STP_DEC * hStpDec)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 
subbandTPInit(HANDLE_STP_DEC self)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  ******************************************************************************/
subbandTPDestroy(HANDLE_STP_DEC * hStpDec)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  ******************************************************************************/
subbandTPApply(spatialDec * self,const SPATIAL_BS_FRAME * frame)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