• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2021 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 = fMult(scaleX, *pBP);
233     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
234         (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleY),
235         SF_SCALE, DFRACT_BITS);
236     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
237         (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleY),
238         SF_SCALE, DFRACT_BITS);
239     hybOutputRealDry++, hybOutputRealWet++;
240     hybOutputImagDry++, hybOutputImagWet++;
241     pBP++;
242   }
243 }
244 
combineSignalCplxScale2(FIXP_DBL * hybOutputRealDry,FIXP_DBL * hybOutputImagDry,FIXP_DBL * hybOutputRealWet,FIXP_DBL * hybOutputImagWet,FIXP_DBL scaleX,int bands)245 inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
246                                     FIXP_DBL *hybOutputImagDry,
247                                     FIXP_DBL *hybOutputRealWet,
248                                     FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
249                                     int bands) {
250   int n;
251 
252   for (n = bands - 1; n >= 0; n--) {
253     *hybOutputRealDry = SATURATE_LEFT_SHIFT(
254         (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleX),
255         SF_SCALE, DFRACT_BITS);
256     *hybOutputImagDry = SATURATE_LEFT_SHIFT(
257         (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleX),
258         SF_SCALE, DFRACT_BITS);
259     hybOutputRealDry++, hybOutputRealWet++;
260     hybOutputImagDry++, hybOutputImagWet++;
261   }
262 }
263 
264 /*******************************************************************************
265  Functionname: subbandTPCreate
266  ******************************************************************************/
subbandTPCreate(HANDLE_STP_DEC * hStpDec)267 SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
268   HANDLE_STP_DEC self = NULL;
269   FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
270   if (hStpDec != NULL) {
271     *hStpDec = self;
272   }
273 
274   return MPS_OK;
275 bail:
276   return MPS_OUTOFMEMORY;
277 }
278 
subbandTPInit(HANDLE_STP_DEC self)279 SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
280   SACDEC_ERROR err = MPS_OK;
281   int ch;
282 
283   for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
284     self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
285     self->oldWetEnerLD64[ch] = FL2FXCONST_DBL(0.0);
286   }
287   for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
288     self->oldDryEnerLD64[ch] = FL2FXCONST_DBL(0.0);
289   }
290 
291   self->BP = BP__FDK;
292   self->BP_GF = BP_GF__FDK;
293 
294   self->update_old_ener = 0;
295 
296   return err;
297 }
298 
299 /*******************************************************************************
300  Functionname: subbandTPDestroy
301  ******************************************************************************/
subbandTPDestroy(HANDLE_STP_DEC * hStpDec)302 void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
303   if (hStpDec != NULL) {
304     FDK_FREE_MEMORY_1D(*hStpDec);
305   }
306 }
307 
308 /*******************************************************************************
309  Functionname: subbandTPApply
310  ******************************************************************************/
subbandTPApply(spatialDec * self,const SPATIAL_BS_FRAME * frame)311 SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
312   FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
313   FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
314   FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
315   FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
316 
317   FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
318   FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
319 
320   FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
321   FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
322 
323   FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
324   FIXP_DBL WetEnerX, damp, tmp;
325   FIXP_DBL dmxReal0, dmxImag0;
326   int skipChannels[MAX_OUTPUT_CHANNELS];
327   int n, ch, cplxBands, cplxHybBands;
328   int dry_scale_dmx, wet_scale_dmx;
329   int i_LF, i_RF;
330   HANDLE_STP_DEC hStpDec;
331   const FIXP_CFG *pBP;
332 
333   int nrgScale = (2 * self->clipProtectGainSF__FDK);
334 
335   hStpDec = self->hStpDec;
336 
337   /* set scalefactor and loop counter */
338   FDK_ASSERT(SF_DRY >= 1);
339   {
340     cplxBands = BP_GF_SIZE;
341     cplxHybBands = self->hybridBands;
342     if (self->treeConfig == TREE_212) {
343       dry_scale_dmx = 2; /* 2 bits to compensate fMultDiv2() and fPow2Div2()
344                             used in energy calculation */
345     } else {
346       dry_scale_dmx = (2 * SF_DRY) - 2;
347     }
348     wet_scale_dmx = 2;
349   }
350 
351   /* setup pointer for forming the direct downmix signal */
352   for (ch = 0; ch < self->numOutputChannels; ch++) {
353     qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
354     qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
355     qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
356     qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
357   }
358 
359   /* clear skipping flag for all output channels */
360   FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
361 
362   /* set scale values to zero */
363   FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
364 
365   /* update normalisation energy with latest smoothed energy */
366   if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
367     hStpDec->update_old_ener = 1;
368     for (ch = 0; ch < self->numInputChannels; ch++) {
369       hStpDec->oldDryEnerLD64[ch] =
370           CalcLdData(fAddSaturate(hStpDec->runDryEner[ch], ABS_THR__FDK));
371     }
372     for (ch = 0; ch < self->numOutputChannels; ch++) {
373       if (self->treeConfig == TREE_212)
374         hStpDec->oldWetEnerLD64[ch] =
375             CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR__FDK));
376       else
377         hStpDec->oldWetEnerLD64[ch] =
378             CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR2__FDK));
379     }
380   } else {
381     hStpDec->update_old_ener++;
382   }
383 
384   /* get channel configuration */
385   switch (self->treeConfig) {
386     case TREE_212:
387       i_LF = 0;
388       i_RF = 1;
389       break;
390     default:
391       return MPS_WRONG_TREECONFIG;
392   }
393 
394   /* form the 'direct' downmix signal */
395   pBP = hStpDec->BP_GF - BP_GF_START;
396   switch (self->treeConfig) {
397     case TREE_212:
398       INT sMin, sNorm, sReal, sImag;
399 
400       sReal = fMin(getScalefactor(&qmfOutputRealDry[i_LF][BP_GF_START],
401                                   cplxBands - BP_GF_START),
402                    getScalefactor(&qmfOutputRealDry[i_RF][BP_GF_START],
403                                   cplxBands - BP_GF_START));
404       sImag = fMin(getScalefactor(&qmfOutputImagDry[i_LF][BP_GF_START],
405                                   cplxBands - BP_GF_START),
406                    getScalefactor(&qmfOutputImagDry[i_RF][BP_GF_START],
407                                   cplxBands - BP_GF_START));
408       sMin = fMin(sReal, sImag) - 1;
409 
410       for (n = BP_GF_START; n < cplxBands; n++) {
411         dmxReal0 = scaleValue(qmfOutputRealDry[i_LF][n], sMin) +
412                    scaleValue(qmfOutputRealDry[i_RF][n], sMin);
413         dmxImag0 = scaleValue(qmfOutputImagDry[i_LF][n], sMin) +
414                    scaleValue(qmfOutputImagDry[i_RF][n], sMin);
415 
416         DryEner0 += (fMultDiv2(fPow2Div2(dmxReal0), pBP[n]) +
417                      fMultDiv2(fPow2Div2(dmxImag0), pBP[n])) >>
418                     SF_DRY_NRG;
419       }
420 
421       sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_DRY_NRG + dry_scale_dmx -
422               (2 * sMin) + nrgScale;
423       DryEner0 = scaleValueSaturate(
424           DryEner0, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
425       break;
426     default:;
427   }
428   DryEner[0] = DryEner0;
429 
430   /* normalise the 'direct' signals */
431   for (ch = 0; ch < self->numInputChannels; ch++) {
432     if (self->treeConfig != TREE_212) DryEner[ch] = DryEner[ch] << nrgScale;
433     hStpDec->runDryEner[ch] =
434         fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
435         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
436     if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
437       DryEnerLD64[ch] =
438           fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
439                  FL2FXCONST_DBL(-0.484375f));
440     } else {
441       DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
442     }
443   }
444   for (; ch < MAX_INPUT_CHANNELS; ch++) {
445     DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
446   }
447 
448   /* normalise the 'diffuse' signals */
449   pBP = hStpDec->BP_GF - BP_GF_START;
450   for (ch = 0; ch < self->numOutputChannels; ch++) {
451     if (skipChannels[ch]) {
452       continue;
453     }
454 
455     WetEnerX = FL2FXCONST_DBL(0.0f);
456 
457     if (self->treeConfig == TREE_212) {
458       INT sMin, sNorm;
459 
460       sMin = fMin(getScalefactor(&qmfOutputRealWet[ch][BP_GF_START],
461                                  cplxBands - BP_GF_START),
462                   getScalefactor(&qmfOutputImagWet[ch][BP_GF_START],
463                                  cplxBands - BP_GF_START));
464 
465       for (n = BP_GF_START; n < cplxBands; n++) {
466         WetEnerX +=
467             (fMultDiv2(fPow2Div2(scaleValue(qmfOutputRealWet[ch][n], sMin)),
468                        pBP[n]) +
469              fMultDiv2(fPow2Div2(scaleValue(qmfOutputImagWet[ch][n], sMin)),
470                        pBP[n])) >>
471             SF_WET_NRG;
472       }
473       sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_WET_NRG + wet_scale_dmx -
474               (2 * sMin) + nrgScale;
475       WetEnerX = scaleValueSaturate(
476           WetEnerX, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
477     } else
478       FDK_ASSERT(self->treeConfig == TREE_212);
479 
480     hStpDec->runWetEner[ch] =
481         fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
482         fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
483 
484     if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
485       WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
486     } else {
487       WetEnerLD64[ch] =
488           fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
489                  FL2FXCONST_DBL(-0.484375f));
490     }
491   }
492 
493   /* compute scale factor for the 'diffuse' signals */
494   switch (self->treeConfig) {
495     case TREE_212:
496       if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
497         CALC_WET_SCALE(0, i_LF);
498         CALC_WET_SCALE(0, i_RF);
499       }
500       break;
501     default:;
502   }
503 
504   damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
505   for (ch = 0; ch < self->numOutputChannels; ch++) {
506     /* damp the scaling factor */
507     scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
508 
509     /* limiting the scale factor */
510     if (scale[ch] > STP_SCALE_LIMIT__FDK) {
511       scale[ch] = STP_SCALE_LIMIT__FDK;
512     }
513     if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
514       scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
515     }
516 
517     /* low pass filter the scaling factor */
518     scale[ch] =
519         fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
520         fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
521     hStpDec->prev_tp_scale[ch] = scale[ch];
522   }
523 
524   /* combine 'direct' and scaled 'diffuse' signal */
525   FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
526   const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
527 
528   for (ch = 0; ch < self->numOutputChannels; ch++) {
529     int no_scaling;
530 
531     no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
532     if (no_scaling) {
533       combineSignalCplx(
534           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
535           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
536           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
537           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
538           cplxHybBands - self->tp_hybBandBorder);
539 
540     } else {
541       FIXP_DBL scaleX;
542       scaleX = scale[ch];
543       pBP = hStpDec->BP - self->tp_hybBandBorder;
544       /* Band[HP_SIZE-3+10-1] needs not to be processed in
545          combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
546       combineSignalCplxScale1(
547           &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
548           &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
549           &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
550           &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
551           &pBP[self->tp_hybBandBorder], scaleX,
552           (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
553 
554       {
555         combineSignalCplxScale2(
556             &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
557             &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
558             &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
559             &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
560             cplxHybBands - (HP_SIZE - 3 + 10 - 1));
561       }
562     }
563   }
564 
565   return (SACDEC_ERROR)MPS_OK;
566   ;
567 }
568