xref: /aosp_15_r20/external/aac/libSBRdec/src/lpp_tran.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 /**************************** SBR 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:
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker /*!
104*e5436536SAndroid Build Coastguard Worker   \file
105*e5436536SAndroid Build Coastguard Worker   \brief  Low Power Profile Transposer
106*e5436536SAndroid Build Coastguard Worker   This module provides the transposer. The main entry point is lppTransposer().
107*e5436536SAndroid Build Coastguard Worker   The function generates high frequency content by copying data from the low
108*e5436536SAndroid Build Coastguard Worker   band (provided by core codec) into the high band. This process is also
109*e5436536SAndroid Build Coastguard Worker   referred to as "patching". The function also implements spectral whitening by
110*e5436536SAndroid Build Coastguard Worker   means of inverse filtering based on LPC coefficients.
111*e5436536SAndroid Build Coastguard Worker 
112*e5436536SAndroid Build Coastguard Worker   Together with the QMF filterbank the transposer can be tested using a supplied
113*e5436536SAndroid Build Coastguard Worker   test program. See main_audio.cpp for details. This module does use fractional
114*e5436536SAndroid Build Coastguard Worker   arithmetic and the accuracy of the computations has an impact on the overall
115*e5436536SAndroid Build Coastguard Worker   sound quality. The module also needs to take into account the different
116*e5436536SAndroid Build Coastguard Worker   scaling of spectral data.
117*e5436536SAndroid Build Coastguard Worker 
118*e5436536SAndroid Build Coastguard Worker   \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview
119*e5436536SAndroid Build Coastguard Worker */
120*e5436536SAndroid Build Coastguard Worker 
121*e5436536SAndroid Build Coastguard Worker #if __has_include(<android/ndk-version.h>)
122*e5436536SAndroid Build Coastguard Worker #include <android/ndk-version.h>
123*e5436536SAndroid Build Coastguard Worker #endif
124*e5436536SAndroid Build Coastguard Worker 
125*e5436536SAndroid Build Coastguard Worker #if defined __ANDROID__ && !defined __ANDROID_NDK__
126*e5436536SAndroid Build Coastguard Worker #include "log/log.h"
127*e5436536SAndroid Build Coastguard Worker #endif
128*e5436536SAndroid Build Coastguard Worker 
129*e5436536SAndroid Build Coastguard Worker #include "lpp_tran.h"
130*e5436536SAndroid Build Coastguard Worker 
131*e5436536SAndroid Build Coastguard Worker #include "sbr_ram.h"
132*e5436536SAndroid Build Coastguard Worker #include "sbr_rom.h"
133*e5436536SAndroid Build Coastguard Worker 
134*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
135*e5436536SAndroid Build Coastguard Worker #include "autocorr2nd.h"
136*e5436536SAndroid Build Coastguard Worker 
137*e5436536SAndroid Build Coastguard Worker #include "HFgen_preFlat.h"
138*e5436536SAndroid Build Coastguard Worker 
139*e5436536SAndroid Build Coastguard Worker #define LPC_SCALE_FACTOR 2
140*e5436536SAndroid Build Coastguard Worker 
141*e5436536SAndroid Build Coastguard Worker /*!
142*e5436536SAndroid Build Coastguard Worker  *
143*e5436536SAndroid Build Coastguard Worker  * \brief Get bandwidth expansion factor from filtering level
144*e5436536SAndroid Build Coastguard Worker  *
145*e5436536SAndroid Build Coastguard Worker  * Returns a filter parameter (bandwidth expansion factor) depending on
146*e5436536SAndroid Build Coastguard Worker  * the desired filtering level signalled in the bitstream.
147*e5436536SAndroid Build Coastguard Worker  * When switching the filtering level from LOW to OFF, an additional
148*e5436536SAndroid Build Coastguard Worker  * level is being inserted to achieve a smooth transition.
149*e5436536SAndroid Build Coastguard Worker  */
150*e5436536SAndroid Build Coastguard Worker 
mapInvfMode(INVF_MODE mode,INVF_MODE prevMode,WHITENING_FACTORS whFactors)151*e5436536SAndroid Build Coastguard Worker static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode,
152*e5436536SAndroid Build Coastguard Worker                             WHITENING_FACTORS whFactors) {
153*e5436536SAndroid Build Coastguard Worker   switch (mode) {
154*e5436536SAndroid Build Coastguard Worker     case INVF_LOW_LEVEL:
155*e5436536SAndroid Build Coastguard Worker       if (prevMode == INVF_OFF)
156*e5436536SAndroid Build Coastguard Worker         return whFactors.transitionLevel;
157*e5436536SAndroid Build Coastguard Worker       else
158*e5436536SAndroid Build Coastguard Worker         return whFactors.lowLevel;
159*e5436536SAndroid Build Coastguard Worker 
160*e5436536SAndroid Build Coastguard Worker     case INVF_MID_LEVEL:
161*e5436536SAndroid Build Coastguard Worker       return whFactors.midLevel;
162*e5436536SAndroid Build Coastguard Worker 
163*e5436536SAndroid Build Coastguard Worker     case INVF_HIGH_LEVEL:
164*e5436536SAndroid Build Coastguard Worker       return whFactors.highLevel;
165*e5436536SAndroid Build Coastguard Worker 
166*e5436536SAndroid Build Coastguard Worker     default:
167*e5436536SAndroid Build Coastguard Worker       if (prevMode == INVF_LOW_LEVEL)
168*e5436536SAndroid Build Coastguard Worker         return whFactors.transitionLevel;
169*e5436536SAndroid Build Coastguard Worker       else
170*e5436536SAndroid Build Coastguard Worker         return whFactors.off;
171*e5436536SAndroid Build Coastguard Worker   }
172*e5436536SAndroid Build Coastguard Worker }
173*e5436536SAndroid Build Coastguard Worker 
174*e5436536SAndroid Build Coastguard Worker /*!
175*e5436536SAndroid Build Coastguard Worker  *
176*e5436536SAndroid Build Coastguard Worker  * \brief Perform inverse filtering level emphasis
177*e5436536SAndroid Build Coastguard Worker  *
178*e5436536SAndroid Build Coastguard Worker  * Retrieve bandwidth expansion factor and apply smoothing for each filter band
179*e5436536SAndroid Build Coastguard Worker  *
180*e5436536SAndroid Build Coastguard Worker  */
181*e5436536SAndroid Build Coastguard Worker 
inverseFilteringLevelEmphasis(HANDLE_SBR_LPP_TRANS hLppTrans,UCHAR nInvfBands,INVF_MODE * sbr_invf_mode,INVF_MODE * sbr_invf_mode_prev,FIXP_DBL * bwVector)182*e5436536SAndroid Build Coastguard Worker static void inverseFilteringLevelEmphasis(
183*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer  */
184*e5436536SAndroid Build Coastguard Worker     UCHAR nInvfBands,              /*!< Number of bands for inverse filtering */
185*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode,      /*!< Current inverse filtering modes */
186*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */
187*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *bwVector             /*!< Resulting filtering levels */
188*e5436536SAndroid Build Coastguard Worker ) {
189*e5436536SAndroid Build Coastguard Worker   for (int i = 0; i < nInvfBands; i++) {
190*e5436536SAndroid Build Coastguard Worker     FIXP_DBL accu;
191*e5436536SAndroid Build Coastguard Worker     FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i],
192*e5436536SAndroid Build Coastguard Worker                                  hLppTrans->pSettings->whFactors);
193*e5436536SAndroid Build Coastguard Worker 
194*e5436536SAndroid Build Coastguard Worker     if (bwTmp < hLppTrans->bwVectorOld[i]) {
195*e5436536SAndroid Build Coastguard Worker       accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) +
196*e5436536SAndroid Build Coastguard Worker              fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]);
197*e5436536SAndroid Build Coastguard Worker     } else {
198*e5436536SAndroid Build Coastguard Worker       accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) +
199*e5436536SAndroid Build Coastguard Worker              fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]);
200*e5436536SAndroid Build Coastguard Worker     }
201*e5436536SAndroid Build Coastguard Worker 
202*e5436536SAndroid Build Coastguard Worker     if (accu<FL2FXCONST_DBL(0.015625f)>> 1) {
203*e5436536SAndroid Build Coastguard Worker       bwVector[i] = FL2FXCONST_DBL(0.0f);
204*e5436536SAndroid Build Coastguard Worker     } else {
205*e5436536SAndroid Build Coastguard Worker       bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f));
206*e5436536SAndroid Build Coastguard Worker     }
207*e5436536SAndroid Build Coastguard Worker   }
208*e5436536SAndroid Build Coastguard Worker }
209*e5436536SAndroid Build Coastguard Worker 
210*e5436536SAndroid Build Coastguard Worker /* Resulting autocorrelation determinant exponent */
211*e5436536SAndroid Build Coastguard Worker #define ACDET_EXP \
212*e5436536SAndroid Build Coastguard Worker   (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale))
213*e5436536SAndroid Build Coastguard Worker #define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR)
214*e5436536SAndroid Build Coastguard Worker #define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1)
215*e5436536SAndroid Build Coastguard Worker /* Resulting transposed QMF values exponent 16 bit normalized samplebits
216*e5436536SAndroid Build Coastguard Worker  * assumed. */
217*e5436536SAndroid Build Coastguard Worker #define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale)
218*e5436536SAndroid Build Coastguard Worker 
calc_qmfBufferReal(FIXP_DBL ** qmfBufferReal,const FIXP_DBL * const lowBandReal,const int startSample,const int stopSample,const UCHAR hiBand,const int dynamicScale,const FIXP_SGL a0r,const FIXP_SGL a1r)219*e5436536SAndroid Build Coastguard Worker static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal,
220*e5436536SAndroid Build Coastguard Worker                                       const FIXP_DBL *const lowBandReal,
221*e5436536SAndroid Build Coastguard Worker                                       const int startSample,
222*e5436536SAndroid Build Coastguard Worker                                       const int stopSample, const UCHAR hiBand,
223*e5436536SAndroid Build Coastguard Worker                                       const int dynamicScale,
224*e5436536SAndroid Build Coastguard Worker                                       const FIXP_SGL a0r, const FIXP_SGL a1r) {
225*e5436536SAndroid Build Coastguard Worker   const int dynscale = fixMax(0, dynamicScale - 1) + 1;
226*e5436536SAndroid Build Coastguard Worker   const int rescale = -fixMin(0, dynamicScale - 1) + 1;
227*e5436536SAndroid Build Coastguard Worker   const int descale =
228*e5436536SAndroid Build Coastguard Worker       fixMin(DFRACT_BITS - 1, LPC_SCALE_FACTOR + dynamicScale + rescale);
229*e5436536SAndroid Build Coastguard Worker 
230*e5436536SAndroid Build Coastguard Worker   for (int i = 0; i < stopSample - startSample; i++) {
231*e5436536SAndroid Build Coastguard Worker     FIXP_DBL accu;
232*e5436536SAndroid Build Coastguard Worker 
233*e5436536SAndroid Build Coastguard Worker     accu = fMultDiv2(a1r, lowBandReal[i]) + fMultDiv2(a0r, lowBandReal[i + 1]);
234*e5436536SAndroid Build Coastguard Worker     accu = (lowBandReal[i + 2] >> descale) + (accu >> dynscale);
235*e5436536SAndroid Build Coastguard Worker 
236*e5436536SAndroid Build Coastguard Worker     qmfBufferReal[i + startSample][hiBand] =
237*e5436536SAndroid Build Coastguard Worker         SATURATE_LEFT_SHIFT(accu, rescale, DFRACT_BITS);
238*e5436536SAndroid Build Coastguard Worker   }
239*e5436536SAndroid Build Coastguard Worker }
240*e5436536SAndroid Build Coastguard Worker 
241*e5436536SAndroid Build Coastguard Worker /*!
242*e5436536SAndroid Build Coastguard Worker  *
243*e5436536SAndroid Build Coastguard Worker  * \brief Perform transposition by patching of subband samples.
244*e5436536SAndroid Build Coastguard Worker  * This function serves as the main entry point into the module. The function
245*e5436536SAndroid Build Coastguard Worker  * determines the areas for the patching process (these are the source range as
246*e5436536SAndroid Build Coastguard Worker  * well as the target range) and implements spectral whitening by means of
247*e5436536SAndroid Build Coastguard Worker  * inverse filtering. The function autoCorrelation2nd() is an auxiliary function
248*e5436536SAndroid Build Coastguard Worker  * for calculating the LPC coefficients for the filtering.  The actual
249*e5436536SAndroid Build Coastguard Worker  * calculation of the LPC coefficients and the implementation of the filtering
250*e5436536SAndroid Build Coastguard Worker  * are done as part of lppTransposer().
251*e5436536SAndroid Build Coastguard Worker  *
252*e5436536SAndroid Build Coastguard Worker  * Note that the filtering is done on all available QMF subsamples, whereas the
253*e5436536SAndroid Build Coastguard Worker  * patching is only done on those QMF subsamples that will be used in the next
254*e5436536SAndroid Build Coastguard Worker  * QMF synthesis. The filtering is also implemented before the patching includes
255*e5436536SAndroid Build Coastguard Worker  * further dependencies on parameters from the SBR data.
256*e5436536SAndroid Build Coastguard Worker  *
257*e5436536SAndroid Build Coastguard Worker  */
258*e5436536SAndroid Build Coastguard Worker 
lppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans,QMF_SCALE_FACTOR * sbrScaleFactor,FIXP_DBL ** qmfBufferReal,FIXP_DBL * degreeAlias,FIXP_DBL ** qmfBufferImag,const int useLP,const int fPreWhitening,const int v_k_master0,const int timeStep,const int firstSlotOffs,const int lastSlotOffs,const int nInvfBands,INVF_MODE * sbr_invf_mode,INVF_MODE * sbr_invf_mode_prev)259*e5436536SAndroid Build Coastguard Worker void lppTransposer(
260*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_LPP_TRANS hLppTrans,   /*!< Handle of lpp transposer  */
261*e5436536SAndroid Build Coastguard Worker     QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */
262*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband
263*e5436536SAndroid Build Coastguard Worker                                  samples (source) */
264*e5436536SAndroid Build Coastguard Worker 
265*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *degreeAlias,    /*!< Vector for results of aliasing estimation */
266*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of
267*e5436536SAndroid Build Coastguard Worker                                  subband samples (source) */
268*e5436536SAndroid Build Coastguard Worker     const int useLP, const int fPreWhitening, const int v_k_master0,
269*e5436536SAndroid Build Coastguard Worker     const int timeStep,       /*!< Time step of envelope */
270*e5436536SAndroid Build Coastguard Worker     const int firstSlotOffs,  /*!< Start position in time */
271*e5436536SAndroid Build Coastguard Worker     const int lastSlotOffs,   /*!< Number of overlap-slots into next frame */
272*e5436536SAndroid Build Coastguard Worker     const int nInvfBands,     /*!< Number of bands for inverse filtering */
273*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
274*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */
275*e5436536SAndroid Build Coastguard Worker ) {
276*e5436536SAndroid Build Coastguard Worker   INT bwIndex[MAX_NUM_PATCHES];
277*e5436536SAndroid Build Coastguard Worker   FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */
278*e5436536SAndroid Build Coastguard Worker   FIXP_DBL preWhiteningGains[(64) / 2];
279*e5436536SAndroid Build Coastguard Worker   int preWhiteningGains_exp[(64) / 2];
280*e5436536SAndroid Build Coastguard Worker 
281*e5436536SAndroid Build Coastguard Worker   int i;
282*e5436536SAndroid Build Coastguard Worker   int loBand, start, stop;
283*e5436536SAndroid Build Coastguard Worker   TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
284*e5436536SAndroid Build Coastguard Worker   PATCH_PARAM *patchParam = pSettings->patchParam;
285*e5436536SAndroid Build Coastguard Worker   int patch;
286*e5436536SAndroid Build Coastguard Worker 
287*e5436536SAndroid Build Coastguard Worker   FIXP_SGL alphar[LPC_ORDER], a0r, a1r;
288*e5436536SAndroid Build Coastguard Worker   FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0;
289*e5436536SAndroid Build Coastguard Worker   FIXP_SGL bw = FL2FXCONST_SGL(0.0f);
290*e5436536SAndroid Build Coastguard Worker 
291*e5436536SAndroid Build Coastguard Worker   int autoCorrLength;
292*e5436536SAndroid Build Coastguard Worker 
293*e5436536SAndroid Build Coastguard Worker   FIXP_DBL k1, k1_below = 0, k1_below2 = 0;
294*e5436536SAndroid Build Coastguard Worker 
295*e5436536SAndroid Build Coastguard Worker   ACORR_COEFS ac;
296*e5436536SAndroid Build Coastguard Worker   int startSample;
297*e5436536SAndroid Build Coastguard Worker   int stopSample;
298*e5436536SAndroid Build Coastguard Worker   int stopSampleClear;
299*e5436536SAndroid Build Coastguard Worker 
300*e5436536SAndroid Build Coastguard Worker   int comLowBandScale;
301*e5436536SAndroid Build Coastguard Worker   int ovLowBandShift;
302*e5436536SAndroid Build Coastguard Worker   int lowBandShift;
303*e5436536SAndroid Build Coastguard Worker   /*  int ovHighBandShift;*/
304*e5436536SAndroid Build Coastguard Worker 
305*e5436536SAndroid Build Coastguard Worker   alphai[0] = FL2FXCONST_SGL(0.0f);
306*e5436536SAndroid Build Coastguard Worker   alphai[1] = FL2FXCONST_SGL(0.0f);
307*e5436536SAndroid Build Coastguard Worker 
308*e5436536SAndroid Build Coastguard Worker   startSample = firstSlotOffs * timeStep;
309*e5436536SAndroid Build Coastguard Worker   stopSample = pSettings->nCols + lastSlotOffs * timeStep;
310*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap);
311*e5436536SAndroid Build Coastguard Worker 
312*e5436536SAndroid Build Coastguard Worker   inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode,
313*e5436536SAndroid Build Coastguard Worker                                 sbr_invf_mode_prev, bwVector);
314*e5436536SAndroid Build Coastguard Worker 
315*e5436536SAndroid Build Coastguard Worker   stopSampleClear = stopSample;
316*e5436536SAndroid Build Coastguard Worker 
317*e5436536SAndroid Build Coastguard Worker   autoCorrLength = pSettings->nCols + pSettings->overlap;
318*e5436536SAndroid Build Coastguard Worker 
319*e5436536SAndroid Build Coastguard Worker   if (pSettings->noOfPatches > 0) {
320*e5436536SAndroid Build Coastguard Worker     /* Set upper subbands to zero:
321*e5436536SAndroid Build Coastguard Worker        This is required in case that the patches do not cover the complete
322*e5436536SAndroid Build Coastguard Worker        highband (because the last patch would be too short). Possible
323*e5436536SAndroid Build Coastguard Worker        optimization: Clearing bands up to usb would be sufficient here. */
324*e5436536SAndroid Build Coastguard Worker     int targetStopBand =
325*e5436536SAndroid Build Coastguard Worker         patchParam[pSettings->noOfPatches - 1].targetStartBand +
326*e5436536SAndroid Build Coastguard Worker         patchParam[pSettings->noOfPatches - 1].numBandsInPatch;
327*e5436536SAndroid Build Coastguard Worker 
328*e5436536SAndroid Build Coastguard Worker     int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL);
329*e5436536SAndroid Build Coastguard Worker 
330*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
331*e5436536SAndroid Build Coastguard Worker       for (i = startSample; i < stopSampleClear; i++) {
332*e5436536SAndroid Build Coastguard Worker         FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
333*e5436536SAndroid Build Coastguard Worker         FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize);
334*e5436536SAndroid Build Coastguard Worker       }
335*e5436536SAndroid Build Coastguard Worker     } else {
336*e5436536SAndroid Build Coastguard Worker       for (i = startSample; i < stopSampleClear; i++) {
337*e5436536SAndroid Build Coastguard Worker         FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
338*e5436536SAndroid Build Coastguard Worker       }
339*e5436536SAndroid Build Coastguard Worker     }
340*e5436536SAndroid Build Coastguard Worker   }
341*e5436536SAndroid Build Coastguard Worker #if defined __ANDROID__ && !defined __ANDROID_NDK__
342*e5436536SAndroid Build Coastguard Worker   else {
343*e5436536SAndroid Build Coastguard Worker     // Safetynet logging
344*e5436536SAndroid Build Coastguard Worker     android_errorWriteLog(0x534e4554, "112160868");
345*e5436536SAndroid Build Coastguard Worker   }
346*e5436536SAndroid Build Coastguard Worker #endif
347*e5436536SAndroid Build Coastguard Worker 
348*e5436536SAndroid Build Coastguard Worker   /* init bwIndex for each patch */
349*e5436536SAndroid Build Coastguard Worker   FDKmemclear(bwIndex, sizeof(bwIndex));
350*e5436536SAndroid Build Coastguard Worker 
351*e5436536SAndroid Build Coastguard Worker   /*
352*e5436536SAndroid Build Coastguard Worker     Calc common low band scale factor
353*e5436536SAndroid Build Coastguard Worker   */
354*e5436536SAndroid Build Coastguard Worker   comLowBandScale =
355*e5436536SAndroid Build Coastguard Worker       fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale);
356*e5436536SAndroid Build Coastguard Worker 
357*e5436536SAndroid Build Coastguard Worker   ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale;
358*e5436536SAndroid Build Coastguard Worker   lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale;
359*e5436536SAndroid Build Coastguard Worker   /*  ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/
360*e5436536SAndroid Build Coastguard Worker 
361*e5436536SAndroid Build Coastguard Worker   if (fPreWhitening) {
362*e5436536SAndroid Build Coastguard Worker     sbrDecoder_calculateGainVec(
363*e5436536SAndroid Build Coastguard Worker         qmfBufferReal, qmfBufferImag,
364*e5436536SAndroid Build Coastguard Worker         DFRACT_BITS - 1 - 16 -
365*e5436536SAndroid Build Coastguard Worker             sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */
366*e5436536SAndroid Build Coastguard Worker         DFRACT_BITS - 1 - 16 -
367*e5436536SAndroid Build Coastguard Worker             sbrScaleFactor->lb_scale, /* convert scale to exponent */
368*e5436536SAndroid Build Coastguard Worker         pSettings->overlap, preWhiteningGains, preWhiteningGains_exp,
369*e5436536SAndroid Build Coastguard Worker         v_k_master0, startSample, stopSample);
370*e5436536SAndroid Build Coastguard Worker   }
371*e5436536SAndroid Build Coastguard Worker 
372*e5436536SAndroid Build Coastguard Worker   /* outer loop over bands to do analysis only once for each band */
373*e5436536SAndroid Build Coastguard Worker 
374*e5436536SAndroid Build Coastguard Worker   if (!useLP) {
375*e5436536SAndroid Build Coastguard Worker     start = pSettings->lbStartPatching;
376*e5436536SAndroid Build Coastguard Worker     stop = pSettings->lbStopPatching;
377*e5436536SAndroid Build Coastguard Worker   } else {
378*e5436536SAndroid Build Coastguard Worker     start = fixMax(1, pSettings->lbStartPatching - 2);
379*e5436536SAndroid Build Coastguard Worker     stop = patchParam[0].targetStartBand;
380*e5436536SAndroid Build Coastguard Worker   }
381*e5436536SAndroid Build Coastguard Worker 
382*e5436536SAndroid Build Coastguard Worker   for (loBand = start; loBand < stop; loBand++) {
383*e5436536SAndroid Build Coastguard Worker     FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
384*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *plowBandReal = lowBandReal;
385*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **pqmfBufferReal =
386*e5436536SAndroid Build Coastguard Worker         qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */;
387*e5436536SAndroid Build Coastguard Worker     FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
388*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *plowBandImag = lowBandImag;
389*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **pqmfBufferImag =
390*e5436536SAndroid Build Coastguard Worker         qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */;
391*e5436536SAndroid Build Coastguard Worker     int resetLPCCoeffs = 0;
392*e5436536SAndroid Build Coastguard Worker     int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR;
393*e5436536SAndroid Build Coastguard Worker     int acDetScale = 0; /* scaling of autocorrelation determinant */
394*e5436536SAndroid Build Coastguard Worker 
395*e5436536SAndroid Build Coastguard Worker     for (i = 0;
396*e5436536SAndroid Build Coastguard Worker          i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/;
397*e5436536SAndroid Build Coastguard Worker          i++) {
398*e5436536SAndroid Build Coastguard Worker       *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand];
399*e5436536SAndroid Build Coastguard Worker       if (!useLP)
400*e5436536SAndroid Build Coastguard Worker         *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand];
401*e5436536SAndroid Build Coastguard Worker     }
402*e5436536SAndroid Build Coastguard Worker 
403*e5436536SAndroid Build Coastguard Worker     /*
404*e5436536SAndroid Build Coastguard Worker       Take old slope length qmf slot source values out of (overlap)qmf buffer
405*e5436536SAndroid Build Coastguard Worker     */
406*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
407*e5436536SAndroid Build Coastguard Worker       for (i = 0;
408*e5436536SAndroid Build Coastguard Worker            i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep;
409*e5436536SAndroid Build Coastguard Worker            i++) {
410*e5436536SAndroid Build Coastguard Worker         *plowBandReal++ = (*pqmfBufferReal++)[loBand];
411*e5436536SAndroid Build Coastguard Worker         *plowBandImag++ = (*pqmfBufferImag++)[loBand];
412*e5436536SAndroid Build Coastguard Worker       }
413*e5436536SAndroid Build Coastguard Worker     } else {
414*e5436536SAndroid Build Coastguard Worker       /* pSettings->overlap is always even */
415*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT((pSettings->overlap & 1) == 0);
416*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < ((pSettings->nCols + pSettings->overlap -
417*e5436536SAndroid Build Coastguard Worker                         firstSlotOffs * timeStep) >>
418*e5436536SAndroid Build Coastguard Worker                        1);
419*e5436536SAndroid Build Coastguard Worker            i++) {
420*e5436536SAndroid Build Coastguard Worker         *plowBandReal++ = (*pqmfBufferReal++)[loBand];
421*e5436536SAndroid Build Coastguard Worker         *plowBandReal++ = (*pqmfBufferReal++)[loBand];
422*e5436536SAndroid Build Coastguard Worker       }
423*e5436536SAndroid Build Coastguard Worker       if (pSettings->nCols & 1) {
424*e5436536SAndroid Build Coastguard Worker         *plowBandReal++ = (*pqmfBufferReal++)[loBand];
425*e5436536SAndroid Build Coastguard Worker       }
426*e5436536SAndroid Build Coastguard Worker     }
427*e5436536SAndroid Build Coastguard Worker 
428*e5436536SAndroid Build Coastguard Worker     /*
429*e5436536SAndroid Build Coastguard Worker       Determine dynamic scaling value.
430*e5436536SAndroid Build Coastguard Worker      */
431*e5436536SAndroid Build Coastguard Worker     dynamicScale =
432*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
433*e5436536SAndroid Build Coastguard Worker                getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) +
434*e5436536SAndroid Build Coastguard Worker                    ovLowBandShift);
435*e5436536SAndroid Build Coastguard Worker     dynamicScale =
436*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
437*e5436536SAndroid Build Coastguard Worker                getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap],
438*e5436536SAndroid Build Coastguard Worker                               pSettings->nCols) +
439*e5436536SAndroid Build Coastguard Worker                    lowBandShift);
440*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
441*e5436536SAndroid Build Coastguard Worker       dynamicScale =
442*e5436536SAndroid Build Coastguard Worker           fixMin(dynamicScale,
443*e5436536SAndroid Build Coastguard Worker                  getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) +
444*e5436536SAndroid Build Coastguard Worker                      ovLowBandShift);
445*e5436536SAndroid Build Coastguard Worker       dynamicScale =
446*e5436536SAndroid Build Coastguard Worker           fixMin(dynamicScale,
447*e5436536SAndroid Build Coastguard Worker                  getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap],
448*e5436536SAndroid Build Coastguard Worker                                 pSettings->nCols) +
449*e5436536SAndroid Build Coastguard Worker                      lowBandShift);
450*e5436536SAndroid Build Coastguard Worker     }
451*e5436536SAndroid Build Coastguard Worker 
452*e5436536SAndroid Build Coastguard Worker     if (dynamicScale == 0) {
453*e5436536SAndroid Build Coastguard Worker       /* In this special case the available headroom bits as well as
454*e5436536SAndroid Build Coastguard Worker          ovLowBandShift and lowBandShift are zero. The spectrum is limited to
455*e5436536SAndroid Build Coastguard Worker          prevent -1.0, so negative values for dynamicScale can be avoided. */
456*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols);
457*e5436536SAndroid Build Coastguard Worker            i++) {
458*e5436536SAndroid Build Coastguard Worker         lowBandReal[i] = fixMax(lowBandReal[i], (FIXP_DBL)0x80000001);
459*e5436536SAndroid Build Coastguard Worker       }
460*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
461*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < (LPC_ORDER + pSettings->overlap + pSettings->nCols);
462*e5436536SAndroid Build Coastguard Worker              i++) {
463*e5436536SAndroid Build Coastguard Worker           lowBandImag[i] = fixMax(lowBandImag[i], (FIXP_DBL)0x80000001);
464*e5436536SAndroid Build Coastguard Worker         }
465*e5436536SAndroid Build Coastguard Worker       }
466*e5436536SAndroid Build Coastguard Worker     } else {
467*e5436536SAndroid Build Coastguard Worker       dynamicScale =
468*e5436536SAndroid Build Coastguard Worker           fixMax(0, dynamicScale -
469*e5436536SAndroid Build Coastguard Worker                         1); /* one additional bit headroom to prevent -1.0 */
470*e5436536SAndroid Build Coastguard Worker     }
471*e5436536SAndroid Build Coastguard Worker 
472*e5436536SAndroid Build Coastguard Worker     /*
473*e5436536SAndroid Build Coastguard Worker       Scale temporal QMF buffer.
474*e5436536SAndroid Build Coastguard Worker      */
475*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap,
476*e5436536SAndroid Build Coastguard Worker                 dynamicScale - ovLowBandShift);
477*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols,
478*e5436536SAndroid Build Coastguard Worker                 dynamicScale - lowBandShift);
479*e5436536SAndroid Build Coastguard Worker 
480*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
481*e5436536SAndroid Build Coastguard Worker       scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap,
482*e5436536SAndroid Build Coastguard Worker                   dynamicScale - ovLowBandShift);
483*e5436536SAndroid Build Coastguard Worker       scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap],
484*e5436536SAndroid Build Coastguard Worker                   pSettings->nCols, dynamicScale - lowBandShift);
485*e5436536SAndroid Build Coastguard Worker     }
486*e5436536SAndroid Build Coastguard Worker 
487*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
488*e5436536SAndroid Build Coastguard Worker       acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER,
489*e5436536SAndroid Build Coastguard Worker                                      lowBandImag + LPC_ORDER, autoCorrLength);
490*e5436536SAndroid Build Coastguard Worker     } else {
491*e5436536SAndroid Build Coastguard Worker       acDetScale +=
492*e5436536SAndroid Build Coastguard Worker           autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength);
493*e5436536SAndroid Build Coastguard Worker     }
494*e5436536SAndroid Build Coastguard Worker 
495*e5436536SAndroid Build Coastguard Worker     /* Examine dynamic of determinant in autocorrelation. */
496*e5436536SAndroid Build Coastguard Worker     acDetScale += 2 * (comLowBandScale + dynamicScale);
497*e5436536SAndroid Build Coastguard Worker     acDetScale *= 2;            /* two times reflection coefficent scaling */
498*e5436536SAndroid Build Coastguard Worker     acDetScale += ac.det_scale; /* ac scaling of determinant */
499*e5436536SAndroid Build Coastguard Worker 
500*e5436536SAndroid Build Coastguard Worker     /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */
501*e5436536SAndroid Build Coastguard Worker     if (acDetScale > 126) {
502*e5436536SAndroid Build Coastguard Worker       resetLPCCoeffs = 1;
503*e5436536SAndroid Build Coastguard Worker     }
504*e5436536SAndroid Build Coastguard Worker 
505*e5436536SAndroid Build Coastguard Worker     alphar[1] = FL2FXCONST_SGL(0.0f);
506*e5436536SAndroid Build Coastguard Worker     if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f);
507*e5436536SAndroid Build Coastguard Worker 
508*e5436536SAndroid Build Coastguard Worker     if (ac.det != FL2FXCONST_DBL(0.0f)) {
509*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp, absTmp, absDet;
510*e5436536SAndroid Build Coastguard Worker 
511*e5436536SAndroid Build Coastguard Worker       absDet = fixp_abs(ac.det);
512*e5436536SAndroid Build Coastguard Worker 
513*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
514*e5436536SAndroid Build Coastguard Worker         tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
515*e5436536SAndroid Build Coastguard Worker               ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >>
516*e5436536SAndroid Build Coastguard Worker                (LPC_SCALE_FACTOR - 1));
517*e5436536SAndroid Build Coastguard Worker       } else {
518*e5436536SAndroid Build Coastguard Worker         tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
519*e5436536SAndroid Build Coastguard Worker               (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1));
520*e5436536SAndroid Build Coastguard Worker       }
521*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
522*e5436536SAndroid Build Coastguard Worker 
523*e5436536SAndroid Build Coastguard Worker       /*
524*e5436536SAndroid Build Coastguard Worker         Quick check: is first filter coeff >= 1(4)
525*e5436536SAndroid Build Coastguard Worker        */
526*e5436536SAndroid Build Coastguard Worker       {
527*e5436536SAndroid Build Coastguard Worker         INT scale;
528*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
529*e5436536SAndroid Build Coastguard Worker         scale = scale + ac.det_scale;
530*e5436536SAndroid Build Coastguard Worker 
531*e5436536SAndroid Build Coastguard Worker         if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
532*e5436536SAndroid Build Coastguard Worker           resetLPCCoeffs = 1;
533*e5436536SAndroid Build Coastguard Worker         } else {
534*e5436536SAndroid Build Coastguard Worker           alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
535*e5436536SAndroid Build Coastguard Worker           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
536*e5436536SAndroid Build Coastguard Worker             alphar[1] = -alphar[1];
537*e5436536SAndroid Build Coastguard Worker           }
538*e5436536SAndroid Build Coastguard Worker         }
539*e5436536SAndroid Build Coastguard Worker       }
540*e5436536SAndroid Build Coastguard Worker 
541*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
542*e5436536SAndroid Build Coastguard Worker         tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) +
543*e5436536SAndroid Build Coastguard Worker               ((fMultDiv2(ac.r01r, ac.r12i) -
544*e5436536SAndroid Build Coastguard Worker                 (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >>
545*e5436536SAndroid Build Coastguard Worker                (LPC_SCALE_FACTOR - 1));
546*e5436536SAndroid Build Coastguard Worker 
547*e5436536SAndroid Build Coastguard Worker         absTmp = fixp_abs(tmp);
548*e5436536SAndroid Build Coastguard Worker 
549*e5436536SAndroid Build Coastguard Worker         /*
550*e5436536SAndroid Build Coastguard Worker         Quick check: is second filter coeff >= 1(4)
551*e5436536SAndroid Build Coastguard Worker         */
552*e5436536SAndroid Build Coastguard Worker         {
553*e5436536SAndroid Build Coastguard Worker           INT scale;
554*e5436536SAndroid Build Coastguard Worker           FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
555*e5436536SAndroid Build Coastguard Worker           scale = scale + ac.det_scale;
556*e5436536SAndroid Build Coastguard Worker 
557*e5436536SAndroid Build Coastguard Worker           if ((scale > 0) &&
558*e5436536SAndroid Build Coastguard Worker               (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >>
559*e5436536SAndroid Build Coastguard Worker                scale)) {
560*e5436536SAndroid Build Coastguard Worker             resetLPCCoeffs = 1;
561*e5436536SAndroid Build Coastguard Worker           } else {
562*e5436536SAndroid Build Coastguard Worker             alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
563*e5436536SAndroid Build Coastguard Worker             if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
564*e5436536SAndroid Build Coastguard Worker               alphai[1] = -alphai[1];
565*e5436536SAndroid Build Coastguard Worker             }
566*e5436536SAndroid Build Coastguard Worker           }
567*e5436536SAndroid Build Coastguard Worker         }
568*e5436536SAndroid Build Coastguard Worker       }
569*e5436536SAndroid Build Coastguard Worker     }
570*e5436536SAndroid Build Coastguard Worker 
571*e5436536SAndroid Build Coastguard Worker     alphar[0] = FL2FXCONST_SGL(0.0f);
572*e5436536SAndroid Build Coastguard Worker     if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f);
573*e5436536SAndroid Build Coastguard Worker 
574*e5436536SAndroid Build Coastguard Worker     if (ac.r11r != FL2FXCONST_DBL(0.0f)) {
575*e5436536SAndroid Build Coastguard Worker       /* ac.r11r is always >=0 */
576*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp, absTmp;
577*e5436536SAndroid Build Coastguard Worker 
578*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
579*e5436536SAndroid Build Coastguard Worker         tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
580*e5436536SAndroid Build Coastguard Worker               (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i));
581*e5436536SAndroid Build Coastguard Worker       } else {
582*e5436536SAndroid Build Coastguard Worker         if (ac.r01r >= FL2FXCONST_DBL(0.0f))
583*e5436536SAndroid Build Coastguard Worker           tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
584*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(alphar[1], ac.r12r);
585*e5436536SAndroid Build Coastguard Worker         else
586*e5436536SAndroid Build Coastguard Worker           tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) +
587*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(alphar[1], ac.r12r);
588*e5436536SAndroid Build Coastguard Worker       }
589*e5436536SAndroid Build Coastguard Worker 
590*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
591*e5436536SAndroid Build Coastguard Worker 
592*e5436536SAndroid Build Coastguard Worker       /*
593*e5436536SAndroid Build Coastguard Worker         Quick check: is first filter coeff >= 1(4)
594*e5436536SAndroid Build Coastguard Worker       */
595*e5436536SAndroid Build Coastguard Worker 
596*e5436536SAndroid Build Coastguard Worker       if (absTmp >= (ac.r11r >> 1)) {
597*e5436536SAndroid Build Coastguard Worker         resetLPCCoeffs = 1;
598*e5436536SAndroid Build Coastguard Worker       } else {
599*e5436536SAndroid Build Coastguard Worker         INT scale;
600*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
601*e5436536SAndroid Build Coastguard Worker         alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
602*e5436536SAndroid Build Coastguard Worker 
603*e5436536SAndroid Build Coastguard Worker         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
604*e5436536SAndroid Build Coastguard Worker           alphar[0] = -alphar[0];
605*e5436536SAndroid Build Coastguard Worker       }
606*e5436536SAndroid Build Coastguard Worker 
607*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
608*e5436536SAndroid Build Coastguard Worker         tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) +
609*e5436536SAndroid Build Coastguard Worker               (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i));
610*e5436536SAndroid Build Coastguard Worker 
611*e5436536SAndroid Build Coastguard Worker         absTmp = fixp_abs(tmp);
612*e5436536SAndroid Build Coastguard Worker 
613*e5436536SAndroid Build Coastguard Worker         /*
614*e5436536SAndroid Build Coastguard Worker         Quick check: is second filter coeff >= 1(4)
615*e5436536SAndroid Build Coastguard Worker         */
616*e5436536SAndroid Build Coastguard Worker         if (absTmp >= (ac.r11r >> 1)) {
617*e5436536SAndroid Build Coastguard Worker           resetLPCCoeffs = 1;
618*e5436536SAndroid Build Coastguard Worker         } else {
619*e5436536SAndroid Build Coastguard Worker           INT scale;
620*e5436536SAndroid Build Coastguard Worker           FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
621*e5436536SAndroid Build Coastguard Worker           alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
622*e5436536SAndroid Build Coastguard Worker           if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
623*e5436536SAndroid Build Coastguard Worker             alphai[0] = -alphai[0];
624*e5436536SAndroid Build Coastguard Worker         }
625*e5436536SAndroid Build Coastguard Worker       }
626*e5436536SAndroid Build Coastguard Worker     }
627*e5436536SAndroid Build Coastguard Worker 
628*e5436536SAndroid Build Coastguard Worker     if (!useLP) {
629*e5436536SAndroid Build Coastguard Worker       /* Now check the quadratic criteria */
630*e5436536SAndroid Build Coastguard Worker       if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >=
631*e5436536SAndroid Build Coastguard Worker           FL2FXCONST_DBL(0.5f))
632*e5436536SAndroid Build Coastguard Worker         resetLPCCoeffs = 1;
633*e5436536SAndroid Build Coastguard Worker       if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >=
634*e5436536SAndroid Build Coastguard Worker           FL2FXCONST_DBL(0.5f))
635*e5436536SAndroid Build Coastguard Worker         resetLPCCoeffs = 1;
636*e5436536SAndroid Build Coastguard Worker     }
637*e5436536SAndroid Build Coastguard Worker 
638*e5436536SAndroid Build Coastguard Worker     if (resetLPCCoeffs) {
639*e5436536SAndroid Build Coastguard Worker       alphar[0] = FL2FXCONST_SGL(0.0f);
640*e5436536SAndroid Build Coastguard Worker       alphar[1] = FL2FXCONST_SGL(0.0f);
641*e5436536SAndroid Build Coastguard Worker       if (!useLP) {
642*e5436536SAndroid Build Coastguard Worker         alphai[0] = FL2FXCONST_SGL(0.0f);
643*e5436536SAndroid Build Coastguard Worker         alphai[1] = FL2FXCONST_SGL(0.0f);
644*e5436536SAndroid Build Coastguard Worker       }
645*e5436536SAndroid Build Coastguard Worker     }
646*e5436536SAndroid Build Coastguard Worker 
647*e5436536SAndroid Build Coastguard Worker     if (useLP) {
648*e5436536SAndroid Build Coastguard Worker       /* Aliasing detection */
649*e5436536SAndroid Build Coastguard Worker       if (ac.r11r == FL2FXCONST_DBL(0.0f)) {
650*e5436536SAndroid Build Coastguard Worker         k1 = FL2FXCONST_DBL(0.0f);
651*e5436536SAndroid Build Coastguard Worker       } else {
652*e5436536SAndroid Build Coastguard Worker         if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) {
653*e5436536SAndroid Build Coastguard Worker           if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) {
654*e5436536SAndroid Build Coastguard Worker             k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/;
655*e5436536SAndroid Build Coastguard Worker           } else {
656*e5436536SAndroid Build Coastguard Worker             /* Since this value is squared later, it must not ever become -1.0f.
657*e5436536SAndroid Build Coastguard Worker              */
658*e5436536SAndroid Build Coastguard Worker             k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/;
659*e5436536SAndroid Build Coastguard Worker           }
660*e5436536SAndroid Build Coastguard Worker         } else {
661*e5436536SAndroid Build Coastguard Worker           INT scale;
662*e5436536SAndroid Build Coastguard Worker           FIXP_DBL result =
663*e5436536SAndroid Build Coastguard Worker               fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale);
664*e5436536SAndroid Build Coastguard Worker           k1 = scaleValueSaturate(result, scale);
665*e5436536SAndroid Build Coastguard Worker 
666*e5436536SAndroid Build Coastguard Worker           if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) {
667*e5436536SAndroid Build Coastguard Worker             k1 = -k1;
668*e5436536SAndroid Build Coastguard Worker           }
669*e5436536SAndroid Build Coastguard Worker         }
670*e5436536SAndroid Build Coastguard Worker       }
671*e5436536SAndroid Build Coastguard Worker       if ((loBand > 1) && (loBand < v_k_master0)) {
672*e5436536SAndroid Build Coastguard Worker         /* Check if the gain should be locked */
673*e5436536SAndroid Build Coastguard Worker         FIXP_DBL deg =
674*e5436536SAndroid Build Coastguard Worker             /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below);
675*e5436536SAndroid Build Coastguard Worker         degreeAlias[loBand] = FL2FXCONST_DBL(0.0f);
676*e5436536SAndroid Build Coastguard Worker         if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) {
677*e5436536SAndroid Build Coastguard Worker           if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */
678*e5436536SAndroid Build Coastguard Worker             degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/;
679*e5436536SAndroid Build Coastguard Worker             if (k1_below2 >
680*e5436536SAndroid Build Coastguard Worker                 FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */
681*e5436536SAndroid Build Coastguard Worker               degreeAlias[loBand - 1] = deg;
682*e5436536SAndroid Build Coastguard Worker             }
683*e5436536SAndroid Build Coastguard Worker           } else if (k1_below2 >
684*e5436536SAndroid Build Coastguard Worker                      FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */
685*e5436536SAndroid Build Coastguard Worker             degreeAlias[loBand] = deg;
686*e5436536SAndroid Build Coastguard Worker           }
687*e5436536SAndroid Build Coastguard Worker         }
688*e5436536SAndroid Build Coastguard Worker         if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) {
689*e5436536SAndroid Build Coastguard Worker           if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */
690*e5436536SAndroid Build Coastguard Worker             degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/;
691*e5436536SAndroid Build Coastguard Worker             if (k1_below2 <
692*e5436536SAndroid Build Coastguard Worker                 FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */
693*e5436536SAndroid Build Coastguard Worker               degreeAlias[loBand - 1] = deg;
694*e5436536SAndroid Build Coastguard Worker             }
695*e5436536SAndroid Build Coastguard Worker           } else if (k1_below2 <
696*e5436536SAndroid Build Coastguard Worker                      FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */
697*e5436536SAndroid Build Coastguard Worker             degreeAlias[loBand] = deg;
698*e5436536SAndroid Build Coastguard Worker           }
699*e5436536SAndroid Build Coastguard Worker         }
700*e5436536SAndroid Build Coastguard Worker       }
701*e5436536SAndroid Build Coastguard Worker       /* remember k1 values of the 2 QMF channels below the current channel */
702*e5436536SAndroid Build Coastguard Worker       k1_below2 = k1_below;
703*e5436536SAndroid Build Coastguard Worker       k1_below = k1;
704*e5436536SAndroid Build Coastguard Worker     }
705*e5436536SAndroid Build Coastguard Worker 
706*e5436536SAndroid Build Coastguard Worker     patch = 0;
707*e5436536SAndroid Build Coastguard Worker 
708*e5436536SAndroid Build Coastguard Worker     while (patch < pSettings->noOfPatches) { /* inner loop over every patch */
709*e5436536SAndroid Build Coastguard Worker 
710*e5436536SAndroid Build Coastguard Worker       int hiBand = loBand + patchParam[patch].targetBandOffs;
711*e5436536SAndroid Build Coastguard Worker 
712*e5436536SAndroid Build Coastguard Worker       if (loBand < patchParam[patch].sourceStartBand ||
713*e5436536SAndroid Build Coastguard Worker           loBand >= patchParam[patch].sourceStopBand
714*e5436536SAndroid Build Coastguard Worker           //|| hiBand >= hLppTrans->pSettings->noChannels
715*e5436536SAndroid Build Coastguard Worker       ) {
716*e5436536SAndroid Build Coastguard Worker         /* Lowband not in current patch - proceed */
717*e5436536SAndroid Build Coastguard Worker         patch++;
718*e5436536SAndroid Build Coastguard Worker         continue;
719*e5436536SAndroid Build Coastguard Worker       }
720*e5436536SAndroid Build Coastguard Worker 
721*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(hiBand < (64));
722*e5436536SAndroid Build Coastguard Worker 
723*e5436536SAndroid Build Coastguard Worker       /* bwIndex[patch] is already initialized with value from previous band
724*e5436536SAndroid Build Coastguard Worker        * inside this patch */
725*e5436536SAndroid Build Coastguard Worker       while (hiBand >= pSettings->bwBorders[bwIndex[patch]] &&
726*e5436536SAndroid Build Coastguard Worker              bwIndex[patch] < MAX_NUM_PATCHES - 1) {
727*e5436536SAndroid Build Coastguard Worker         bwIndex[patch]++;
728*e5436536SAndroid Build Coastguard Worker       }
729*e5436536SAndroid Build Coastguard Worker 
730*e5436536SAndroid Build Coastguard Worker       /*
731*e5436536SAndroid Build Coastguard Worker         Filter Step 2: add the left slope with the current filter to the buffer
732*e5436536SAndroid Build Coastguard Worker                        pure source values are already in there
733*e5436536SAndroid Build Coastguard Worker       */
734*e5436536SAndroid Build Coastguard Worker       bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]);
735*e5436536SAndroid Build Coastguard Worker 
736*e5436536SAndroid Build Coastguard Worker       a0r = FX_DBL2FX_SGL(
737*e5436536SAndroid Build Coastguard Worker           fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */
738*e5436536SAndroid Build Coastguard Worker 
739*e5436536SAndroid Build Coastguard Worker       if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0]));
740*e5436536SAndroid Build Coastguard Worker       bw = FX_DBL2FX_SGL(fPow2(bw));
741*e5436536SAndroid Build Coastguard Worker       a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1]));
742*e5436536SAndroid Build Coastguard Worker       if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1]));
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker       /*
745*e5436536SAndroid Build Coastguard Worker         Filter Step 3: insert the middle part which won't be windowed
746*e5436536SAndroid Build Coastguard Worker       */
747*e5436536SAndroid Build Coastguard Worker       if (bw <= FL2FXCONST_SGL(0.0f)) {
748*e5436536SAndroid Build Coastguard Worker         if (!useLP) {
749*e5436536SAndroid Build Coastguard Worker           int descale =
750*e5436536SAndroid Build Coastguard Worker               fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
751*e5436536SAndroid Build Coastguard Worker           for (i = startSample; i < stopSample; i++) {
752*e5436536SAndroid Build Coastguard Worker             FIXP_DBL accu1, accu2;
753*e5436536SAndroid Build Coastguard Worker             accu1 = lowBandReal[LPC_ORDER + i] >> descale;
754*e5436536SAndroid Build Coastguard Worker             accu2 = lowBandImag[LPC_ORDER + i] >> descale;
755*e5436536SAndroid Build Coastguard Worker             if (fPreWhitening) {
756*e5436536SAndroid Build Coastguard Worker               accu1 = scaleValueSaturate(
757*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(accu1, preWhiteningGains[loBand]),
758*e5436536SAndroid Build Coastguard Worker                   preWhiteningGains_exp[loBand] + 1);
759*e5436536SAndroid Build Coastguard Worker               accu2 = scaleValueSaturate(
760*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(accu2, preWhiteningGains[loBand]),
761*e5436536SAndroid Build Coastguard Worker                   preWhiteningGains_exp[loBand] + 1);
762*e5436536SAndroid Build Coastguard Worker             }
763*e5436536SAndroid Build Coastguard Worker             qmfBufferReal[i][hiBand] = accu1;
764*e5436536SAndroid Build Coastguard Worker             qmfBufferImag[i][hiBand] = accu2;
765*e5436536SAndroid Build Coastguard Worker           }
766*e5436536SAndroid Build Coastguard Worker         } else {
767*e5436536SAndroid Build Coastguard Worker           int descale =
768*e5436536SAndroid Build Coastguard Worker               fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
769*e5436536SAndroid Build Coastguard Worker           for (i = startSample; i < stopSample; i++) {
770*e5436536SAndroid Build Coastguard Worker             qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale;
771*e5436536SAndroid Build Coastguard Worker           }
772*e5436536SAndroid Build Coastguard Worker         }
773*e5436536SAndroid Build Coastguard Worker       } else { /* bw <= 0 */
774*e5436536SAndroid Build Coastguard Worker 
775*e5436536SAndroid Build Coastguard Worker         if (!useLP) {
776*e5436536SAndroid Build Coastguard Worker           const int dynscale = fixMax(0, dynamicScale - 2) + 1;
777*e5436536SAndroid Build Coastguard Worker           const int rescale = -fixMin(0, dynamicScale - 2) + 1;
778*e5436536SAndroid Build Coastguard Worker           const int descale = fixMin(DFRACT_BITS - 1,
779*e5436536SAndroid Build Coastguard Worker                                      LPC_SCALE_FACTOR + dynamicScale + rescale);
780*e5436536SAndroid Build Coastguard Worker 
781*e5436536SAndroid Build Coastguard Worker           for (i = startSample; i < stopSample; i++) {
782*e5436536SAndroid Build Coastguard Worker             FIXP_DBL accu1, accu2;
783*e5436536SAndroid Build Coastguard Worker 
784*e5436536SAndroid Build Coastguard Worker             accu1 = ((fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
785*e5436536SAndroid Build Coastguard Worker                       fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1])) >>
786*e5436536SAndroid Build Coastguard Worker                      1) +
787*e5436536SAndroid Build Coastguard Worker                     ((fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
788*e5436536SAndroid Build Coastguard Worker                       fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
789*e5436536SAndroid Build Coastguard Worker                      1);
790*e5436536SAndroid Build Coastguard Worker             accu2 = ((fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
791*e5436536SAndroid Build Coastguard Worker                       fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1])) >>
792*e5436536SAndroid Build Coastguard Worker                      1) +
793*e5436536SAndroid Build Coastguard Worker                     ((fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
794*e5436536SAndroid Build Coastguard Worker                       fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
795*e5436536SAndroid Build Coastguard Worker                      1);
796*e5436536SAndroid Build Coastguard Worker 
797*e5436536SAndroid Build Coastguard Worker             accu1 =
798*e5436536SAndroid Build Coastguard Worker                 (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 >> dynscale);
799*e5436536SAndroid Build Coastguard Worker             accu2 =
800*e5436536SAndroid Build Coastguard Worker                 (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 >> dynscale);
801*e5436536SAndroid Build Coastguard Worker             if (fPreWhitening) {
802*e5436536SAndroid Build Coastguard Worker               qmfBufferReal[i][hiBand] = scaleValueSaturate(
803*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(accu1, preWhiteningGains[loBand]),
804*e5436536SAndroid Build Coastguard Worker                   preWhiteningGains_exp[loBand] + 1 + rescale);
805*e5436536SAndroid Build Coastguard Worker               qmfBufferImag[i][hiBand] = scaleValueSaturate(
806*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(accu2, preWhiteningGains[loBand]),
807*e5436536SAndroid Build Coastguard Worker                   preWhiteningGains_exp[loBand] + 1 + rescale);
808*e5436536SAndroid Build Coastguard Worker             } else {
809*e5436536SAndroid Build Coastguard Worker               qmfBufferReal[i][hiBand] =
810*e5436536SAndroid Build Coastguard Worker                   SATURATE_LEFT_SHIFT(accu1, rescale, DFRACT_BITS);
811*e5436536SAndroid Build Coastguard Worker               qmfBufferImag[i][hiBand] =
812*e5436536SAndroid Build Coastguard Worker                   SATURATE_LEFT_SHIFT(accu2, rescale, DFRACT_BITS);
813*e5436536SAndroid Build Coastguard Worker             }
814*e5436536SAndroid Build Coastguard Worker           }
815*e5436536SAndroid Build Coastguard Worker         } else {
816*e5436536SAndroid Build Coastguard Worker           FDK_ASSERT(dynamicScale >= 0);
817*e5436536SAndroid Build Coastguard Worker           calc_qmfBufferReal(
818*e5436536SAndroid Build Coastguard Worker               qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]),
819*e5436536SAndroid Build Coastguard Worker               startSample, stopSample, hiBand, dynamicScale, a0r, a1r);
820*e5436536SAndroid Build Coastguard Worker         }
821*e5436536SAndroid Build Coastguard Worker       } /* bw <= 0 */
822*e5436536SAndroid Build Coastguard Worker 
823*e5436536SAndroid Build Coastguard Worker       patch++;
824*e5436536SAndroid Build Coastguard Worker 
825*e5436536SAndroid Build Coastguard Worker     } /* inner loop over patches */
826*e5436536SAndroid Build Coastguard Worker 
827*e5436536SAndroid Build Coastguard Worker     /*
828*e5436536SAndroid Build Coastguard Worker      * store the unmodified filter coefficients if there is
829*e5436536SAndroid Build Coastguard Worker      * an overlapping envelope
830*e5436536SAndroid Build Coastguard Worker      *****************************************************************/
831*e5436536SAndroid Build Coastguard Worker 
832*e5436536SAndroid Build Coastguard Worker   } /* outer loop over bands (loBand) */
833*e5436536SAndroid Build Coastguard Worker 
834*e5436536SAndroid Build Coastguard Worker   if (useLP) {
835*e5436536SAndroid Build Coastguard Worker     for (loBand = pSettings->lbStartPatching;
836*e5436536SAndroid Build Coastguard Worker          loBand < pSettings->lbStopPatching; loBand++) {
837*e5436536SAndroid Build Coastguard Worker       patch = 0;
838*e5436536SAndroid Build Coastguard Worker       while (patch < pSettings->noOfPatches) {
839*e5436536SAndroid Build Coastguard Worker         UCHAR hiBand = loBand + patchParam[patch].targetBandOffs;
840*e5436536SAndroid Build Coastguard Worker 
841*e5436536SAndroid Build Coastguard Worker         if (loBand < patchParam[patch].sourceStartBand ||
842*e5436536SAndroid Build Coastguard Worker             loBand >= patchParam[patch].sourceStopBand ||
843*e5436536SAndroid Build Coastguard Worker             hiBand >= (64) /* Highband out of range (biterror) */
844*e5436536SAndroid Build Coastguard Worker         ) {
845*e5436536SAndroid Build Coastguard Worker           /* Lowband not in current patch or highband out of range (might be
846*e5436536SAndroid Build Coastguard Worker            * caused by biterrors)- proceed */
847*e5436536SAndroid Build Coastguard Worker           patch++;
848*e5436536SAndroid Build Coastguard Worker           continue;
849*e5436536SAndroid Build Coastguard Worker         }
850*e5436536SAndroid Build Coastguard Worker 
851*e5436536SAndroid Build Coastguard Worker         if (hiBand != patchParam[patch].targetStartBand)
852*e5436536SAndroid Build Coastguard Worker           degreeAlias[hiBand] = degreeAlias[loBand];
853*e5436536SAndroid Build Coastguard Worker 
854*e5436536SAndroid Build Coastguard Worker         patch++;
855*e5436536SAndroid Build Coastguard Worker       }
856*e5436536SAndroid Build Coastguard Worker     } /* end  for loop */
857*e5436536SAndroid Build Coastguard Worker   }
858*e5436536SAndroid Build Coastguard Worker 
859*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nInvfBands; i++) {
860*e5436536SAndroid Build Coastguard Worker     hLppTrans->bwVectorOld[i] = bwVector[i];
861*e5436536SAndroid Build Coastguard Worker   }
862*e5436536SAndroid Build Coastguard Worker 
863*e5436536SAndroid Build Coastguard Worker   /*
864*e5436536SAndroid Build Coastguard Worker     set high band scale factor
865*e5436536SAndroid Build Coastguard Worker   */
866*e5436536SAndroid Build Coastguard Worker   sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR);
867*e5436536SAndroid Build Coastguard Worker }
868*e5436536SAndroid Build Coastguard Worker 
lppTransposerHBE(HANDLE_SBR_LPP_TRANS hLppTrans,HANDLE_HBE_TRANSPOSER hQmfTransposer,QMF_SCALE_FACTOR * sbrScaleFactor,FIXP_DBL ** qmfBufferReal,FIXP_DBL ** qmfBufferImag,const int timeStep,const int firstSlotOffs,const int lastSlotOffs,const int nInvfBands,INVF_MODE * sbr_invf_mode,INVF_MODE * sbr_invf_mode_prev)869*e5436536SAndroid Build Coastguard Worker void lppTransposerHBE(
870*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer  */
871*e5436536SAndroid Build Coastguard Worker     HANDLE_HBE_TRANSPOSER hQmfTransposer,
872*e5436536SAndroid Build Coastguard Worker     QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */
873*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband
874*e5436536SAndroid Build Coastguard Worker                                  samples (source) */
875*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of
876*e5436536SAndroid Build Coastguard Worker                                  subband samples (source) */
877*e5436536SAndroid Build Coastguard Worker     const int timeStep,       /*!< Time step of envelope */
878*e5436536SAndroid Build Coastguard Worker     const int firstSlotOffs,  /*!< Start position in time */
879*e5436536SAndroid Build Coastguard Worker     const int lastSlotOffs,   /*!< Number of overlap-slots into next frame */
880*e5436536SAndroid Build Coastguard Worker     const int nInvfBands,     /*!< Number of bands for inverse filtering */
881*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */
882*e5436536SAndroid Build Coastguard Worker     INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */
883*e5436536SAndroid Build Coastguard Worker ) {
884*e5436536SAndroid Build Coastguard Worker   INT bwIndex;
885*e5436536SAndroid Build Coastguard Worker   FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */
886*e5436536SAndroid Build Coastguard Worker 
887*e5436536SAndroid Build Coastguard Worker   int i;
888*e5436536SAndroid Build Coastguard Worker   int loBand, start, stop;
889*e5436536SAndroid Build Coastguard Worker   TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
890*e5436536SAndroid Build Coastguard Worker   PATCH_PARAM *patchParam = pSettings->patchParam;
891*e5436536SAndroid Build Coastguard Worker 
892*e5436536SAndroid Build Coastguard Worker   FIXP_SGL alphar[LPC_ORDER], a0r, a1r;
893*e5436536SAndroid Build Coastguard Worker   FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0;
894*e5436536SAndroid Build Coastguard Worker   FIXP_SGL bw = FL2FXCONST_SGL(0.0f);
895*e5436536SAndroid Build Coastguard Worker 
896*e5436536SAndroid Build Coastguard Worker   int autoCorrLength;
897*e5436536SAndroid Build Coastguard Worker 
898*e5436536SAndroid Build Coastguard Worker   ACORR_COEFS ac;
899*e5436536SAndroid Build Coastguard Worker   int startSample;
900*e5436536SAndroid Build Coastguard Worker   int stopSample;
901*e5436536SAndroid Build Coastguard Worker   int stopSampleClear;
902*e5436536SAndroid Build Coastguard Worker 
903*e5436536SAndroid Build Coastguard Worker   int comBandScale;
904*e5436536SAndroid Build Coastguard Worker   int ovLowBandShift;
905*e5436536SAndroid Build Coastguard Worker   int lowBandShift;
906*e5436536SAndroid Build Coastguard Worker   /*  int ovHighBandShift;*/
907*e5436536SAndroid Build Coastguard Worker 
908*e5436536SAndroid Build Coastguard Worker   alphai[0] = FL2FXCONST_SGL(0.0f);
909*e5436536SAndroid Build Coastguard Worker   alphai[1] = FL2FXCONST_SGL(0.0f);
910*e5436536SAndroid Build Coastguard Worker 
911*e5436536SAndroid Build Coastguard Worker   startSample = firstSlotOffs * timeStep;
912*e5436536SAndroid Build Coastguard Worker   stopSample = pSettings->nCols + lastSlotOffs * timeStep;
913*e5436536SAndroid Build Coastguard Worker 
914*e5436536SAndroid Build Coastguard Worker   inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode,
915*e5436536SAndroid Build Coastguard Worker                                 sbr_invf_mode_prev, bwVector);
916*e5436536SAndroid Build Coastguard Worker 
917*e5436536SAndroid Build Coastguard Worker   stopSampleClear = stopSample;
918*e5436536SAndroid Build Coastguard Worker 
919*e5436536SAndroid Build Coastguard Worker   autoCorrLength = pSettings->nCols + pSettings->overlap;
920*e5436536SAndroid Build Coastguard Worker 
921*e5436536SAndroid Build Coastguard Worker   if (pSettings->noOfPatches > 0) {
922*e5436536SAndroid Build Coastguard Worker     /* Set upper subbands to zero:
923*e5436536SAndroid Build Coastguard Worker        This is required in case that the patches do not cover the complete
924*e5436536SAndroid Build Coastguard Worker        highband (because the last patch would be too short). Possible
925*e5436536SAndroid Build Coastguard Worker        optimization: Clearing bands up to usb would be sufficient here. */
926*e5436536SAndroid Build Coastguard Worker     int targetStopBand =
927*e5436536SAndroid Build Coastguard Worker         patchParam[pSettings->noOfPatches - 1].targetStartBand +
928*e5436536SAndroid Build Coastguard Worker         patchParam[pSettings->noOfPatches - 1].numBandsInPatch;
929*e5436536SAndroid Build Coastguard Worker 
930*e5436536SAndroid Build Coastguard Worker     int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL);
931*e5436536SAndroid Build Coastguard Worker 
932*e5436536SAndroid Build Coastguard Worker     for (i = startSample; i < stopSampleClear; i++) {
933*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize);
934*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize);
935*e5436536SAndroid Build Coastguard Worker     }
936*e5436536SAndroid Build Coastguard Worker   }
937*e5436536SAndroid Build Coastguard Worker #if defined __ANDROID__ && !defined __ANDROID_NDK__
938*e5436536SAndroid Build Coastguard Worker   else {
939*e5436536SAndroid Build Coastguard Worker     // Safetynet logging
940*e5436536SAndroid Build Coastguard Worker     android_errorWriteLog(0x534e4554, "112160868");
941*e5436536SAndroid Build Coastguard Worker   }
942*e5436536SAndroid Build Coastguard Worker #endif
943*e5436536SAndroid Build Coastguard Worker 
944*e5436536SAndroid Build Coastguard Worker   /*
945*e5436536SAndroid Build Coastguard Worker   Calc common low band scale factor
946*e5436536SAndroid Build Coastguard Worker   */
947*e5436536SAndroid Build Coastguard Worker   comBandScale = sbrScaleFactor->hb_scale;
948*e5436536SAndroid Build Coastguard Worker 
949*e5436536SAndroid Build Coastguard Worker   ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale;
950*e5436536SAndroid Build Coastguard Worker   lowBandShift = sbrScaleFactor->hb_scale - comBandScale;
951*e5436536SAndroid Build Coastguard Worker   /*  ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/
952*e5436536SAndroid Build Coastguard Worker 
953*e5436536SAndroid Build Coastguard Worker   /* outer loop over bands to do analysis only once for each band */
954*e5436536SAndroid Build Coastguard Worker 
955*e5436536SAndroid Build Coastguard Worker   start = hQmfTransposer->startBand;
956*e5436536SAndroid Build Coastguard Worker   stop = hQmfTransposer->stopBand;
957*e5436536SAndroid Build Coastguard Worker 
958*e5436536SAndroid Build Coastguard Worker   for (loBand = start; loBand < stop; loBand++) {
959*e5436536SAndroid Build Coastguard Worker     bwIndex = 0;
960*e5436536SAndroid Build Coastguard Worker 
961*e5436536SAndroid Build Coastguard Worker     FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
962*e5436536SAndroid Build Coastguard Worker     FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER];
963*e5436536SAndroid Build Coastguard Worker 
964*e5436536SAndroid Build Coastguard Worker     int resetLPCCoeffs = 0;
965*e5436536SAndroid Build Coastguard Worker     int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR;
966*e5436536SAndroid Build Coastguard Worker     int acDetScale = 0; /* scaling of autocorrelation determinant */
967*e5436536SAndroid Build Coastguard Worker 
968*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < LPC_ORDER; i++) {
969*e5436536SAndroid Build Coastguard Worker       lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand];
970*e5436536SAndroid Build Coastguard Worker       lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand];
971*e5436536SAndroid Build Coastguard Worker     }
972*e5436536SAndroid Build Coastguard Worker 
973*e5436536SAndroid Build Coastguard Worker     for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) {
974*e5436536SAndroid Build Coastguard Worker       lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand];
975*e5436536SAndroid Build Coastguard Worker       lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand];
976*e5436536SAndroid Build Coastguard Worker     }
977*e5436536SAndroid Build Coastguard Worker 
978*e5436536SAndroid Build Coastguard Worker     /*
979*e5436536SAndroid Build Coastguard Worker     Take old slope length qmf slot source values out of (overlap)qmf buffer
980*e5436536SAndroid Build Coastguard Worker     */
981*e5436536SAndroid Build Coastguard Worker     for (i = firstSlotOffs * timeStep;
982*e5436536SAndroid Build Coastguard Worker          i < pSettings->nCols + pSettings->overlap; i++) {
983*e5436536SAndroid Build Coastguard Worker       lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand];
984*e5436536SAndroid Build Coastguard Worker       lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand];
985*e5436536SAndroid Build Coastguard Worker     }
986*e5436536SAndroid Build Coastguard Worker 
987*e5436536SAndroid Build Coastguard Worker     /* store unmodified values to buffer */
988*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) {
989*e5436536SAndroid Build Coastguard Worker       hLppTrans->lpcFilterStatesRealHBE[i][loBand] =
990*e5436536SAndroid Build Coastguard Worker           qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand];
991*e5436536SAndroid Build Coastguard Worker       hLppTrans->lpcFilterStatesImagHBE[i][loBand] =
992*e5436536SAndroid Build Coastguard Worker           qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand];
993*e5436536SAndroid Build Coastguard Worker     }
994*e5436536SAndroid Build Coastguard Worker 
995*e5436536SAndroid Build Coastguard Worker     /*
996*e5436536SAndroid Build Coastguard Worker     Determine dynamic scaling value.
997*e5436536SAndroid Build Coastguard Worker     */
998*e5436536SAndroid Build Coastguard Worker     dynamicScale =
999*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
1000*e5436536SAndroid Build Coastguard Worker                getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) +
1001*e5436536SAndroid Build Coastguard Worker                    ovLowBandShift);
1002*e5436536SAndroid Build Coastguard Worker     dynamicScale =
1003*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
1004*e5436536SAndroid Build Coastguard Worker                getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap],
1005*e5436536SAndroid Build Coastguard Worker                               pSettings->nCols) +
1006*e5436536SAndroid Build Coastguard Worker                    lowBandShift);
1007*e5436536SAndroid Build Coastguard Worker     dynamicScale =
1008*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
1009*e5436536SAndroid Build Coastguard Worker                getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) +
1010*e5436536SAndroid Build Coastguard Worker                    ovLowBandShift);
1011*e5436536SAndroid Build Coastguard Worker     dynamicScale =
1012*e5436536SAndroid Build Coastguard Worker         fixMin(dynamicScale,
1013*e5436536SAndroid Build Coastguard Worker                getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap],
1014*e5436536SAndroid Build Coastguard Worker                               pSettings->nCols) +
1015*e5436536SAndroid Build Coastguard Worker                    lowBandShift);
1016*e5436536SAndroid Build Coastguard Worker 
1017*e5436536SAndroid Build Coastguard Worker     dynamicScale =
1018*e5436536SAndroid Build Coastguard Worker         dynamicScale - 1; /* one additional bit headroom to prevent -1.0 */
1019*e5436536SAndroid Build Coastguard Worker 
1020*e5436536SAndroid Build Coastguard Worker     /*
1021*e5436536SAndroid Build Coastguard Worker     Scale temporal QMF buffer.
1022*e5436536SAndroid Build Coastguard Worker     */
1023*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap,
1024*e5436536SAndroid Build Coastguard Worker                 dynamicScale - ovLowBandShift);
1025*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols,
1026*e5436536SAndroid Build Coastguard Worker                 dynamicScale - lowBandShift);
1027*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap,
1028*e5436536SAndroid Build Coastguard Worker                 dynamicScale - ovLowBandShift);
1029*e5436536SAndroid Build Coastguard Worker     scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols,
1030*e5436536SAndroid Build Coastguard Worker                 dynamicScale - lowBandShift);
1031*e5436536SAndroid Build Coastguard Worker 
1032*e5436536SAndroid Build Coastguard Worker     acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER,
1033*e5436536SAndroid Build Coastguard Worker                                    lowBandImag + LPC_ORDER, autoCorrLength);
1034*e5436536SAndroid Build Coastguard Worker 
1035*e5436536SAndroid Build Coastguard Worker     /* Examine dynamic of determinant in autocorrelation. */
1036*e5436536SAndroid Build Coastguard Worker     acDetScale += 2 * (comBandScale + dynamicScale);
1037*e5436536SAndroid Build Coastguard Worker     acDetScale *= 2;            /* two times reflection coefficent scaling */
1038*e5436536SAndroid Build Coastguard Worker     acDetScale += ac.det_scale; /* ac scaling of determinant */
1039*e5436536SAndroid Build Coastguard Worker 
1040*e5436536SAndroid Build Coastguard Worker     /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */
1041*e5436536SAndroid Build Coastguard Worker     if (acDetScale > 126) {
1042*e5436536SAndroid Build Coastguard Worker       resetLPCCoeffs = 1;
1043*e5436536SAndroid Build Coastguard Worker     }
1044*e5436536SAndroid Build Coastguard Worker 
1045*e5436536SAndroid Build Coastguard Worker     alphar[1] = FL2FXCONST_SGL(0.0f);
1046*e5436536SAndroid Build Coastguard Worker     alphai[1] = FL2FXCONST_SGL(0.0f);
1047*e5436536SAndroid Build Coastguard Worker 
1048*e5436536SAndroid Build Coastguard Worker     if (ac.det != FL2FXCONST_DBL(0.0f)) {
1049*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp, absTmp, absDet;
1050*e5436536SAndroid Build Coastguard Worker 
1051*e5436536SAndroid Build Coastguard Worker       absDet = fixp_abs(ac.det);
1052*e5436536SAndroid Build Coastguard Worker 
1053*e5436536SAndroid Build Coastguard Worker       tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) -
1054*e5436536SAndroid Build Coastguard Worker             ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >>
1055*e5436536SAndroid Build Coastguard Worker              (LPC_SCALE_FACTOR - 1));
1056*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
1057*e5436536SAndroid Build Coastguard Worker 
1058*e5436536SAndroid Build Coastguard Worker       /*
1059*e5436536SAndroid Build Coastguard Worker       Quick check: is first filter coeff >= 1(4)
1060*e5436536SAndroid Build Coastguard Worker       */
1061*e5436536SAndroid Build Coastguard Worker       {
1062*e5436536SAndroid Build Coastguard Worker         INT scale;
1063*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
1064*e5436536SAndroid Build Coastguard Worker         scale = scale + ac.det_scale;
1065*e5436536SAndroid Build Coastguard Worker 
1066*e5436536SAndroid Build Coastguard Worker         if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
1067*e5436536SAndroid Build Coastguard Worker           resetLPCCoeffs = 1;
1068*e5436536SAndroid Build Coastguard Worker         } else {
1069*e5436536SAndroid Build Coastguard Worker           alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
1070*e5436536SAndroid Build Coastguard Worker           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
1071*e5436536SAndroid Build Coastguard Worker             alphar[1] = -alphar[1];
1072*e5436536SAndroid Build Coastguard Worker           }
1073*e5436536SAndroid Build Coastguard Worker         }
1074*e5436536SAndroid Build Coastguard Worker       }
1075*e5436536SAndroid Build Coastguard Worker 
1076*e5436536SAndroid Build Coastguard Worker       tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) +
1077*e5436536SAndroid Build Coastguard Worker             ((fMultDiv2(ac.r01r, ac.r12i) -
1078*e5436536SAndroid Build Coastguard Worker               (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >>
1079*e5436536SAndroid Build Coastguard Worker              (LPC_SCALE_FACTOR - 1));
1080*e5436536SAndroid Build Coastguard Worker 
1081*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
1082*e5436536SAndroid Build Coastguard Worker 
1083*e5436536SAndroid Build Coastguard Worker       /*
1084*e5436536SAndroid Build Coastguard Worker       Quick check: is second filter coeff >= 1(4)
1085*e5436536SAndroid Build Coastguard Worker       */
1086*e5436536SAndroid Build Coastguard Worker       {
1087*e5436536SAndroid Build Coastguard Worker         INT scale;
1088*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, absDet, &scale);
1089*e5436536SAndroid Build Coastguard Worker         scale = scale + ac.det_scale;
1090*e5436536SAndroid Build Coastguard Worker 
1091*e5436536SAndroid Build Coastguard Worker         if ((scale > 0) &&
1092*e5436536SAndroid Build Coastguard Worker             (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) {
1093*e5436536SAndroid Build Coastguard Worker           resetLPCCoeffs = 1;
1094*e5436536SAndroid Build Coastguard Worker         } else {
1095*e5436536SAndroid Build Coastguard Worker           alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
1096*e5436536SAndroid Build Coastguard Worker           if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
1097*e5436536SAndroid Build Coastguard Worker             alphai[1] = -alphai[1];
1098*e5436536SAndroid Build Coastguard Worker           }
1099*e5436536SAndroid Build Coastguard Worker         }
1100*e5436536SAndroid Build Coastguard Worker       }
1101*e5436536SAndroid Build Coastguard Worker     }
1102*e5436536SAndroid Build Coastguard Worker 
1103*e5436536SAndroid Build Coastguard Worker     alphar[0] = FL2FXCONST_SGL(0.0f);
1104*e5436536SAndroid Build Coastguard Worker     alphai[0] = FL2FXCONST_SGL(0.0f);
1105*e5436536SAndroid Build Coastguard Worker 
1106*e5436536SAndroid Build Coastguard Worker     if (ac.r11r != FL2FXCONST_DBL(0.0f)) {
1107*e5436536SAndroid Build Coastguard Worker       /* ac.r11r is always >=0 */
1108*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp, absTmp;
1109*e5436536SAndroid Build Coastguard Worker 
1110*e5436536SAndroid Build Coastguard Worker       tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) +
1111*e5436536SAndroid Build Coastguard Worker             (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i));
1112*e5436536SAndroid Build Coastguard Worker 
1113*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
1114*e5436536SAndroid Build Coastguard Worker 
1115*e5436536SAndroid Build Coastguard Worker       /*
1116*e5436536SAndroid Build Coastguard Worker       Quick check: is first filter coeff >= 1(4)
1117*e5436536SAndroid Build Coastguard Worker       */
1118*e5436536SAndroid Build Coastguard Worker 
1119*e5436536SAndroid Build Coastguard Worker       if (absTmp >= (ac.r11r >> 1)) {
1120*e5436536SAndroid Build Coastguard Worker         resetLPCCoeffs = 1;
1121*e5436536SAndroid Build Coastguard Worker       } else {
1122*e5436536SAndroid Build Coastguard Worker         INT scale;
1123*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
1124*e5436536SAndroid Build Coastguard Worker         alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
1125*e5436536SAndroid Build Coastguard Worker 
1126*e5436536SAndroid Build Coastguard Worker         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
1127*e5436536SAndroid Build Coastguard Worker           alphar[0] = -alphar[0];
1128*e5436536SAndroid Build Coastguard Worker       }
1129*e5436536SAndroid Build Coastguard Worker 
1130*e5436536SAndroid Build Coastguard Worker       tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) +
1131*e5436536SAndroid Build Coastguard Worker             (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i));
1132*e5436536SAndroid Build Coastguard Worker 
1133*e5436536SAndroid Build Coastguard Worker       absTmp = fixp_abs(tmp);
1134*e5436536SAndroid Build Coastguard Worker 
1135*e5436536SAndroid Build Coastguard Worker       /*
1136*e5436536SAndroid Build Coastguard Worker       Quick check: is second filter coeff >= 1(4)
1137*e5436536SAndroid Build Coastguard Worker       */
1138*e5436536SAndroid Build Coastguard Worker       if (absTmp >= (ac.r11r >> 1)) {
1139*e5436536SAndroid Build Coastguard Worker         resetLPCCoeffs = 1;
1140*e5436536SAndroid Build Coastguard Worker       } else {
1141*e5436536SAndroid Build Coastguard Worker         INT scale;
1142*e5436536SAndroid Build Coastguard Worker         FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
1143*e5436536SAndroid Build Coastguard Worker         alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
1144*e5436536SAndroid Build Coastguard Worker         if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) {
1145*e5436536SAndroid Build Coastguard Worker           alphai[0] = -alphai[0];
1146*e5436536SAndroid Build Coastguard Worker         }
1147*e5436536SAndroid Build Coastguard Worker       }
1148*e5436536SAndroid Build Coastguard Worker     }
1149*e5436536SAndroid Build Coastguard Worker 
1150*e5436536SAndroid Build Coastguard Worker     /* Now check the quadratic criteria */
1151*e5436536SAndroid Build Coastguard Worker     if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >=
1152*e5436536SAndroid Build Coastguard Worker         FL2FXCONST_DBL(0.5f)) {
1153*e5436536SAndroid Build Coastguard Worker       resetLPCCoeffs = 1;
1154*e5436536SAndroid Build Coastguard Worker     }
1155*e5436536SAndroid Build Coastguard Worker     if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >=
1156*e5436536SAndroid Build Coastguard Worker         FL2FXCONST_DBL(0.5f)) {
1157*e5436536SAndroid Build Coastguard Worker       resetLPCCoeffs = 1;
1158*e5436536SAndroid Build Coastguard Worker     }
1159*e5436536SAndroid Build Coastguard Worker 
1160*e5436536SAndroid Build Coastguard Worker     if (resetLPCCoeffs) {
1161*e5436536SAndroid Build Coastguard Worker       alphar[0] = FL2FXCONST_SGL(0.0f);
1162*e5436536SAndroid Build Coastguard Worker       alphar[1] = FL2FXCONST_SGL(0.0f);
1163*e5436536SAndroid Build Coastguard Worker       alphai[0] = FL2FXCONST_SGL(0.0f);
1164*e5436536SAndroid Build Coastguard Worker       alphai[1] = FL2FXCONST_SGL(0.0f);
1165*e5436536SAndroid Build Coastguard Worker     }
1166*e5436536SAndroid Build Coastguard Worker 
1167*e5436536SAndroid Build Coastguard Worker     while (bwIndex < MAX_NUM_PATCHES - 1 &&
1168*e5436536SAndroid Build Coastguard Worker            loBand >= pSettings->bwBorders[bwIndex]) {
1169*e5436536SAndroid Build Coastguard Worker       bwIndex++;
1170*e5436536SAndroid Build Coastguard Worker     }
1171*e5436536SAndroid Build Coastguard Worker 
1172*e5436536SAndroid Build Coastguard Worker     /*
1173*e5436536SAndroid Build Coastguard Worker     Filter Step 2: add the left slope with the current filter to the buffer
1174*e5436536SAndroid Build Coastguard Worker     pure source values are already in there
1175*e5436536SAndroid Build Coastguard Worker     */
1176*e5436536SAndroid Build Coastguard Worker     bw = FX_DBL2FX_SGL(bwVector[bwIndex]);
1177*e5436536SAndroid Build Coastguard Worker 
1178*e5436536SAndroid Build Coastguard Worker     a0r = FX_DBL2FX_SGL(
1179*e5436536SAndroid Build Coastguard Worker         fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */
1180*e5436536SAndroid Build Coastguard Worker     a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0]));
1181*e5436536SAndroid Build Coastguard Worker     bw = FX_DBL2FX_SGL(fPow2(bw));
1182*e5436536SAndroid Build Coastguard Worker     a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1]));
1183*e5436536SAndroid Build Coastguard Worker     a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1]));
1184*e5436536SAndroid Build Coastguard Worker 
1185*e5436536SAndroid Build Coastguard Worker     /*
1186*e5436536SAndroid Build Coastguard Worker     Filter Step 3: insert the middle part which won't be windowed
1187*e5436536SAndroid Build Coastguard Worker     */
1188*e5436536SAndroid Build Coastguard Worker     if (bw <= FL2FXCONST_SGL(0.0f)) {
1189*e5436536SAndroid Build Coastguard Worker       int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
1190*e5436536SAndroid Build Coastguard Worker       for (i = startSample; i < stopSample; i++) {
1191*e5436536SAndroid Build Coastguard Worker         qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale;
1192*e5436536SAndroid Build Coastguard Worker         qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale;
1193*e5436536SAndroid Build Coastguard Worker       }
1194*e5436536SAndroid Build Coastguard Worker     } else { /* bw <= 0 */
1195*e5436536SAndroid Build Coastguard Worker 
1196*e5436536SAndroid Build Coastguard Worker       int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
1197*e5436536SAndroid Build Coastguard Worker       dynamicScale +=
1198*e5436536SAndroid Build Coastguard Worker           1; /* prevent negativ scale factor due to 'one additional bit
1199*e5436536SAndroid Build Coastguard Worker                 headroom' */
1200*e5436536SAndroid Build Coastguard Worker 
1201*e5436536SAndroid Build Coastguard Worker       for (i = startSample; i < stopSample; i++) {
1202*e5436536SAndroid Build Coastguard Worker         FIXP_DBL accu1, accu2;
1203*e5436536SAndroid Build Coastguard Worker 
1204*e5436536SAndroid Build Coastguard Worker         accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
1205*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) +
1206*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
1207*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
1208*e5436536SAndroid Build Coastguard Worker                 dynamicScale;
1209*e5436536SAndroid Build Coastguard Worker         accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
1210*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) +
1211*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
1212*e5436536SAndroid Build Coastguard Worker                  fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
1213*e5436536SAndroid Build Coastguard Worker                 dynamicScale;
1214*e5436536SAndroid Build Coastguard Worker 
1215*e5436536SAndroid Build Coastguard Worker         qmfBufferReal[i][loBand] =
1216*e5436536SAndroid Build Coastguard Worker             (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << (1 + 1));
1217*e5436536SAndroid Build Coastguard Worker         qmfBufferImag[i][loBand] =
1218*e5436536SAndroid Build Coastguard Worker             (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << (1 + 1));
1219*e5436536SAndroid Build Coastguard Worker       }
1220*e5436536SAndroid Build Coastguard Worker     } /* bw <= 0 */
1221*e5436536SAndroid Build Coastguard Worker 
1222*e5436536SAndroid Build Coastguard Worker     /*
1223*e5436536SAndroid Build Coastguard Worker      * store the unmodified filter coefficients if there is
1224*e5436536SAndroid Build Coastguard Worker      * an overlapping envelope
1225*e5436536SAndroid Build Coastguard Worker      *****************************************************************/
1226*e5436536SAndroid Build Coastguard Worker 
1227*e5436536SAndroid Build Coastguard Worker   } /* outer loop over bands (loBand) */
1228*e5436536SAndroid Build Coastguard Worker 
1229*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nInvfBands; i++) {
1230*e5436536SAndroid Build Coastguard Worker     hLppTrans->bwVectorOld[i] = bwVector[i];
1231*e5436536SAndroid Build Coastguard Worker   }
1232*e5436536SAndroid Build Coastguard Worker 
1233*e5436536SAndroid Build Coastguard Worker   /*
1234*e5436536SAndroid Build Coastguard Worker   set high band scale factor
1235*e5436536SAndroid Build Coastguard Worker   */
1236*e5436536SAndroid Build Coastguard Worker   sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR);
1237*e5436536SAndroid Build Coastguard Worker }
1238*e5436536SAndroid Build Coastguard Worker 
1239*e5436536SAndroid Build Coastguard Worker /*!
1240*e5436536SAndroid Build Coastguard Worker  *
1241*e5436536SAndroid Build Coastguard Worker  * \brief Initialize one low power transposer instance
1242*e5436536SAndroid Build Coastguard Worker  *
1243*e5436536SAndroid Build Coastguard Worker  *
1244*e5436536SAndroid Build Coastguard Worker  */
1245*e5436536SAndroid Build Coastguard Worker SBR_ERROR
createLppTransposer(HANDLE_SBR_LPP_TRANS hs,TRANSPOSER_SETTINGS * pSettings,const int highBandStartSb,UCHAR * v_k_master,const int numMaster,const int usb,const int timeSlots,const int nCols,UCHAR * noiseBandTable,const int noNoiseBands,UINT fs,const int chan,const int overlap)1246*e5436536SAndroid Build Coastguard Worker createLppTransposer(
1247*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_LPP_TRANS hs,        /*!< Handle of low power transposer  */
1248*e5436536SAndroid Build Coastguard Worker     TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */
1249*e5436536SAndroid Build Coastguard Worker     const int highBandStartSb,      /*!< ? */
1250*e5436536SAndroid Build Coastguard Worker     UCHAR *v_k_master,              /*!< Master table */
1251*e5436536SAndroid Build Coastguard Worker     const int numMaster,            /*!< Valid entries in master table */
1252*e5436536SAndroid Build Coastguard Worker     const int usb,                  /*!< Highband area stop subband */
1253*e5436536SAndroid Build Coastguard Worker     const int timeSlots,            /*!< Number of time slots */
1254*e5436536SAndroid Build Coastguard Worker     const int nCols,                /*!< Number of colums (codec qmf bank) */
1255*e5436536SAndroid Build Coastguard Worker     UCHAR *noiseBandTable,  /*!< Mapping of SBR noise bands to QMF bands */
1256*e5436536SAndroid Build Coastguard Worker     const int noNoiseBands, /*!< Number of noise bands */
1257*e5436536SAndroid Build Coastguard Worker     UINT fs,                /*!< Sample Frequency */
1258*e5436536SAndroid Build Coastguard Worker     const int chan,         /*!< Channel number */
1259*e5436536SAndroid Build Coastguard Worker     const int overlap) {
1260*e5436536SAndroid Build Coastguard Worker   /* FB inverse filtering settings */
1261*e5436536SAndroid Build Coastguard Worker   hs->pSettings = pSettings;
1262*e5436536SAndroid Build Coastguard Worker 
1263*e5436536SAndroid Build Coastguard Worker   pSettings->nCols = nCols;
1264*e5436536SAndroid Build Coastguard Worker   pSettings->overlap = overlap;
1265*e5436536SAndroid Build Coastguard Worker 
1266*e5436536SAndroid Build Coastguard Worker   switch (timeSlots) {
1267*e5436536SAndroid Build Coastguard Worker     case 15:
1268*e5436536SAndroid Build Coastguard Worker     case 16:
1269*e5436536SAndroid Build Coastguard Worker       break;
1270*e5436536SAndroid Build Coastguard Worker 
1271*e5436536SAndroid Build Coastguard Worker     default:
1272*e5436536SAndroid Build Coastguard Worker       return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */
1273*e5436536SAndroid Build Coastguard Worker   }
1274*e5436536SAndroid Build Coastguard Worker 
1275*e5436536SAndroid Build Coastguard Worker   if (chan == 0) {
1276*e5436536SAndroid Build Coastguard Worker     /* Init common data only once */
1277*e5436536SAndroid Build Coastguard Worker     hs->pSettings->nCols = nCols;
1278*e5436536SAndroid Build Coastguard Worker 
1279*e5436536SAndroid Build Coastguard Worker     return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster,
1280*e5436536SAndroid Build Coastguard Worker                               noiseBandTable, noNoiseBands, usb, fs);
1281*e5436536SAndroid Build Coastguard Worker   }
1282*e5436536SAndroid Build Coastguard Worker   return SBRDEC_OK;
1283*e5436536SAndroid Build Coastguard Worker }
1284*e5436536SAndroid Build Coastguard Worker 
findClosestEntry(UCHAR goalSb,UCHAR * v_k_master,UCHAR numMaster,UCHAR direction)1285*e5436536SAndroid Build Coastguard Worker static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster,
1286*e5436536SAndroid Build Coastguard Worker                             UCHAR direction) {
1287*e5436536SAndroid Build Coastguard Worker   int index;
1288*e5436536SAndroid Build Coastguard Worker 
1289*e5436536SAndroid Build Coastguard Worker   if (goalSb <= v_k_master[0]) return v_k_master[0];
1290*e5436536SAndroid Build Coastguard Worker 
1291*e5436536SAndroid Build Coastguard Worker   if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster];
1292*e5436536SAndroid Build Coastguard Worker 
1293*e5436536SAndroid Build Coastguard Worker   if (direction) {
1294*e5436536SAndroid Build Coastguard Worker     index = 0;
1295*e5436536SAndroid Build Coastguard Worker     while (v_k_master[index] < goalSb) {
1296*e5436536SAndroid Build Coastguard Worker       index++;
1297*e5436536SAndroid Build Coastguard Worker     }
1298*e5436536SAndroid Build Coastguard Worker   } else {
1299*e5436536SAndroid Build Coastguard Worker     index = numMaster;
1300*e5436536SAndroid Build Coastguard Worker     while (v_k_master[index] > goalSb) {
1301*e5436536SAndroid Build Coastguard Worker       index--;
1302*e5436536SAndroid Build Coastguard Worker     }
1303*e5436536SAndroid Build Coastguard Worker   }
1304*e5436536SAndroid Build Coastguard Worker 
1305*e5436536SAndroid Build Coastguard Worker   return v_k_master[index];
1306*e5436536SAndroid Build Coastguard Worker }
1307*e5436536SAndroid Build Coastguard Worker 
1308*e5436536SAndroid Build Coastguard Worker /*!
1309*e5436536SAndroid Build Coastguard Worker  *
1310*e5436536SAndroid Build Coastguard Worker  * \brief Reset memory for one lpp transposer instance
1311*e5436536SAndroid Build Coastguard Worker  *
1312*e5436536SAndroid Build Coastguard Worker  * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error
1313*e5436536SAndroid Build Coastguard Worker  */
1314*e5436536SAndroid Build Coastguard Worker SBR_ERROR
resetLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans,UCHAR highBandStartSb,UCHAR * v_k_master,UCHAR numMaster,UCHAR * noiseBandTable,UCHAR noNoiseBands,UCHAR usb,UINT fs)1315*e5436536SAndroid Build Coastguard Worker resetLppTransposer(
1316*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer  */
1317*e5436536SAndroid Build Coastguard Worker     UCHAR highBandStartSb,          /*!< High band area: start subband */
1318*e5436536SAndroid Build Coastguard Worker     UCHAR *v_k_master,              /*!< Master table */
1319*e5436536SAndroid Build Coastguard Worker     UCHAR numMaster,                /*!< Valid entries in master table */
1320*e5436536SAndroid Build Coastguard Worker     UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */
1321*e5436536SAndroid Build Coastguard Worker     UCHAR noNoiseBands,    /*!< Number of noise bands */
1322*e5436536SAndroid Build Coastguard Worker     UCHAR usb,             /*!< High band area: stop subband */
1323*e5436536SAndroid Build Coastguard Worker     UINT fs                /*!< SBR output sampling frequency */
1324*e5436536SAndroid Build Coastguard Worker ) {
1325*e5436536SAndroid Build Coastguard Worker   TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings;
1326*e5436536SAndroid Build Coastguard Worker   PATCH_PARAM *patchParam = pSettings->patchParam;
1327*e5436536SAndroid Build Coastguard Worker 
1328*e5436536SAndroid Build Coastguard Worker   int i, patch;
1329*e5436536SAndroid Build Coastguard Worker   int targetStopBand;
1330*e5436536SAndroid Build Coastguard Worker   int sourceStartBand;
1331*e5436536SAndroid Build Coastguard Worker   int patchDistance;
1332*e5436536SAndroid Build Coastguard Worker   int numBandsInPatch;
1333*e5436536SAndroid Build Coastguard Worker 
1334*e5436536SAndroid Build Coastguard Worker   int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling
1335*e5436536SAndroid Build Coastguard Worker                               terms*/
1336*e5436536SAndroid Build Coastguard Worker   int xoverOffset = highBandStartSb -
1337*e5436536SAndroid Build Coastguard Worker                     lsb; /* Calculate distance in QMF bands between k0 and kx */
1338*e5436536SAndroid Build Coastguard Worker   int startFreqHz;
1339*e5436536SAndroid Build Coastguard Worker 
1340*e5436536SAndroid Build Coastguard Worker   int desiredBorder;
1341*e5436536SAndroid Build Coastguard Worker 
1342*e5436536SAndroid Build Coastguard Worker   usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with
1343*e5436536SAndroid Build Coastguard Worker                                                float code). */
1344*e5436536SAndroid Build Coastguard Worker 
1345*e5436536SAndroid Build Coastguard Worker   /*
1346*e5436536SAndroid Build Coastguard Worker    * Plausibility check
1347*e5436536SAndroid Build Coastguard Worker    */
1348*e5436536SAndroid Build Coastguard Worker 
1349*e5436536SAndroid Build Coastguard Worker   if (pSettings->nCols == 64) {
1350*e5436536SAndroid Build Coastguard Worker     if (lsb < 4) {
1351*e5436536SAndroid Build Coastguard Worker       /* 4:1 SBR Requirement k0 >= 4 missed! */
1352*e5436536SAndroid Build Coastguard Worker       return SBRDEC_UNSUPPORTED_CONFIG;
1353*e5436536SAndroid Build Coastguard Worker     }
1354*e5436536SAndroid Build Coastguard Worker   } else if (lsb - SHIFT_START_SB < 4) {
1355*e5436536SAndroid Build Coastguard Worker     return SBRDEC_UNSUPPORTED_CONFIG;
1356*e5436536SAndroid Build Coastguard Worker   }
1357*e5436536SAndroid Build Coastguard Worker 
1358*e5436536SAndroid Build Coastguard Worker   /*
1359*e5436536SAndroid Build Coastguard Worker    * Initialize the patching parameter
1360*e5436536SAndroid Build Coastguard Worker    */
1361*e5436536SAndroid Build Coastguard Worker   /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */
1362*e5436536SAndroid Build Coastguard Worker   desiredBorder = (((2048000 * 2) / fs) + 1) >> 1;
1363*e5436536SAndroid Build Coastguard Worker 
1364*e5436536SAndroid Build Coastguard Worker   desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster,
1365*e5436536SAndroid Build Coastguard Worker                                    1); /* Adapt region to master-table */
1366*e5436536SAndroid Build Coastguard Worker 
1367*e5436536SAndroid Build Coastguard Worker   /* First patch */
1368*e5436536SAndroid Build Coastguard Worker   sourceStartBand = SHIFT_START_SB + xoverOffset;
1369*e5436536SAndroid Build Coastguard Worker   targetStopBand = lsb + xoverOffset; /* upperBand */
1370*e5436536SAndroid Build Coastguard Worker 
1371*e5436536SAndroid Build Coastguard Worker   /* Even (odd) numbered channel must be patched to even (odd) numbered channel
1372*e5436536SAndroid Build Coastguard Worker    */
1373*e5436536SAndroid Build Coastguard Worker   patch = 0;
1374*e5436536SAndroid Build Coastguard Worker   while (targetStopBand < usb) {
1375*e5436536SAndroid Build Coastguard Worker     /* Too many patches?
1376*e5436536SAndroid Build Coastguard Worker        Allow MAX_NUM_PATCHES+1 patches here.
1377*e5436536SAndroid Build Coastguard Worker        we need to check later again, since patch might be the highest patch
1378*e5436536SAndroid Build Coastguard Worker        AND contain less than 3 bands => actual number of patches will be reduced
1379*e5436536SAndroid Build Coastguard Worker        by 1.
1380*e5436536SAndroid Build Coastguard Worker     */
1381*e5436536SAndroid Build Coastguard Worker     if (patch > MAX_NUM_PATCHES) {
1382*e5436536SAndroid Build Coastguard Worker       return SBRDEC_UNSUPPORTED_CONFIG;
1383*e5436536SAndroid Build Coastguard Worker     }
1384*e5436536SAndroid Build Coastguard Worker 
1385*e5436536SAndroid Build Coastguard Worker     patchParam[patch].guardStartBand = targetStopBand;
1386*e5436536SAndroid Build Coastguard Worker     patchParam[patch].targetStartBand = targetStopBand;
1387*e5436536SAndroid Build Coastguard Worker 
1388*e5436536SAndroid Build Coastguard Worker     numBandsInPatch =
1389*e5436536SAndroid Build Coastguard Worker         desiredBorder - targetStopBand; /* Get the desired range of the patch */
1390*e5436536SAndroid Build Coastguard Worker 
1391*e5436536SAndroid Build Coastguard Worker     if (numBandsInPatch >= lsb - sourceStartBand) {
1392*e5436536SAndroid Build Coastguard Worker       /* Desired number bands are not available -> patch whole source range */
1393*e5436536SAndroid Build Coastguard Worker       patchDistance =
1394*e5436536SAndroid Build Coastguard Worker           targetStopBand - sourceStartBand; /* Get the targetOffset */
1395*e5436536SAndroid Build Coastguard Worker       patchDistance =
1396*e5436536SAndroid Build Coastguard Worker           patchDistance & ~1; /* Rounding off odd numbers and make all even */
1397*e5436536SAndroid Build Coastguard Worker       numBandsInPatch =
1398*e5436536SAndroid Build Coastguard Worker           lsb - (targetStopBand -
1399*e5436536SAndroid Build Coastguard Worker                  patchDistance); /* Update number of bands to be patched */
1400*e5436536SAndroid Build Coastguard Worker       numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch,
1401*e5436536SAndroid Build Coastguard Worker                                          v_k_master, numMaster, 0) -
1402*e5436536SAndroid Build Coastguard Worker                         targetStopBand; /* Adapt region to master-table */
1403*e5436536SAndroid Build Coastguard Worker     }
1404*e5436536SAndroid Build Coastguard Worker 
1405*e5436536SAndroid Build Coastguard Worker     if (pSettings->nCols == 64) {
1406*e5436536SAndroid Build Coastguard Worker       if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) {
1407*e5436536SAndroid Build Coastguard Worker         return SBRDEC_UNSUPPORTED_CONFIG;
1408*e5436536SAndroid Build Coastguard Worker       }
1409*e5436536SAndroid Build Coastguard Worker     }
1410*e5436536SAndroid Build Coastguard Worker 
1411*e5436536SAndroid Build Coastguard Worker     /* Desired number bands are available -> get the minimal even patching
1412*e5436536SAndroid Build Coastguard Worker      * distance */
1413*e5436536SAndroid Build Coastguard Worker     patchDistance =
1414*e5436536SAndroid Build Coastguard Worker         numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */
1415*e5436536SAndroid Build Coastguard Worker     patchDistance = (patchDistance + 1) &
1416*e5436536SAndroid Build Coastguard Worker                     ~1; /* Rounding up odd numbers and make all even */
1417*e5436536SAndroid Build Coastguard Worker 
1418*e5436536SAndroid Build Coastguard Worker     if (numBandsInPatch > 0) {
1419*e5436536SAndroid Build Coastguard Worker       patchParam[patch].sourceStartBand = targetStopBand - patchDistance;
1420*e5436536SAndroid Build Coastguard Worker       patchParam[patch].targetBandOffs = patchDistance;
1421*e5436536SAndroid Build Coastguard Worker       patchParam[patch].numBandsInPatch = numBandsInPatch;
1422*e5436536SAndroid Build Coastguard Worker       patchParam[patch].sourceStopBand =
1423*e5436536SAndroid Build Coastguard Worker           patchParam[patch].sourceStartBand + numBandsInPatch;
1424*e5436536SAndroid Build Coastguard Worker 
1425*e5436536SAndroid Build Coastguard Worker       targetStopBand += patchParam[patch].numBandsInPatch;
1426*e5436536SAndroid Build Coastguard Worker       patch++;
1427*e5436536SAndroid Build Coastguard Worker     }
1428*e5436536SAndroid Build Coastguard Worker 
1429*e5436536SAndroid Build Coastguard Worker     /* All patches but first */
1430*e5436536SAndroid Build Coastguard Worker     sourceStartBand = SHIFT_START_SB;
1431*e5436536SAndroid Build Coastguard Worker 
1432*e5436536SAndroid Build Coastguard Worker     /* Check if we are close to desiredBorder */
1433*e5436536SAndroid Build Coastguard Worker     if (desiredBorder - targetStopBand < 3) /* MPEG doc */
1434*e5436536SAndroid Build Coastguard Worker     {
1435*e5436536SAndroid Build Coastguard Worker       desiredBorder = usb;
1436*e5436536SAndroid Build Coastguard Worker     }
1437*e5436536SAndroid Build Coastguard Worker   }
1438*e5436536SAndroid Build Coastguard Worker 
1439*e5436536SAndroid Build Coastguard Worker   patch--;
1440*e5436536SAndroid Build Coastguard Worker 
1441*e5436536SAndroid Build Coastguard Worker   /* If highest patch contains less than three subband: skip it */
1442*e5436536SAndroid Build Coastguard Worker   if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) {
1443*e5436536SAndroid Build Coastguard Worker     patch--;
1444*e5436536SAndroid Build Coastguard Worker     targetStopBand =
1445*e5436536SAndroid Build Coastguard Worker         patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch;
1446*e5436536SAndroid Build Coastguard Worker   }
1447*e5436536SAndroid Build Coastguard Worker 
1448*e5436536SAndroid Build Coastguard Worker   /* now check if we don't have one too many */
1449*e5436536SAndroid Build Coastguard Worker   if (patch >= MAX_NUM_PATCHES) {
1450*e5436536SAndroid Build Coastguard Worker     return SBRDEC_UNSUPPORTED_CONFIG;
1451*e5436536SAndroid Build Coastguard Worker   }
1452*e5436536SAndroid Build Coastguard Worker 
1453*e5436536SAndroid Build Coastguard Worker   pSettings->noOfPatches = patch + 1;
1454*e5436536SAndroid Build Coastguard Worker 
1455*e5436536SAndroid Build Coastguard Worker   /* Check lowest and highest source subband */
1456*e5436536SAndroid Build Coastguard Worker   pSettings->lbStartPatching = targetStopBand;
1457*e5436536SAndroid Build Coastguard Worker   pSettings->lbStopPatching = 0;
1458*e5436536SAndroid Build Coastguard Worker   for (patch = 0; patch < pSettings->noOfPatches; patch++) {
1459*e5436536SAndroid Build Coastguard Worker     pSettings->lbStartPatching =
1460*e5436536SAndroid Build Coastguard Worker         fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand);
1461*e5436536SAndroid Build Coastguard Worker     pSettings->lbStopPatching =
1462*e5436536SAndroid Build Coastguard Worker         fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand);
1463*e5436536SAndroid Build Coastguard Worker   }
1464*e5436536SAndroid Build Coastguard Worker 
1465*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < noNoiseBands; i++) {
1466*e5436536SAndroid Build Coastguard Worker     pSettings->bwBorders[i] = noiseBandTable[i + 1];
1467*e5436536SAndroid Build Coastguard Worker   }
1468*e5436536SAndroid Build Coastguard Worker   for (; i < MAX_NUM_NOISE_VALUES; i++) {
1469*e5436536SAndroid Build Coastguard Worker     pSettings->bwBorders[i] = 255;
1470*e5436536SAndroid Build Coastguard Worker   }
1471*e5436536SAndroid Build Coastguard Worker 
1472*e5436536SAndroid Build Coastguard Worker   /*
1473*e5436536SAndroid Build Coastguard Worker    * Choose whitening factors
1474*e5436536SAndroid Build Coastguard Worker    */
1475*e5436536SAndroid Build Coastguard Worker 
1476*e5436536SAndroid Build Coastguard Worker   startFreqHz =
1477*e5436536SAndroid Build Coastguard Worker       ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */
1478*e5436536SAndroid Build Coastguard Worker 
1479*e5436536SAndroid Build Coastguard Worker   for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) {
1480*e5436536SAndroid Build Coastguard Worker     if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break;
1481*e5436536SAndroid Build Coastguard Worker   }
1482*e5436536SAndroid Build Coastguard Worker   i--;
1483*e5436536SAndroid Build Coastguard Worker 
1484*e5436536SAndroid Build Coastguard Worker   pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0];
1485*e5436536SAndroid Build Coastguard Worker   pSettings->whFactors.transitionLevel =
1486*e5436536SAndroid Build Coastguard Worker       FDK_sbrDecoder_sbr_whFactorsTable[i][1];
1487*e5436536SAndroid Build Coastguard Worker   pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2];
1488*e5436536SAndroid Build Coastguard Worker   pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3];
1489*e5436536SAndroid Build Coastguard Worker   pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4];
1490*e5436536SAndroid Build Coastguard Worker 
1491*e5436536SAndroid Build Coastguard Worker   return SBRDEC_OK;
1492*e5436536SAndroid Build Coastguard Worker }
1493