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