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