• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2019 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 SF_FREQ_DOMAIN_HEADROOM (2 * (1))
110 
111 #define BP_GF_START 6
112 #define BP_GF_SIZE 25
113 #define HP_SIZE 9
114 #define STP_UPDATE_ENERGY_RATE 32
115 
116 #define SF_WET 5
117 #define SF_DRY \
118   3 /* SF_DRY == 2 would produce good conformance test results as well */
119 #define SF_DRY_NRG                                                           \
120   (4 - 1) /* 8.495f = sum(BP_GF__FDK[i])                                     \
121              i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy        \
122              calculation needs 4 bits headroom, headroom can be reduced by 1 \
123              bit due to fPow2Div2() usage */
124 #define SF_WET_NRG                                                           \
125   (4 - 1) /* 8.495f = sum(BP_GF__FDK[i])                                     \
126              i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy        \
127              calculation needs 4 bits headroom, headroom can be reduced by 1 \
128              bit due to fPow2Div2() usage */
129 #define SF_PRODUCT_BP_GF 13
130 #define SF_PRODUCT_BP_GF_GF 26
131 #define SF_SCALE 2
132 
133 #define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125)      /* LD64((1<<SF_SCALE))*/
134 #define STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.950f) /* 0.95 */
135 #define ONE_MINUS_STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.05f) /* 1.0 - 0.95 */
136 #define STP_LPF_COEFF2__FDK FL2FXCONST_DBL(0.450f)          /* 0.45 */
137 #define ONE_MINUS_STP_LPF_COEFF2__FDK \
138   FL2FXCONST_DBL(1.0f - 0.450f) /* 1.0 - 0.45 */
139 #define STP_SCALE_LIMIT__FDK \
140   FL2FXCONST_DBL(2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE */
141 #define ONE_DIV_STP_SCALE_LIMIT__FDK                                          \
142   FL2FXCONST_DBL(1.0f / 2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE \
143                                                          */
144 #define ABS_THR__FDK       \
145   FL2FXCONST_DBL(ABS_THR / \
146                  ((float)(1 << (22 + 22 - 26)))) /* scaled by 18 bits */
147 #define ABS_THR2__FDK                      \
148   FL2FXCONST_DBL(ABS_THR * 32.0f * 32.0f / \
149                  ((float)(1 << (22 + 22 - 26)))) /* scaled by 10 bits */
150 #define STP_SCALE_LIMIT_HI \
151   FL2FXCONST_DBL(3.02222222222 / (1 << SF_SCALE)) /* see 4. below */
152 #define STP_SCALE_LIMIT_LO \
153   FL2FXCONST_DBL(0.28289992119 / (1 << SF_SCALE)) /* see 4. below */
154 #define STP_SCALE_LIMIT_HI_LD64                 \
155   FL2FXCONST_DBL(0.04986280452) /* see 4. below \
156                                  */
157 #define STP_SCALE_LIMIT_LO_LD64                 \
158   FL2FXCONST_DBL(0.05692613500) /* see 4. below \
159                                  */
160 
161 /*  Scale factor calculation for the diffuse signal needs adapted thresholds
162     for STP_SCALE_LIMIT and 1/STP_SCALE_LIMIT:
163 
164     1. scale = sqrt(DryNrg/WetNrg)
165 
166     2. Damping of scale factor
167        scale2 = 0.1 + 0.9 * scale
168 
169     3. Limiting of scale factor
170           STP_SCALE_LIMIT           >=        scale2        >= 1/STP_SCALE_LIMIT
171        => STP_SCALE_LIMIT           >=  (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT
172        => (STP_SCALE_LIMIT-0.1)/0.9 >=        scale         >=
173    (1/STP_SCALE_LIMIT-0.1)/0.9
174 
175     3. Limiting of scale factor before sqrt calculation
176        ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >=
177    ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2        >= (scale^2) >=
178    (STP_SCALE_LIMIT_LO)^2
179 
180     4. Thresholds for limiting of scale factor
181        STP_SCALE_LIMIT_HI      = ((2.82-0.1)/0.9)
182        STP_SCALE_LIMIT_LO      = (((1.0/2.82)-0.1)/0.9)
183        STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI)
184        STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
185 */
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 
combineSignalCplx(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,int bands)209 inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry,
210                               FIXP_DBL *hybOutputImagDry,
211                               FIXP_DBL *hybOutputRealWet,
212                               FIXP_DBL *hybOutputImagWet, int bands) {
213   int n;
214 
215   for (n = bands - 1; n >= 0; n--) {
216     *hybOutputRealDry = fAddSaturate(*hybOutputRealDry, *hybOutputRealWet);
217     *hybOutputImagDry = fAddSaturate(*hybOutputImagDry, *hybOutputImagWet);
218     hybOutputRealDry++, hybOutputRealWet++;
219     hybOutputImagDry++, hybOutputImagWet++;
220   }
221 }
222 
combineSignalCplxScale1(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,const FIXP_CFG * pBP,FIXP_DBL scaleX,int bands)223 inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
224                                     FIXP_DBL *hybOutputImagDry,
225                                     FIXP_DBL *hybOutputRealWet,
226                                     FIXP_DBL *hybOutputImagWet,
227                                     const FIXP_CFG *pBP, FIXP_DBL scaleX,
228                                     int bands) {
229   int n;
230   FIXP_DBL scaleY;
231   for (n = bands - 1; n >= 0; n--) {
232     scaleY = fMultDiv2(scaleX, *pBP);
233     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
234         (*hybOutputRealDry >> 1) +
235             (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 1)),
236         1, DFRACT_BITS);
237     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
238         (*hybOutputImagDry >> 1) +
239             (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 1)),
240         1, DFRACT_BITS);
241     hybOutputRealDry++, hybOutputRealWet++;
242     hybOutputImagDry++, hybOutputImagWet++;
243     pBP++;
244   }
245 }
246 
combineSignalCplxScale2(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,FIXP_DBL scaleX,int bands)247 inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
248                                     FIXP_DBL *hybOutputImagDry,
249                                     FIXP_DBL *hybOutputRealWet,
250                                     FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
251                                     int bands) {
252   int n;
253 
254   for (n = bands - 1; n >= 0; n--) {
255     *hybOutputRealDry =
256         *hybOutputRealDry +
257         (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
258     *hybOutputImagDry =
259         *hybOutputImagDry +
260         (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
261     hybOutputRealDry++, hybOutputRealWet++;
262     hybOutputImagDry++, hybOutputImagWet++;
263   }
264 }
265 
266 /*******************************************************************************
267  Functionname: subbandTPCreate
268  ******************************************************************************/
subbandTPCreate(HANDLE_STP_DEC * hStpDec)269 SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
270   HANDLE_STP_DEC self = NULL;
271   FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
272   if (hStpDec != NULL) {
273     *hStpDec = self;
274   }
275 
276   return MPS_OK;
277 bail:
278   return MPS_OUTOFMEMORY;
279 }
280 
subbandTPInit(HANDLE_STP_DEC self)281 SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
282   SACDEC_ERROR err = MPS_OK;
283   int ch;
284 
285   for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
286     self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
287     self->oldWetEnerLD64[ch] = FL2FXCONST_DBL(0.0);
288   }
289   for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
290     self->oldDryEnerLD64[ch] = FL2FXCONST_DBL(0.0);
291   }
292 
293   self->BP = BP__FDK;
294   self->BP_GF = BP_GF__FDK;
295 
296   self->update_old_ener = 0;
297 
298   return err;
299 }
300 
301 /*******************************************************************************
302  Functionname: subbandTPDestroy
303  ******************************************************************************/
subbandTPDestroy(HANDLE_STP_DEC * hStpDec)304 void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
305   if (hStpDec != NULL) {
306     FDK_FREE_MEMORY_1D(*hStpDec);
307   }
308 }
309 
310 /*******************************************************************************
311  Functionname: subbandTPApply
312  ******************************************************************************/
subbandTPApply(spatialDec * self,const SPATIAL_BS_FRAME * frame)313 SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
314   FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
315   FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
316   FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
317   FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
318 
319   FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
320   FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
321 
322   FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
323   FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
324 
325   FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
326   FIXP_DBL WetEnerX, damp, tmp;
327   FIXP_DBL dmxReal0, dmxImag0;
328   int skipChannels[MAX_OUTPUT_CHANNELS];
329   int n, ch, cplxBands, cplxHybBands;
330   int dry_scale_dmx, wet_scale_dmx;
331   int i_LF, i_RF;
332   HANDLE_STP_DEC hStpDec;
333   const FIXP_CFG *pBP;
334 
335   int nrgScale = (2 * self->clipProtectGainSF__FDK);
336 
337   hStpDec = self->hStpDec;
338 
339   /* set scalefactor and loop counter */
340   FDK_ASSERT(SF_DRY >= 1);
341   {
342     cplxBands = BP_GF_SIZE;
343     cplxHybBands = self->hybridBands;
344     if (self->treeConfig == TREE_212) {
345       dry_scale_dmx = 2; /* 2 bits to compensate fMultDiv2() and fPow2Div2()
346                             used in energy calculation */
347     } else {
348       dry_scale_dmx = (2 * SF_DRY) - 2;
349     }
350     wet_scale_dmx = 2;
351   }
352 
353   /* setup pointer for forming the direct downmix signal */
354   for (ch = 0; ch < self->numOutputChannels; ch++) {
355     qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
356     qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
357     qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
358     qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
359   }
360 
361   /* clear skipping flag for all output channels */
362   FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
363 
364   /* set scale values to zero */
365   FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
366 
367   /* update normalisation energy with latest smoothed energy */
368   if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
369     hStpDec->update_old_ener = 1;
370     for (ch = 0; ch < self->numInputChannels; ch++) {
371       hStpDec->oldDryEnerLD64[ch] =
372           CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
373     }
374     for (ch = 0; ch < self->numOutputChannels; ch++) {
375       if (self->treeConfig == TREE_212)
376         hStpDec->oldWetEnerLD64[ch] =
377             CalcLdData(hStpDec->runWetEner[ch] + ABS_THR__FDK);
378       else
379         hStpDec->oldWetEnerLD64[ch] =
380             CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
381     }
382   } else {
383     hStpDec->update_old_ener++;
384   }
385 
386   /* get channel configuration */
387   switch (self->treeConfig) {
388     case TREE_212:
389       i_LF = 0;
390       i_RF = 1;
391       break;
392     default:
393       return MPS_WRONG_TREECONFIG;
394   }
395 
396   /* form the 'direct' downmix signal */
397   pBP = hStpDec->BP_GF - BP_GF_START;
398   switch (self->treeConfig) {
399     case TREE_212:
400       INT sMin, sNorm, sReal, sImag;
401 
402       sReal = fMin(getScalefactor(&qmfOutputRealDry[i_LF][BP_GF_START],
403                                   cplxBands - BP_GF_START),
404                    getScalefactor(&qmfOutputRealDry[i_RF][BP_GF_START],
405                                   cplxBands - BP_GF_START));
406       sImag = fMin(getScalefactor(&qmfOutputImagDry[i_LF][BP_GF_START],
407                                   cplxBands - BP_GF_START),
408                    getScalefactor(&qmfOutputImagDry[i_RF][BP_GF_START],
409                                   cplxBands - BP_GF_START));
410       sMin = fMin(sReal, sImag) - 1;
411 
412       for (n = BP_GF_START; n < cplxBands; n++) {
413         dmxReal0 = scaleValue(qmfOutputRealDry[i_LF][n], sMin) +
414                    scaleValue(qmfOutputRealDry[i_RF][n], sMin);
415         dmxImag0 = scaleValue(qmfOutputImagDry[i_LF][n], sMin) +
416                    scaleValue(qmfOutputImagDry[i_RF][n], sMin);
417 
418         DryEner0 += (fMultDiv2(fPow2Div2(dmxReal0), pBP[n]) +
419                      fMultDiv2(fPow2Div2(dmxImag0), pBP[n])) >>
420                     SF_DRY_NRG;
421       }
422 
423       sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_DRY_NRG + dry_scale_dmx -
424               (2 * sMin) + nrgScale;
425       DryEner0 = scaleValueSaturate(
426           DryEner0, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
427       break;
428     default:;
429   }
430   DryEner[0] = DryEner0;
431 
432   /* normalise the 'direct' signals */
433   for (ch = 0; ch < self->numInputChannels; ch++) {
434     if (self->treeConfig != TREE_212) DryEner[ch] = DryEner[ch] << nrgScale;
435     hStpDec->runDryEner[ch] =
436         fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
437         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
438     if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
439       DryEnerLD64[ch] =
440           fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
441                  FL2FXCONST_DBL(-0.484375f));
442     } else {
443       DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
444     }
445   }
446   for (; ch < MAX_INPUT_CHANNELS; ch++) {
447     DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
448   }
449 
450   /* normalise the 'diffuse' signals */
451   pBP = hStpDec->BP_GF - BP_GF_START;
452   for (ch = 0; ch < self->numOutputChannels; ch++) {
453     if (skipChannels[ch]) {
454       continue;
455     }
456 
457     WetEnerX = FL2FXCONST_DBL(0.0f);
458 
459     if (self->treeConfig == TREE_212) {
460       INT sMin, sNorm;
461 
462       sMin = fMin(getScalefactor(&qmfOutputRealWet[ch][BP_GF_START],
463                                  cplxBands - BP_GF_START),
464                   getScalefactor(&qmfOutputImagWet[ch][BP_GF_START],
465                                  cplxBands - BP_GF_START));
466 
467       for (n = BP_GF_START; n < cplxBands; n++) {
468         WetEnerX +=
469             (fMultDiv2(fPow2Div2(scaleValue(qmfOutputRealWet[ch][n], sMin)),
470                        pBP[n]) +
471              fMultDiv2(fPow2Div2(scaleValue(qmfOutputImagWet[ch][n], sMin)),
472                        pBP[n])) >>
473             SF_WET_NRG;
474       }
475       sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_WET_NRG + wet_scale_dmx -
476               (2 * sMin) + nrgScale;
477       WetEnerX = scaleValueSaturate(
478           WetEnerX, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
479     } else
480       FDK_ASSERT(self->treeConfig == TREE_212);
481 
482     hStpDec->runWetEner[ch] =
483         fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
484         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
485 
486     if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
487       WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
488     } else {
489       WetEnerLD64[ch] =
490           fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
491                  FL2FXCONST_DBL(-0.484375f));
492     }
493   }
494 
495   /* compute scale factor for the 'diffuse' signals */
496   switch (self->treeConfig) {
497     case TREE_212:
498       if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
499         CALC_WET_SCALE(0, i_LF);
500         CALC_WET_SCALE(0, i_RF);
501       }
502       break;
503     default:;
504   }
505 
506   damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
507   for (ch = 0; ch < self->numOutputChannels; ch++) {
508     /* damp the scaling factor */
509     scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
510 
511     /* limiting the scale factor */
512     if (scale[ch] > STP_SCALE_LIMIT__FDK) {
513       scale[ch] = STP_SCALE_LIMIT__FDK;
514     }
515     if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
516       scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
517     }
518 
519     /* low pass filter the scaling factor */
520     scale[ch] =
521         fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
522         fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
523     hStpDec->prev_tp_scale[ch] = scale[ch];
524   }
525 
526   /* combine 'direct' and scaled 'diffuse' signal */
527   FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
528   const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
529 
530   for (ch = 0; ch < self->numOutputChannels; ch++) {
531     int no_scaling;
532 
533     no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
534     if (no_scaling) {
535       combineSignalCplx(
536           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
537           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
538           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
539           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
540           cplxHybBands - self->tp_hybBandBorder);
541 
542     } else {
543       FIXP_DBL scaleX;
544       scaleX = scale[ch];
545       pBP = hStpDec->BP - self->tp_hybBandBorder;
546       /* Band[HP_SIZE-3+10-1] needs not to be processed in
547          combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
548       combineSignalCplxScale1(
549           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
550           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
551           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
552           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
553           &pBP[self->tp_hybBandBorder], scaleX,
554           (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
555 
556       {
557         combineSignalCplxScale2(
558             &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
559             &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
560             &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
561             &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
562             cplxHybBands - (HP_SIZE - 3 + 10 - 1));
563       }
564     }
565   }
566 
567   return (SACDEC_ERROR)MPS_OK;
568   ;
569 }
570