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 - 2020 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 Sbr decoder
106*e5436536SAndroid Build Coastguard Worker This module provides the actual decoder implementation. The SBR data (side
107*e5436536SAndroid Build Coastguard Worker information) is already decoded. Only three functions are provided:
108*e5436536SAndroid Build Coastguard Worker
109*e5436536SAndroid Build Coastguard Worker \li 1.) createSbrDec(): One time initialization
110*e5436536SAndroid Build Coastguard Worker \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in
111*e5436536SAndroid Build Coastguard Worker an SBR_HEADER_ELEMENT requires a reset and recalculation of important SBR
112*e5436536SAndroid Build Coastguard Worker structures. \li 3.) sbr_dec(): The actual decoder. Calls the different tools
113*e5436536SAndroid Build Coastguard Worker such as filterbanks, lppTransposer(), and calculateSbrEnvelope() [the envelope
114*e5436536SAndroid Build Coastguard Worker adjuster].
115*e5436536SAndroid Build Coastguard Worker
116*e5436536SAndroid Build Coastguard Worker \sa sbr_dec(), \ref documentationOverview
117*e5436536SAndroid Build Coastguard Worker */
118*e5436536SAndroid Build Coastguard Worker
119*e5436536SAndroid Build Coastguard Worker #include "sbr_dec.h"
120*e5436536SAndroid Build Coastguard Worker
121*e5436536SAndroid Build Coastguard Worker #include "sbr_ram.h"
122*e5436536SAndroid Build Coastguard Worker #include "env_extr.h"
123*e5436536SAndroid Build Coastguard Worker #include "env_calc.h"
124*e5436536SAndroid Build Coastguard Worker #include "scale.h"
125*e5436536SAndroid Build Coastguard Worker #include "FDK_matrixCalloc.h"
126*e5436536SAndroid Build Coastguard Worker #include "hbe.h"
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
129*e5436536SAndroid Build Coastguard Worker
130*e5436536SAndroid Build Coastguard Worker #include "sbrdec_drc.h"
131*e5436536SAndroid Build Coastguard Worker
copyHarmonicSpectrum(int * xOverQmf,FIXP_DBL ** qmfReal,FIXP_DBL ** qmfImag,int noCols,int overlap,KEEP_STATES_SYNCED_MODE keepStatesSynced)132*e5436536SAndroid Build Coastguard Worker static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal,
133*e5436536SAndroid Build Coastguard Worker FIXP_DBL **qmfImag, int noCols, int overlap,
134*e5436536SAndroid Build Coastguard Worker KEEP_STATES_SYNCED_MODE keepStatesSynced) {
135*e5436536SAndroid Build Coastguard Worker int patchBands;
136*e5436536SAndroid Build Coastguard Worker int patch, band, col, target, sourceBands, i;
137*e5436536SAndroid Build Coastguard Worker int numPatches = 0;
138*e5436536SAndroid Build Coastguard Worker int slotOffset = 0;
139*e5436536SAndroid Build Coastguard Worker
140*e5436536SAndroid Build Coastguard Worker FIXP_DBL **ppqmfReal = qmfReal + overlap;
141*e5436536SAndroid Build Coastguard Worker FIXP_DBL **ppqmfImag = qmfImag + overlap;
142*e5436536SAndroid Build Coastguard Worker
143*e5436536SAndroid Build Coastguard Worker if (keepStatesSynced == KEEP_STATES_SYNCED_NORMAL) {
144*e5436536SAndroid Build Coastguard Worker slotOffset = noCols - overlap - LPC_ORDER;
145*e5436536SAndroid Build Coastguard Worker }
146*e5436536SAndroid Build Coastguard Worker
147*e5436536SAndroid Build Coastguard Worker if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) {
148*e5436536SAndroid Build Coastguard Worker ppqmfReal = qmfReal;
149*e5436536SAndroid Build Coastguard Worker ppqmfImag = qmfImag;
150*e5436536SAndroid Build Coastguard Worker }
151*e5436536SAndroid Build Coastguard Worker
152*e5436536SAndroid Build Coastguard Worker for (i = 1; i < MAX_NUM_PATCHES; i++) {
153*e5436536SAndroid Build Coastguard Worker if (xOverQmf[i] != 0) {
154*e5436536SAndroid Build Coastguard Worker numPatches++;
155*e5436536SAndroid Build Coastguard Worker }
156*e5436536SAndroid Build Coastguard Worker }
157*e5436536SAndroid Build Coastguard Worker
158*e5436536SAndroid Build Coastguard Worker for (patch = (MAX_STRETCH_HBE - 1); patch < numPatches; patch++) {
159*e5436536SAndroid Build Coastguard Worker patchBands = xOverQmf[patch + 1] - xOverQmf[patch];
160*e5436536SAndroid Build Coastguard Worker target = xOverQmf[patch];
161*e5436536SAndroid Build Coastguard Worker sourceBands = xOverQmf[MAX_STRETCH_HBE - 1] - xOverQmf[MAX_STRETCH_HBE - 2];
162*e5436536SAndroid Build Coastguard Worker
163*e5436536SAndroid Build Coastguard Worker while (patchBands > 0) {
164*e5436536SAndroid Build Coastguard Worker int numBands = sourceBands;
165*e5436536SAndroid Build Coastguard Worker int startBand = xOverQmf[MAX_STRETCH_HBE - 1] - 1;
166*e5436536SAndroid Build Coastguard Worker if (target + numBands >= xOverQmf[patch + 1]) {
167*e5436536SAndroid Build Coastguard Worker numBands = xOverQmf[patch + 1] - target;
168*e5436536SAndroid Build Coastguard Worker }
169*e5436536SAndroid Build Coastguard Worker if ((((target + numBands - 1) % 2) +
170*e5436536SAndroid Build Coastguard Worker ((xOverQmf[MAX_STRETCH_HBE - 1] - 1) % 2)) %
171*e5436536SAndroid Build Coastguard Worker 2) {
172*e5436536SAndroid Build Coastguard Worker if (numBands == sourceBands) {
173*e5436536SAndroid Build Coastguard Worker numBands--;
174*e5436536SAndroid Build Coastguard Worker } else {
175*e5436536SAndroid Build Coastguard Worker startBand--;
176*e5436536SAndroid Build Coastguard Worker }
177*e5436536SAndroid Build Coastguard Worker }
178*e5436536SAndroid Build Coastguard Worker if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) {
179*e5436536SAndroid Build Coastguard Worker for (col = slotOffset; col < overlap + LPC_ORDER; col++) {
180*e5436536SAndroid Build Coastguard Worker i = 0;
181*e5436536SAndroid Build Coastguard Worker for (band = numBands; band > 0; band--) {
182*e5436536SAndroid Build Coastguard Worker if ((target + band - 1 < 64) &&
183*e5436536SAndroid Build Coastguard Worker (target + band - 1 < xOverQmf[patch + 1])) {
184*e5436536SAndroid Build Coastguard Worker ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i];
185*e5436536SAndroid Build Coastguard Worker ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i];
186*e5436536SAndroid Build Coastguard Worker i++;
187*e5436536SAndroid Build Coastguard Worker }
188*e5436536SAndroid Build Coastguard Worker }
189*e5436536SAndroid Build Coastguard Worker }
190*e5436536SAndroid Build Coastguard Worker } else {
191*e5436536SAndroid Build Coastguard Worker for (col = slotOffset; col < noCols; col++) {
192*e5436536SAndroid Build Coastguard Worker i = 0;
193*e5436536SAndroid Build Coastguard Worker for (band = numBands; band > 0; band--) {
194*e5436536SAndroid Build Coastguard Worker if ((target + band - 1 < 64) &&
195*e5436536SAndroid Build Coastguard Worker (target + band - 1 < xOverQmf[patch + 1])) {
196*e5436536SAndroid Build Coastguard Worker ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i];
197*e5436536SAndroid Build Coastguard Worker ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i];
198*e5436536SAndroid Build Coastguard Worker i++;
199*e5436536SAndroid Build Coastguard Worker }
200*e5436536SAndroid Build Coastguard Worker }
201*e5436536SAndroid Build Coastguard Worker }
202*e5436536SAndroid Build Coastguard Worker }
203*e5436536SAndroid Build Coastguard Worker target += numBands;
204*e5436536SAndroid Build Coastguard Worker patchBands -= numBands;
205*e5436536SAndroid Build Coastguard Worker }
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 \brief SBR decoder core function for one channel
211*e5436536SAndroid Build Coastguard Worker
212*e5436536SAndroid Build Coastguard Worker \image html BufferMgmtDetailed-1632.png
213*e5436536SAndroid Build Coastguard Worker
214*e5436536SAndroid Build Coastguard Worker Besides the filter states of the QMF filter bank and the LPC-states of
215*e5436536SAndroid Build Coastguard Worker the LPP-Transposer, processing is mainly based on four buffers:
216*e5436536SAndroid Build Coastguard Worker #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2
217*e5436536SAndroid Build Coastguard Worker is reused for all channels and might be used by the core decoder, a
218*e5436536SAndroid Build Coastguard Worker static overlap buffer is required for each channel. Due to in-place
219*e5436536SAndroid Build Coastguard Worker processing, #timeIn and #timeOut point to identical locations.
220*e5436536SAndroid Build Coastguard Worker
221*e5436536SAndroid Build Coastguard Worker The spectral data is organized in so-called slots. Each slot
222*e5436536SAndroid Build Coastguard Worker contains 64 bands of complex data. The number of slots per frame
223*e5436536SAndroid Build Coastguard Worker depends on the frame size. For mp3PRO, there are 18 slots per frame
224*e5436536SAndroid Build Coastguard Worker and 6 slots per #OverlapBuffer. It is not necessary to have the slots
225*e5436536SAndroid Build Coastguard Worker in located consecutive address ranges.
226*e5436536SAndroid Build Coastguard Worker
227*e5436536SAndroid Build Coastguard Worker To optimize memory usage and to minimize the number of memory
228*e5436536SAndroid Build Coastguard Worker accesses, the memory management is organized as follows (slot numbers
229*e5436536SAndroid Build Coastguard Worker based on mp3PRO):
230*e5436536SAndroid Build Coastguard Worker
231*e5436536SAndroid Build Coastguard Worker 1.) Input time domain signal is located in #timeIn. The last slots
232*e5436536SAndroid Build Coastguard Worker (0..5) of the spectral data of the previous frame are located in the
233*e5436536SAndroid Build Coastguard Worker #OverlapBuffer. In addition, #frameData of the current frame resides
234*e5436536SAndroid Build Coastguard Worker in the upper part of #timeIn.
235*e5436536SAndroid Build Coastguard Worker
236*e5436536SAndroid Build Coastguard Worker 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are
237*e5436536SAndroid Build Coastguard Worker transformed into a slot of up to 32 complex spectral low band values at a
238*e5436536SAndroid Build Coastguard Worker time. The first spectral slot -- nr. 6 -- is written at slot number
239*e5436536SAndroid Build Coastguard Worker zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with
240*e5436536SAndroid Build Coastguard Worker spectral data.
241*e5436536SAndroid Build Coastguard Worker
242*e5436536SAndroid Build Coastguard Worker 3.) LPP-Transposition in lppTransposer() is processed on 24 slots. During the
243*e5436536SAndroid Build Coastguard Worker transposition, the high band part of the spectral data is replicated
244*e5436536SAndroid Build Coastguard Worker based on the low band data.
245*e5436536SAndroid Build Coastguard Worker
246*e5436536SAndroid Build Coastguard Worker Envelope Adjustment is processed on the high band part of the spectral
247*e5436536SAndroid Build Coastguard Worker data only by calculateSbrEnvelope().
248*e5436536SAndroid Build Coastguard Worker
249*e5436536SAndroid Build Coastguard Worker 4.) The cplxSynthesisQmfFiltering() creates 64 time domain samples out
250*e5436536SAndroid Build Coastguard Worker of a slot of 64 complex spectral values at a time. The first 6 slots
251*e5436536SAndroid Build Coastguard Worker in #timeOut are filled from the results of spectral slots 0..5 in the
252*e5436536SAndroid Build Coastguard Worker #OverlapBuffer. The consecutive slots in timeOut are now filled with
253*e5436536SAndroid Build Coastguard Worker the results of spectral slots 6..17.
254*e5436536SAndroid Build Coastguard Worker
255*e5436536SAndroid Build Coastguard Worker 5.) The preprocessed slots 18..23 have to be stored in the
256*e5436536SAndroid Build Coastguard Worker #OverlapBuffer.
257*e5436536SAndroid Build Coastguard Worker
258*e5436536SAndroid Build Coastguard Worker */
259*e5436536SAndroid Build Coastguard Worker
sbr_dec(HANDLE_SBR_DEC hSbrDec,LONG * timeIn,LONG * timeOut,HANDLE_SBR_DEC hSbrDecRight,LONG * timeOutRight,const int strideOut,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA hFrameData,HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,const int applyProcessing,HANDLE_PS_DEC h_ps_d,const UINT flags,const int codecFrameSize,const INT sbrInDataHeadroom)260*e5436536SAndroid Build Coastguard Worker void sbr_dec(
261*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
262*e5436536SAndroid Build Coastguard Worker LONG *timeIn, /*!< pointer to input time signal */
263*e5436536SAndroid Build Coastguard Worker LONG *timeOut, /*!< pointer to output time signal */
264*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */
265*e5436536SAndroid Build Coastguard Worker LONG *timeOutRight, /*!< pointer to output time signal */
266*e5436536SAndroid Build Coastguard Worker const int strideOut, /*!< Time data traversal strideOut */
267*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
268*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */
269*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_PREV_FRAME_DATA
270*e5436536SAndroid Build Coastguard Worker hPrevFrameData, /*!< Some control data of last frame */
271*e5436536SAndroid Build Coastguard Worker const int applyProcessing, /*!< Flag for SBR operation */
272*e5436536SAndroid Build Coastguard Worker HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize,
273*e5436536SAndroid Build Coastguard Worker const INT sbrInDataHeadroom) {
274*e5436536SAndroid Build Coastguard Worker int i, slot, reserve;
275*e5436536SAndroid Build Coastguard Worker int saveLbScale;
276*e5436536SAndroid Build Coastguard Worker int lastSlotOffs;
277*e5436536SAndroid Build Coastguard Worker FIXP_DBL maxVal;
278*e5436536SAndroid Build Coastguard Worker
279*e5436536SAndroid Build Coastguard Worker /* temporary pointer / variable for QMF;
280*e5436536SAndroid Build Coastguard Worker required as we want to use temporary buffer
281*e5436536SAndroid Build Coastguard Worker creating one frame delay for HBE in LP mode */
282*e5436536SAndroid Build Coastguard Worker LONG *pTimeInQmf = timeIn;
283*e5436536SAndroid Build Coastguard Worker
284*e5436536SAndroid Build Coastguard Worker /* Number of QMF timeslots in the overlap buffer: */
285*e5436536SAndroid Build Coastguard Worker int ov_len = hSbrDec->LppTrans.pSettings->overlap;
286*e5436536SAndroid Build Coastguard Worker
287*e5436536SAndroid Build Coastguard Worker /* Number of QMF slots per frame */
288*e5436536SAndroid Build Coastguard Worker int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep;
289*e5436536SAndroid Build Coastguard Worker
290*e5436536SAndroid Build Coastguard Worker /* create pointer array for data to use for HBE and legacy sbr */
291*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pLowBandReal[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)];
292*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pLowBandImag[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)];
293*e5436536SAndroid Build Coastguard Worker
294*e5436536SAndroid Build Coastguard Worker /* set pReal to where QMF analysis writes in case of legacy SBR */
295*e5436536SAndroid Build Coastguard Worker FIXP_DBL **pReal = pLowBandReal + ov_len;
296*e5436536SAndroid Build Coastguard Worker FIXP_DBL **pImag = pLowBandImag + ov_len;
297*e5436536SAndroid Build Coastguard Worker
298*e5436536SAndroid Build Coastguard Worker /* map QMF buffer to pointer array (Overlap + Frame)*/
299*e5436536SAndroid Build Coastguard Worker for (i = 0; i < noCols + ov_len; i++) {
300*e5436536SAndroid Build Coastguard Worker pLowBandReal[i] = hSbrDec->qmfDomainInCh->hQmfSlotsReal[i];
301*e5436536SAndroid Build Coastguard Worker pLowBandImag[i] = hSbrDec->qmfDomainInCh->hQmfSlotsImag[i];
302*e5436536SAndroid Build Coastguard Worker }
303*e5436536SAndroid Build Coastguard Worker
304*e5436536SAndroid Build Coastguard Worker if ((flags & SBRDEC_USAC_HARMONICSBR)) {
305*e5436536SAndroid Build Coastguard Worker /* in case of harmonic SBR and no HBE_LP map additional buffer for
306*e5436536SAndroid Build Coastguard Worker one more frame to pointer arry */
307*e5436536SAndroid Build Coastguard Worker for (i = 0; i < noCols; i++) {
308*e5436536SAndroid Build Coastguard Worker pLowBandReal[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsReal[i];
309*e5436536SAndroid Build Coastguard Worker pLowBandImag[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsImag[i];
310*e5436536SAndroid Build Coastguard Worker }
311*e5436536SAndroid Build Coastguard Worker
312*e5436536SAndroid Build Coastguard Worker /* shift scale values according to buffer */
313*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_ov = hSbrDec->scale_lb;
314*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_lb = hSbrDec->scale_hbe;
315*e5436536SAndroid Build Coastguard Worker
316*e5436536SAndroid Build Coastguard Worker /* set pReal to where QMF analysis writes in case of HBE */
317*e5436536SAndroid Build Coastguard Worker pReal += noCols;
318*e5436536SAndroid Build Coastguard Worker pImag += noCols;
319*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_SKIP_QMF_ANA) {
320*e5436536SAndroid Build Coastguard Worker /* stereoCfgIndex3 with HBE */
321*e5436536SAndroid Build Coastguard Worker FDK_QmfDomain_QmfData2HBE(hSbrDec->qmfDomainInCh,
322*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsReal,
323*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsImag);
324*e5436536SAndroid Build Coastguard Worker } else {
325*e5436536SAndroid Build Coastguard Worker /* We have to move old hbe frame data to lb area of buffer */
326*e5436536SAndroid Build Coastguard Worker for (i = 0; i < noCols; i++) {
327*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pLowBandReal[ov_len + i], hSbrDec->hQmfHBESlotsReal[i],
328*e5436536SAndroid Build Coastguard Worker hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL));
329*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pLowBandImag[ov_len + i], hSbrDec->hQmfHBESlotsImag[i],
330*e5436536SAndroid Build Coastguard Worker hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL));
331*e5436536SAndroid Build Coastguard Worker }
332*e5436536SAndroid Build Coastguard Worker }
333*e5436536SAndroid Build Coastguard Worker }
334*e5436536SAndroid Build Coastguard Worker
335*e5436536SAndroid Build Coastguard Worker /*
336*e5436536SAndroid Build Coastguard Worker low band codec signal subband filtering
337*e5436536SAndroid Build Coastguard Worker */
338*e5436536SAndroid Build Coastguard Worker
339*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_SKIP_QMF_ANA) {
340*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_USAC_HARMONICSBR)) /* stereoCfgIndex3 w/o HBE */
341*e5436536SAndroid Build Coastguard Worker FDK_QmfDomain_WorkBuffer2ProcChannel(hSbrDec->qmfDomainInCh);
342*e5436536SAndroid Build Coastguard Worker } else {
343*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64));
344*e5436536SAndroid Build Coastguard Worker qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag,
345*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf,
346*e5436536SAndroid Build Coastguard Worker 0 + sbrInDataHeadroom, 1, qmfTemp);
347*e5436536SAndroid Build Coastguard Worker
348*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64));
349*e5436536SAndroid Build Coastguard Worker }
350*e5436536SAndroid Build Coastguard Worker
351*e5436536SAndroid Build Coastguard Worker /*
352*e5436536SAndroid Build Coastguard Worker Clear upper half of spectrum
353*e5436536SAndroid Build Coastguard Worker */
354*e5436536SAndroid Build Coastguard Worker if (!((flags & SBRDEC_USAC_HARMONICSBR) &&
355*e5436536SAndroid Build Coastguard Worker (hFrameData->sbrPatchingMode == 0))) {
356*e5436536SAndroid Build Coastguard Worker int nAnalysisBands = hHeaderData->numberOfAnalysisBands;
357*e5436536SAndroid Build Coastguard Worker
358*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_LOW_POWER)) {
359*e5436536SAndroid Build Coastguard Worker for (slot = ov_len; slot < noCols + ov_len; slot++) {
360*e5436536SAndroid Build Coastguard Worker FDKmemclear(&pLowBandReal[slot][nAnalysisBands],
361*e5436536SAndroid Build Coastguard Worker ((64) - nAnalysisBands) * sizeof(FIXP_DBL));
362*e5436536SAndroid Build Coastguard Worker FDKmemclear(&pLowBandImag[slot][nAnalysisBands],
363*e5436536SAndroid Build Coastguard Worker ((64) - nAnalysisBands) * sizeof(FIXP_DBL));
364*e5436536SAndroid Build Coastguard Worker }
365*e5436536SAndroid Build Coastguard Worker } else {
366*e5436536SAndroid Build Coastguard Worker for (slot = ov_len; slot < noCols + ov_len; slot++) {
367*e5436536SAndroid Build Coastguard Worker FDKmemclear(&pLowBandReal[slot][nAnalysisBands],
368*e5436536SAndroid Build Coastguard Worker ((64) - nAnalysisBands) * sizeof(FIXP_DBL));
369*e5436536SAndroid Build Coastguard Worker }
370*e5436536SAndroid Build Coastguard Worker }
371*e5436536SAndroid Build Coastguard Worker }
372*e5436536SAndroid Build Coastguard Worker
373*e5436536SAndroid Build Coastguard Worker /*
374*e5436536SAndroid Build Coastguard Worker Shift spectral data left to gain accuracy in transposer and adjustor
375*e5436536SAndroid Build Coastguard Worker */
376*e5436536SAndroid Build Coastguard Worker /* Range was increased from lsb to no_channels because in some cases (e.g.
377*e5436536SAndroid Build Coastguard Worker USAC conf eSbr_4_Pvc.mp4 and some HBE cases) it could be observed that the
378*e5436536SAndroid Build Coastguard Worker signal between lsb and no_channels is used for the patching process.
379*e5436536SAndroid Build Coastguard Worker */
380*e5436536SAndroid Build Coastguard Worker maxVal = maxSubbandSample(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0,
381*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols);
382*e5436536SAndroid Build Coastguard Worker
383*e5436536SAndroid Build Coastguard Worker reserve = fixMax(0, CntLeadingZeros(maxVal) - 1);
384*e5436536SAndroid Build Coastguard Worker reserve = fixMin(reserve,
385*e5436536SAndroid Build Coastguard Worker DFRACT_BITS - 1 - hSbrDec->qmfDomainInCh->scaling.lb_scale);
386*e5436536SAndroid Build Coastguard Worker
387*e5436536SAndroid Build Coastguard Worker /* If all data is zero, lb_scale could become too large */
388*e5436536SAndroid Build Coastguard Worker rescaleSubbandSamples(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0,
389*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols,
390*e5436536SAndroid Build Coastguard Worker reserve);
391*e5436536SAndroid Build Coastguard Worker
392*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.lb_scale += reserve;
393*e5436536SAndroid Build Coastguard Worker
394*e5436536SAndroid Build Coastguard Worker if ((flags & SBRDEC_USAC_HARMONICSBR)) {
395*e5436536SAndroid Build Coastguard Worker /* actually this is our hbe_scale */
396*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_hbe = hSbrDec->qmfDomainInCh->scaling.lb_scale;
397*e5436536SAndroid Build Coastguard Worker /* the real lb_scale is stored in scale_lb from sbr */
398*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.lb_scale = hSbrDec->scale_lb;
399*e5436536SAndroid Build Coastguard Worker }
400*e5436536SAndroid Build Coastguard Worker /*
401*e5436536SAndroid Build Coastguard Worker save low band scale, wavecoding or parametric stereo may modify it
402*e5436536SAndroid Build Coastguard Worker */
403*e5436536SAndroid Build Coastguard Worker saveLbScale = hSbrDec->qmfDomainInCh->scaling.lb_scale;
404*e5436536SAndroid Build Coastguard Worker
405*e5436536SAndroid Build Coastguard Worker if (applyProcessing) {
406*e5436536SAndroid Build Coastguard Worker UCHAR *borders = hFrameData->frameInfo.borders;
407*e5436536SAndroid Build Coastguard Worker lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] -
408*e5436536SAndroid Build Coastguard Worker hHeaderData->numberTimeSlots;
409*e5436536SAndroid Build Coastguard Worker
410*e5436536SAndroid Build Coastguard Worker FIXP_DBL degreeAlias[(64)];
411*e5436536SAndroid Build Coastguard Worker PVC_DYNAMIC_DATA pvcDynamicData;
412*e5436536SAndroid Build Coastguard Worker pvcInitFrame(
413*e5436536SAndroid Build Coastguard Worker &hSbrDec->PvcStaticData, &pvcDynamicData,
414*e5436536SAndroid Build Coastguard Worker (hHeaderData->frameErrorFlag ? 0 : hHeaderData->bs_info.pvc_mode),
415*e5436536SAndroid Build Coastguard Worker hFrameData->ns, hHeaderData->timeStep,
416*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.lowSubband,
417*e5436536SAndroid Build Coastguard Worker hFrameData->frameInfo.pvcBorders[0], hFrameData->pvcID);
418*e5436536SAndroid Build Coastguard Worker
419*e5436536SAndroid Build Coastguard Worker if (!hHeaderData->frameErrorFlag && (hHeaderData->bs_info.pvc_mode > 0)) {
420*e5436536SAndroid Build Coastguard Worker pvcDecodeFrame(&hSbrDec->PvcStaticData, &pvcDynamicData, pLowBandReal,
421*e5436536SAndroid Build Coastguard Worker pLowBandImag, ov_len,
422*e5436536SAndroid Build Coastguard Worker SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale),
423*e5436536SAndroid Build Coastguard Worker SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale));
424*e5436536SAndroid Build Coastguard Worker }
425*e5436536SAndroid Build Coastguard Worker pvcEndFrame(&hSbrDec->PvcStaticData, &pvcDynamicData);
426*e5436536SAndroid Build Coastguard Worker
427*e5436536SAndroid Build Coastguard Worker /* The transposer will override most values in degreeAlias[].
428*e5436536SAndroid Build Coastguard Worker The array needs to be cleared at least from lowSubband to highSubband
429*e5436536SAndroid Build Coastguard Worker before. */
430*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_LOW_POWER)
431*e5436536SAndroid Build Coastguard Worker FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband],
432*e5436536SAndroid Build Coastguard Worker (hHeaderData->freqBandData.highSubband -
433*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.lowSubband) *
434*e5436536SAndroid Build Coastguard Worker sizeof(FIXP_DBL));
435*e5436536SAndroid Build Coastguard Worker
436*e5436536SAndroid Build Coastguard Worker /*
437*e5436536SAndroid Build Coastguard Worker Inverse filtering of lowband and transposition into the SBR-frequency
438*e5436536SAndroid Build Coastguard Worker range
439*e5436536SAndroid Build Coastguard Worker */
440*e5436536SAndroid Build Coastguard Worker
441*e5436536SAndroid Build Coastguard Worker {
442*e5436536SAndroid Build Coastguard Worker KEEP_STATES_SYNCED_MODE keepStatesSyncedMode =
443*e5436536SAndroid Build Coastguard Worker ((flags & SBRDEC_USAC_HARMONICSBR) &&
444*e5436536SAndroid Build Coastguard Worker (hFrameData->sbrPatchingMode != 0))
445*e5436536SAndroid Build Coastguard Worker ? KEEP_STATES_SYNCED_NORMAL
446*e5436536SAndroid Build Coastguard Worker : KEEP_STATES_SYNCED_OFF;
447*e5436536SAndroid Build Coastguard Worker
448*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_USAC_HARMONICSBR) {
449*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_QUAD_RATE) {
450*e5436536SAndroid Build Coastguard Worker pReal -= 32;
451*e5436536SAndroid Build Coastguard Worker pImag -= 32;
452*e5436536SAndroid Build Coastguard Worker }
453*e5436536SAndroid Build Coastguard Worker
454*e5436536SAndroid Build Coastguard Worker if ((hSbrDec->savedStates == 0) && (hFrameData->sbrPatchingMode == 1)) {
455*e5436536SAndroid Build Coastguard Worker /* copy saved states from previous frame to legacy SBR lpc filterstate
456*e5436536SAndroid Build Coastguard Worker * buffer */
457*e5436536SAndroid Build Coastguard Worker for (i = 0; i < LPC_ORDER + ov_len; i++) {
458*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
459*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i],
460*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferReal[noCols - LPC_ORDER - ov_len + i],
461*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
462*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
463*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i],
464*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferImag[noCols - LPC_ORDER - ov_len + i],
465*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
466*e5436536SAndroid Build Coastguard Worker }
467*e5436536SAndroid Build Coastguard Worker }
468*e5436536SAndroid Build Coastguard Worker
469*e5436536SAndroid Build Coastguard Worker /* saving unmodified QMF states in case we are switching from legacy SBR
470*e5436536SAndroid Build Coastguard Worker * to HBE */
471*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->hHBE->noCols; i++) {
472*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->codecQMFBufferReal[i], pLowBandReal[ov_len + i],
473*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
474*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->codecQMFBufferImag[i], pLowBandImag[ov_len + i],
475*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
476*e5436536SAndroid Build Coastguard Worker }
477*e5436536SAndroid Build Coastguard Worker
478*e5436536SAndroid Build Coastguard Worker QmfTransposerApply(
479*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE, pReal, pImag, noCols, pLowBandReal, pLowBandImag,
480*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealHBE,
481*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagHBE,
482*e5436536SAndroid Build Coastguard Worker hFrameData->sbrPitchInBins, hSbrDec->scale_lb, hSbrDec->scale_hbe,
483*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep,
484*e5436536SAndroid Build Coastguard Worker borders[0], ov_len, keepStatesSyncedMode);
485*e5436536SAndroid Build Coastguard Worker
486*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_QUAD_RATE) {
487*e5436536SAndroid Build Coastguard Worker int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE);
488*e5436536SAndroid Build Coastguard Worker
489*e5436536SAndroid Build Coastguard Worker copyHarmonicSpectrum(xOverQmf, pLowBandReal, pLowBandImag, noCols,
490*e5436536SAndroid Build Coastguard Worker ov_len, keepStatesSyncedMode);
491*e5436536SAndroid Build Coastguard Worker }
492*e5436536SAndroid Build Coastguard Worker }
493*e5436536SAndroid Build Coastguard Worker }
494*e5436536SAndroid Build Coastguard Worker
495*e5436536SAndroid Build Coastguard Worker if ((flags & SBRDEC_USAC_HARMONICSBR) &&
496*e5436536SAndroid Build Coastguard Worker (hFrameData->sbrPatchingMode == 0)) {
497*e5436536SAndroid Build Coastguard Worker hSbrDec->prev_frame_lSbr = 0;
498*e5436536SAndroid Build Coastguard Worker hSbrDec->prev_frame_hbeSbr = 1;
499*e5436536SAndroid Build Coastguard Worker
500*e5436536SAndroid Build Coastguard Worker lppTransposerHBE(
501*e5436536SAndroid Build Coastguard Worker &hSbrDec->LppTrans, hSbrDec->hHBE, &hSbrDec->qmfDomainInCh->scaling,
502*e5436536SAndroid Build Coastguard Worker pLowBandReal, pLowBandImag, hHeaderData->timeStep, borders[0],
503*e5436536SAndroid Build Coastguard Worker lastSlotOffs, hHeaderData->freqBandData.nInvfBands,
504*e5436536SAndroid Build Coastguard Worker hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode);
505*e5436536SAndroid Build Coastguard Worker
506*e5436536SAndroid Build Coastguard Worker } else {
507*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_USAC_HARMONICSBR) {
508*e5436536SAndroid Build Coastguard Worker for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) {
509*e5436536SAndroid Build Coastguard Worker /*
510*e5436536SAndroid Build Coastguard Worker Store the unmodified qmf Slots values for upper part of spectrum
511*e5436536SAndroid Build Coastguard Worker (required for LPC filtering) required if next frame is a HBE frame
512*e5436536SAndroid Build Coastguard Worker */
513*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealHBE[i],
514*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh
515*e5436536SAndroid Build Coastguard Worker ->hQmfSlotsReal[hSbrDec->hHBE->noCols - LPC_ORDER + i],
516*e5436536SAndroid Build Coastguard Worker (64) * sizeof(FIXP_DBL));
517*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagHBE[i],
518*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh
519*e5436536SAndroid Build Coastguard Worker ->hQmfSlotsImag[hSbrDec->hHBE->noCols - LPC_ORDER + i],
520*e5436536SAndroid Build Coastguard Worker (64) * sizeof(FIXP_DBL));
521*e5436536SAndroid Build Coastguard Worker }
522*e5436536SAndroid Build Coastguard Worker }
523*e5436536SAndroid Build Coastguard Worker {
524*e5436536SAndroid Build Coastguard Worker hSbrDec->prev_frame_lSbr = 1;
525*e5436536SAndroid Build Coastguard Worker hSbrDec->prev_frame_hbeSbr = 0;
526*e5436536SAndroid Build Coastguard Worker }
527*e5436536SAndroid Build Coastguard Worker
528*e5436536SAndroid Build Coastguard Worker lppTransposer(
529*e5436536SAndroid Build Coastguard Worker &hSbrDec->LppTrans, &hSbrDec->qmfDomainInCh->scaling, pLowBandReal,
530*e5436536SAndroid Build Coastguard Worker degreeAlias, // only used if useLP = 1
531*e5436536SAndroid Build Coastguard Worker pLowBandImag, flags & SBRDEC_LOW_POWER,
532*e5436536SAndroid Build Coastguard Worker hHeaderData->bs_info.sbr_preprocessing,
533*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.v_k_master[0], hHeaderData->timeStep,
534*e5436536SAndroid Build Coastguard Worker borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands,
535*e5436536SAndroid Build Coastguard Worker hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode);
536*e5436536SAndroid Build Coastguard Worker }
537*e5436536SAndroid Build Coastguard Worker
538*e5436536SAndroid Build Coastguard Worker /*
539*e5436536SAndroid Build Coastguard Worker Adjust envelope of current frame.
540*e5436536SAndroid Build Coastguard Worker */
541*e5436536SAndroid Build Coastguard Worker
542*e5436536SAndroid Build Coastguard Worker if ((hFrameData->sbrPatchingMode !=
543*e5436536SAndroid Build Coastguard Worker hSbrDec->SbrCalculateEnvelope.sbrPatchingMode)) {
544*e5436536SAndroid Build Coastguard Worker ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable,
545*e5436536SAndroid Build Coastguard Worker &hHeaderData->freqBandData.noLimiterBands,
546*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.freqBandTable[0],
547*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.nSfb[0],
548*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->patchParam,
549*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->noOfPatches,
550*e5436536SAndroid Build Coastguard Worker hHeaderData->bs_data.limiterBands,
551*e5436536SAndroid Build Coastguard Worker hFrameData->sbrPatchingMode,
552*e5436536SAndroid Build Coastguard Worker (flags & SBRDEC_USAC_HARMONICSBR) &&
553*e5436536SAndroid Build Coastguard Worker (hFrameData->sbrPatchingMode == 0)
554*e5436536SAndroid Build Coastguard Worker ? GetxOverBandQmfTransposer(hSbrDec->hHBE)
555*e5436536SAndroid Build Coastguard Worker : NULL,
556*e5436536SAndroid Build Coastguard Worker Get41SbrQmfTransposer(hSbrDec->hHBE));
557*e5436536SAndroid Build Coastguard Worker
558*e5436536SAndroid Build Coastguard Worker hSbrDec->SbrCalculateEnvelope.sbrPatchingMode =
559*e5436536SAndroid Build Coastguard Worker hFrameData->sbrPatchingMode;
560*e5436536SAndroid Build Coastguard Worker }
561*e5436536SAndroid Build Coastguard Worker
562*e5436536SAndroid Build Coastguard Worker calculateSbrEnvelope(
563*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainInCh->scaling, &hSbrDec->SbrCalculateEnvelope,
564*e5436536SAndroid Build Coastguard Worker hHeaderData, hFrameData, &pvcDynamicData, pLowBandReal, pLowBandImag,
565*e5436536SAndroid Build Coastguard Worker flags & SBRDEC_LOW_POWER,
566*e5436536SAndroid Build Coastguard Worker
567*e5436536SAndroid Build Coastguard Worker degreeAlias, flags,
568*e5436536SAndroid Build Coastguard Worker (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag));
569*e5436536SAndroid Build Coastguard Worker
570*e5436536SAndroid Build Coastguard Worker #if (SBRDEC_MAX_HB_FADE_FRAMES > 0)
571*e5436536SAndroid Build Coastguard Worker /* Avoid hard onsets of high band */
572*e5436536SAndroid Build Coastguard Worker if (hHeaderData->frameErrorFlag) {
573*e5436536SAndroid Build Coastguard Worker if (hSbrDec->highBandFadeCnt < SBRDEC_MAX_HB_FADE_FRAMES) {
574*e5436536SAndroid Build Coastguard Worker hSbrDec->highBandFadeCnt += 1;
575*e5436536SAndroid Build Coastguard Worker }
576*e5436536SAndroid Build Coastguard Worker } else {
577*e5436536SAndroid Build Coastguard Worker if (hSbrDec->highBandFadeCnt >
578*e5436536SAndroid Build Coastguard Worker 0) { /* Manipulate high band scale factor to get a smooth fade-in */
579*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.hb_scale += hSbrDec->highBandFadeCnt;
580*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.hb_scale =
581*e5436536SAndroid Build Coastguard Worker fMin(hSbrDec->qmfDomainInCh->scaling.hb_scale, DFRACT_BITS - 1);
582*e5436536SAndroid Build Coastguard Worker hSbrDec->highBandFadeCnt -= 1;
583*e5436536SAndroid Build Coastguard Worker }
584*e5436536SAndroid Build Coastguard Worker }
585*e5436536SAndroid Build Coastguard Worker
586*e5436536SAndroid Build Coastguard Worker #endif
587*e5436536SAndroid Build Coastguard Worker /*
588*e5436536SAndroid Build Coastguard Worker Update hPrevFrameData (to be used in the next frame)
589*e5436536SAndroid Build Coastguard Worker */
590*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
591*e5436536SAndroid Build Coastguard Worker hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i];
592*e5436536SAndroid Build Coastguard Worker }
593*e5436536SAndroid Build Coastguard Worker hPrevFrameData->coupling = hFrameData->coupling;
594*e5436536SAndroid Build Coastguard Worker hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes];
595*e5436536SAndroid Build Coastguard Worker hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame;
596*e5436536SAndroid Build Coastguard Worker hPrevFrameData->prevSbrPitchInBins = hFrameData->sbrPitchInBins;
597*e5436536SAndroid Build Coastguard Worker /* could be done in extractFrameInfo_pvc() but hPrevFrameData is not
598*e5436536SAndroid Build Coastguard Worker * available there */
599*e5436536SAndroid Build Coastguard Worker FDKmemcpy(&hPrevFrameData->prevFrameInfo, &hFrameData->frameInfo,
600*e5436536SAndroid Build Coastguard Worker sizeof(FRAME_INFO));
601*e5436536SAndroid Build Coastguard Worker } else {
602*e5436536SAndroid Build Coastguard Worker /* rescale from lsb to nAnalysisBands in order to compensate scaling with
603*e5436536SAndroid Build Coastguard Worker * hb_scale in this area, done by synthesisFiltering*/
604*e5436536SAndroid Build Coastguard Worker int rescale;
605*e5436536SAndroid Build Coastguard Worker int lsb;
606*e5436536SAndroid Build Coastguard Worker int length;
607*e5436536SAndroid Build Coastguard Worker
608*e5436536SAndroid Build Coastguard Worker /* Reset hb_scale if no highband is present, because hb_scale is considered
609*e5436536SAndroid Build Coastguard Worker * in the QMF-synthesis */
610*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.hb_scale = saveLbScale;
611*e5436536SAndroid Build Coastguard Worker
612*e5436536SAndroid Build Coastguard Worker rescale = hSbrDec->qmfDomainInCh->scaling.hb_scale -
613*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.ov_lb_scale;
614*e5436536SAndroid Build Coastguard Worker lsb = hSbrDec->qmfDomainOutCh->fb.lsb;
615*e5436536SAndroid Build Coastguard Worker length = (hSbrDec->qmfDomainInCh->fb.no_channels - lsb);
616*e5436536SAndroid Build Coastguard Worker
617*e5436536SAndroid Build Coastguard Worker if ((rescale < 0) && (length > 0)) {
618*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_LOW_POWER)) {
619*e5436536SAndroid Build Coastguard Worker for (i = 0; i < ov_len; i++) {
620*e5436536SAndroid Build Coastguard Worker scaleValues(&pLowBandReal[i][lsb], length, rescale);
621*e5436536SAndroid Build Coastguard Worker scaleValues(&pLowBandImag[i][lsb], length, rescale);
622*e5436536SAndroid Build Coastguard Worker }
623*e5436536SAndroid Build Coastguard Worker } else {
624*e5436536SAndroid Build Coastguard Worker for (i = 0; i < ov_len; i++) {
625*e5436536SAndroid Build Coastguard Worker scaleValues(&pLowBandReal[i][lsb], length, rescale);
626*e5436536SAndroid Build Coastguard Worker }
627*e5436536SAndroid Build Coastguard Worker }
628*e5436536SAndroid Build Coastguard Worker }
629*e5436536SAndroid Build Coastguard Worker }
630*e5436536SAndroid Build Coastguard Worker
631*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_USAC_HARMONICSBR)) {
632*e5436536SAndroid Build Coastguard Worker int length = hSbrDec->qmfDomainInCh->fb.lsb;
633*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_SYNTAX_USAC) {
634*e5436536SAndroid Build Coastguard Worker length = hSbrDec->qmfDomainInCh->fb.no_channels;
635*e5436536SAndroid Build Coastguard Worker }
636*e5436536SAndroid Build Coastguard Worker
637*e5436536SAndroid Build Coastguard Worker /* in case of legacy sbr saving of filter states here */
638*e5436536SAndroid Build Coastguard Worker for (i = 0; i < LPC_ORDER + ov_len; i++) {
639*e5436536SAndroid Build Coastguard Worker /*
640*e5436536SAndroid Build Coastguard Worker Store the unmodified qmf Slots values (required for LPC filtering)
641*e5436536SAndroid Build Coastguard Worker */
642*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_LOW_POWER)) {
643*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i],
644*e5436536SAndroid Build Coastguard Worker pLowBandReal[noCols - LPC_ORDER + i],
645*e5436536SAndroid Build Coastguard Worker length * sizeof(FIXP_DBL));
646*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i],
647*e5436536SAndroid Build Coastguard Worker pLowBandImag[noCols - LPC_ORDER + i],
648*e5436536SAndroid Build Coastguard Worker length * sizeof(FIXP_DBL));
649*e5436536SAndroid Build Coastguard Worker } else
650*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i],
651*e5436536SAndroid Build Coastguard Worker pLowBandReal[noCols - LPC_ORDER + i],
652*e5436536SAndroid Build Coastguard Worker length * sizeof(FIXP_DBL));
653*e5436536SAndroid Build Coastguard Worker }
654*e5436536SAndroid Build Coastguard Worker }
655*e5436536SAndroid Build Coastguard Worker
656*e5436536SAndroid Build Coastguard Worker /*
657*e5436536SAndroid Build Coastguard Worker Synthesis subband filtering.
658*e5436536SAndroid Build Coastguard Worker */
659*e5436536SAndroid Build Coastguard Worker
660*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_PS_DECODED)) {
661*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
662*e5436536SAndroid Build Coastguard Worker int outScalefactor = -(8);
663*e5436536SAndroid Build Coastguard Worker
664*e5436536SAndroid Build Coastguard Worker if (h_ps_d != NULL) {
665*e5436536SAndroid Build Coastguard Worker h_ps_d->procFrameBased = 1; /* we here do frame based processing */
666*e5436536SAndroid Build Coastguard Worker }
667*e5436536SAndroid Build Coastguard Worker
668*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, pLowBandReal,
669*e5436536SAndroid Build Coastguard Worker (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag,
670*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainOutCh->fb.no_col, &outScalefactor);
671*e5436536SAndroid Build Coastguard Worker
672*e5436536SAndroid Build Coastguard Worker qmfChangeOutScalefactor(&hSbrDec->qmfDomainOutCh->fb, outScalefactor);
673*e5436536SAndroid Build Coastguard Worker
674*e5436536SAndroid Build Coastguard Worker {
675*e5436536SAndroid Build Coastguard Worker HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData;
676*e5436536SAndroid Build Coastguard Worker int save_usb = hSbrDec->qmfDomainOutCh->fb.usb;
677*e5436536SAndroid Build Coastguard Worker
678*e5436536SAndroid Build Coastguard Worker #if (QMF_MAX_SYNTHESIS_BANDS <= 64)
679*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
680*e5436536SAndroid Build Coastguard Worker #else
681*e5436536SAndroid Build Coastguard Worker C_AALLOC_STACK_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
682*e5436536SAndroid Build Coastguard Worker #endif
683*e5436536SAndroid Build Coastguard Worker if (hSbrDec->qmfDomainOutCh->fb.usb < hFreq->ov_highSubband) {
684*e5436536SAndroid Build Coastguard Worker /* we need to patch usb for this frame as overlap may contain higher
685*e5436536SAndroid Build Coastguard Worker frequency range if headerchange occured; fb. usb is always limited
686*e5436536SAndroid Build Coastguard Worker to maximum fb.no_channels; In case of wrongly decoded headers it
687*e5436536SAndroid Build Coastguard Worker might be that ov_highSubband is higher than the number of synthesis
688*e5436536SAndroid Build Coastguard Worker channels (fb.no_channels), which is forbidden, therefore we need to
689*e5436536SAndroid Build Coastguard Worker limit ov_highSubband with fMin function to avoid not allowed usb in
690*e5436536SAndroid Build Coastguard Worker synthesis filterbank. */
691*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainOutCh->fb.usb =
692*e5436536SAndroid Build Coastguard Worker fMin((UINT)hFreq->ov_highSubband,
693*e5436536SAndroid Build Coastguard Worker (UINT)hSbrDec->qmfDomainOutCh->fb.no_channels);
694*e5436536SAndroid Build Coastguard Worker }
695*e5436536SAndroid Build Coastguard Worker {
696*e5436536SAndroid Build Coastguard Worker qmfSynthesisFiltering(
697*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainOutCh->fb, pLowBandReal,
698*e5436536SAndroid Build Coastguard Worker (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag,
699*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainInCh->scaling,
700*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut,
701*e5436536SAndroid Build Coastguard Worker qmfTemp);
702*e5436536SAndroid Build Coastguard Worker }
703*e5436536SAndroid Build Coastguard Worker /* restore saved value */
704*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainOutCh->fb.usb = save_usb;
705*e5436536SAndroid Build Coastguard Worker hFreq->ov_highSubband = save_usb;
706*e5436536SAndroid Build Coastguard Worker #if (QMF_MAX_SYNTHESIS_BANDS <= 64)
707*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
708*e5436536SAndroid Build Coastguard Worker #else
709*e5436536SAndroid Build Coastguard Worker C_AALLOC_STACK_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
710*e5436536SAndroid Build Coastguard Worker #endif
711*e5436536SAndroid Build Coastguard Worker }
712*e5436536SAndroid Build Coastguard Worker }
713*e5436536SAndroid Build Coastguard Worker
714*e5436536SAndroid Build Coastguard Worker } else { /* (flags & SBRDEC_PS_DECODED) */
715*e5436536SAndroid Build Coastguard Worker INT sdiff;
716*e5436536SAndroid Build Coastguard Worker INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov,
717*e5436536SAndroid Build Coastguard Worker outScalefactor, outScalefactorR, outScalefactorL;
718*e5436536SAndroid Build Coastguard Worker
719*e5436536SAndroid Build Coastguard Worker HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb;
720*e5436536SAndroid Build Coastguard Worker HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb;
721*e5436536SAndroid Build Coastguard Worker
722*e5436536SAndroid Build Coastguard Worker /* adapt scaling */
723*e5436536SAndroid Build Coastguard Worker sdiff = hSbrDec->qmfDomainInCh->scaling.lb_scale -
724*e5436536SAndroid Build Coastguard Worker reserve; /* Scaling difference */
725*e5436536SAndroid Build Coastguard Worker scaleFactorHighBand = sdiff - hSbrDec->qmfDomainInCh->scaling.hb_scale;
726*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.ov_lb_scale;
727*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_no_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.lb_scale;
728*e5436536SAndroid Build Coastguard Worker
729*e5436536SAndroid Build Coastguard Worker /* Scale of low band overlapping QMF data */
730*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_ov =
731*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_ov));
732*e5436536SAndroid Build Coastguard Worker /* Scale of low band current QMF data */
733*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_no_ov = fMin(
734*e5436536SAndroid Build Coastguard Worker DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_no_ov));
735*e5436536SAndroid Build Coastguard Worker /* Scale of current high band */
736*e5436536SAndroid Build Coastguard Worker scaleFactorHighBand =
737*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorHighBand));
738*e5436536SAndroid Build Coastguard Worker
739*e5436536SAndroid Build Coastguard Worker if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot
740*e5436536SAndroid Build Coastguard Worker based processing copy filter states */
741*e5436536SAndroid Build Coastguard Worker { /* procFrameBased will be unset later */
742*e5436536SAndroid Build Coastguard Worker /* copy filter states from left to right */
743*e5436536SAndroid Build Coastguard Worker /* was ((640)-(64))*sizeof(FIXP_QSS)
744*e5436536SAndroid Build Coastguard Worker flexible amount of synthesis bands needed for QMF based resampling
745*e5436536SAndroid Build Coastguard Worker */
746*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <=
747*e5436536SAndroid Build Coastguard Worker QMF_MAX_SYNTHESIS_BANDS);
748*e5436536SAndroid Build Coastguard Worker synQmfRight->outScalefactor = synQmf->outScalefactor;
749*e5436536SAndroid Build Coastguard Worker FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates,
750*e5436536SAndroid Build Coastguard Worker 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis *
751*e5436536SAndroid Build Coastguard Worker sizeof(FIXP_QSS));
752*e5436536SAndroid Build Coastguard Worker }
753*e5436536SAndroid Build Coastguard Worker
754*e5436536SAndroid Build Coastguard Worker /* Feed delaylines when parametric stereo is switched on. */
755*e5436536SAndroid Build Coastguard Worker PreparePsProcessing(h_ps_d, pLowBandReal, pLowBandImag,
756*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_ov);
757*e5436536SAndroid Build Coastguard Worker
758*e5436536SAndroid Build Coastguard Worker /* use the same synthese qmf values for left and right channel */
759*e5436536SAndroid Build Coastguard Worker synQmfRight->no_col = synQmf->no_col;
760*e5436536SAndroid Build Coastguard Worker synQmfRight->lsb = synQmf->lsb;
761*e5436536SAndroid Build Coastguard Worker synQmfRight->usb = synQmf->usb;
762*e5436536SAndroid Build Coastguard Worker
763*e5436536SAndroid Build Coastguard Worker int env = 0;
764*e5436536SAndroid Build Coastguard Worker
765*e5436536SAndroid Build Coastguard Worker {
766*e5436536SAndroid Build Coastguard Worker #if (QMF_MAX_SYNTHESIS_BANDS <= 64)
767*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL,
768*e5436536SAndroid Build Coastguard Worker 2 * QMF_MAX_SYNTHESIS_BANDS);
769*e5436536SAndroid Build Coastguard Worker #else
770*e5436536SAndroid Build Coastguard Worker C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
771*e5436536SAndroid Build Coastguard Worker #endif
772*e5436536SAndroid Build Coastguard Worker
773*e5436536SAndroid Build Coastguard Worker int maxShift = 0;
774*e5436536SAndroid Build Coastguard Worker
775*e5436536SAndroid Build Coastguard Worker if (hSbrDec->sbrDrcChannel.enable != 0) {
776*e5436536SAndroid Build Coastguard Worker if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) {
777*e5436536SAndroid Build Coastguard Worker maxShift = hSbrDec->sbrDrcChannel.prevFact_exp;
778*e5436536SAndroid Build Coastguard Worker }
779*e5436536SAndroid Build Coastguard Worker if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) {
780*e5436536SAndroid Build Coastguard Worker maxShift = hSbrDec->sbrDrcChannel.currFact_exp;
781*e5436536SAndroid Build Coastguard Worker }
782*e5436536SAndroid Build Coastguard Worker if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) {
783*e5436536SAndroid Build Coastguard Worker maxShift = hSbrDec->sbrDrcChannel.nextFact_exp;
784*e5436536SAndroid Build Coastguard Worker }
785*e5436536SAndroid Build Coastguard Worker }
786*e5436536SAndroid Build Coastguard Worker
787*e5436536SAndroid Build Coastguard Worker /* copy DRC data to right channel (with PS both channels use the same DRC
788*e5436536SAndroid Build Coastguard Worker * gains) */
789*e5436536SAndroid Build Coastguard Worker FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel,
790*e5436536SAndroid Build Coastguard Worker sizeof(SBRDEC_DRC_CHANNEL));
791*e5436536SAndroid Build Coastguard Worker
792*e5436536SAndroid Build Coastguard Worker outScalefactor = maxShift - (8);
793*e5436536SAndroid Build Coastguard Worker outScalefactorL = outScalefactorR =
794*e5436536SAndroid Build Coastguard Worker sbrInDataHeadroom + 1; /* +1: psDiffScale! (MPEG-PS) */
795*e5436536SAndroid Build Coastguard Worker
796*e5436536SAndroid Build Coastguard Worker for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
797*e5436536SAndroid Build Coastguard Worker
798*e5436536SAndroid Build Coastguard Worker /* qmf timeslot of right channel */
799*e5436536SAndroid Build Coastguard Worker FIXP_DBL *rQmfReal = pWorkBuffer;
800*e5436536SAndroid Build Coastguard Worker FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels;
801*e5436536SAndroid Build Coastguard Worker
802*e5436536SAndroid Build Coastguard Worker {
803*e5436536SAndroid Build Coastguard Worker if (i ==
804*e5436536SAndroid Build Coastguard Worker h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]) {
805*e5436536SAndroid Build Coastguard Worker initSlotBasedRotation(h_ps_d, env,
806*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.highSubband);
807*e5436536SAndroid Build Coastguard Worker env++;
808*e5436536SAndroid Build Coastguard Worker }
809*e5436536SAndroid Build Coastguard Worker
810*e5436536SAndroid Build Coastguard Worker ApplyPsSlot(
811*e5436536SAndroid Build Coastguard Worker h_ps_d, /* parametric stereo decoder handle */
812*e5436536SAndroid Build Coastguard Worker (pLowBandReal + i), /* one timeslot of left/mono channel */
813*e5436536SAndroid Build Coastguard Worker (pLowBandImag + i), /* one timeslot of left/mono channel */
814*e5436536SAndroid Build Coastguard Worker rQmfReal, /* one timeslot or right channel */
815*e5436536SAndroid Build Coastguard Worker rQmfImag, /* one timeslot or right channel */
816*e5436536SAndroid Build Coastguard Worker scaleFactorLowBand_no_ov,
817*e5436536SAndroid Build Coastguard Worker (i < hSbrDec->LppTrans.pSettings->overlap)
818*e5436536SAndroid Build Coastguard Worker ? scaleFactorLowBand_ov
819*e5436536SAndroid Build Coastguard Worker : scaleFactorLowBand_no_ov,
820*e5436536SAndroid Build Coastguard Worker scaleFactorHighBand, synQmf->lsb, synQmf->usb);
821*e5436536SAndroid Build Coastguard Worker }
822*e5436536SAndroid Build Coastguard Worker
823*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcApplySlot(/* right channel */
824*e5436536SAndroid Build Coastguard Worker &hSbrDecRight->sbrDrcChannel, rQmfReal,
825*e5436536SAndroid Build Coastguard Worker rQmfImag, i, synQmfRight->no_col, maxShift);
826*e5436536SAndroid Build Coastguard Worker
827*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcApplySlot(/* left channel */
828*e5436536SAndroid Build Coastguard Worker &hSbrDec->sbrDrcChannel, *(pLowBandReal + i),
829*e5436536SAndroid Build Coastguard Worker *(pLowBandImag + i), i, synQmf->no_col,
830*e5436536SAndroid Build Coastguard Worker maxShift);
831*e5436536SAndroid Build Coastguard Worker
832*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
833*e5436536SAndroid Build Coastguard Worker qmfChangeOutScalefactor(synQmf, outScalefactor);
834*e5436536SAndroid Build Coastguard Worker qmfChangeOutScalefactor(synQmfRight, outScalefactor);
835*e5436536SAndroid Build Coastguard Worker
836*e5436536SAndroid Build Coastguard Worker qmfSynthesisFilteringSlot(
837*e5436536SAndroid Build Coastguard Worker synQmfRight, rQmfReal, /* QMF real buffer */
838*e5436536SAndroid Build Coastguard Worker rQmfImag, /* QMF imag buffer */
839*e5436536SAndroid Build Coastguard Worker outScalefactorL, outScalefactorL,
840*e5436536SAndroid Build Coastguard Worker timeOutRight + (i * synQmf->no_channels * strideOut), strideOut,
841*e5436536SAndroid Build Coastguard Worker pWorkBuffer);
842*e5436536SAndroid Build Coastguard Worker
843*e5436536SAndroid Build Coastguard Worker qmfSynthesisFilteringSlot(
844*e5436536SAndroid Build Coastguard Worker synQmf, *(pLowBandReal + i), /* QMF real buffer */
845*e5436536SAndroid Build Coastguard Worker *(pLowBandImag + i), /* QMF imag buffer */
846*e5436536SAndroid Build Coastguard Worker outScalefactorR, outScalefactorR,
847*e5436536SAndroid Build Coastguard Worker timeOut + (i * synQmf->no_channels * strideOut), strideOut,
848*e5436536SAndroid Build Coastguard Worker pWorkBuffer);
849*e5436536SAndroid Build Coastguard Worker }
850*e5436536SAndroid Build Coastguard Worker } /* no_col loop i */
851*e5436536SAndroid Build Coastguard Worker #if (QMF_MAX_SYNTHESIS_BANDS <= 64)
852*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
853*e5436536SAndroid Build Coastguard Worker #else
854*e5436536SAndroid Build Coastguard Worker C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS);
855*e5436536SAndroid Build Coastguard Worker #endif
856*e5436536SAndroid Build Coastguard Worker }
857*e5436536SAndroid Build Coastguard Worker }
858*e5436536SAndroid Build Coastguard Worker
859*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcUpdateChannel(&hSbrDec->sbrDrcChannel);
860*e5436536SAndroid Build Coastguard Worker
861*e5436536SAndroid Build Coastguard Worker /*
862*e5436536SAndroid Build Coastguard Worker Update overlap buffer
863*e5436536SAndroid Build Coastguard Worker Even bands above usb are copied to avoid outdated spectral data in case
864*e5436536SAndroid Build Coastguard Worker the stop frequency raises.
865*e5436536SAndroid Build Coastguard Worker */
866*e5436536SAndroid Build Coastguard Worker
867*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
868*e5436536SAndroid Build Coastguard Worker {
869*e5436536SAndroid Build Coastguard Worker FDK_QmfDomain_SaveOverlap(hSbrDec->qmfDomainInCh, 0);
870*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale == saveLbScale);
871*e5436536SAndroid Build Coastguard Worker }
872*e5436536SAndroid Build Coastguard Worker }
873*e5436536SAndroid Build Coastguard Worker
874*e5436536SAndroid Build Coastguard Worker hSbrDec->savedStates = 0;
875*e5436536SAndroid Build Coastguard Worker
876*e5436536SAndroid Build Coastguard Worker /* Save current frame status */
877*e5436536SAndroid Build Coastguard Worker hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag;
878*e5436536SAndroid Build Coastguard Worker hSbrDec->applySbrProc_old = applyProcessing;
879*e5436536SAndroid Build Coastguard Worker
880*e5436536SAndroid Build Coastguard Worker } /* sbr_dec() */
881*e5436536SAndroid Build Coastguard Worker
882*e5436536SAndroid Build Coastguard Worker /*!
883*e5436536SAndroid Build Coastguard Worker \brief Creates sbr decoder structure
884*e5436536SAndroid Build Coastguard Worker \return errorCode, 0 if successful
885*e5436536SAndroid Build Coastguard Worker */
886*e5436536SAndroid Build Coastguard Worker SBR_ERROR
createSbrDec(SBR_CHANNEL * hSbrChannel,HANDLE_SBR_HEADER_DATA hHeaderData,TRANSPOSER_SETTINGS * pSettings,const int downsampleFac,const UINT qmfFlags,const UINT flags,const int overlap,int chan,int codecFrameSize)887*e5436536SAndroid Build Coastguard Worker createSbrDec(SBR_CHANNEL *hSbrChannel,
888*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
889*e5436536SAndroid Build Coastguard Worker TRANSPOSER_SETTINGS *pSettings,
890*e5436536SAndroid Build Coastguard Worker const int downsampleFac, /*!< Downsampling factor */
891*e5436536SAndroid Build Coastguard Worker const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */
892*e5436536SAndroid Build Coastguard Worker const UINT flags, const int overlap,
893*e5436536SAndroid Build Coastguard Worker int chan, /*!< Channel for which to assign buffers etc. */
894*e5436536SAndroid Build Coastguard Worker int codecFrameSize)
895*e5436536SAndroid Build Coastguard Worker
896*e5436536SAndroid Build Coastguard Worker {
897*e5436536SAndroid Build Coastguard Worker SBR_ERROR err = SBRDEC_OK;
898*e5436536SAndroid Build Coastguard Worker int timeSlots =
899*e5436536SAndroid Build Coastguard Worker hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */
900*e5436536SAndroid Build Coastguard Worker int noCols =
901*e5436536SAndroid Build Coastguard Worker timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */
902*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec);
903*e5436536SAndroid Build Coastguard Worker
904*e5436536SAndroid Build Coastguard Worker #if (SBRDEC_MAX_HB_FADE_FRAMES > 0)
905*e5436536SAndroid Build Coastguard Worker hs->highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES;
906*e5436536SAndroid Build Coastguard Worker
907*e5436536SAndroid Build Coastguard Worker #endif
908*e5436536SAndroid Build Coastguard Worker hs->scale_hbe = 15;
909*e5436536SAndroid Build Coastguard Worker hs->scale_lb = 15;
910*e5436536SAndroid Build Coastguard Worker hs->scale_ov = 15;
911*e5436536SAndroid Build Coastguard Worker
912*e5436536SAndroid Build Coastguard Worker hs->prev_frame_lSbr = 0;
913*e5436536SAndroid Build Coastguard Worker hs->prev_frame_hbeSbr = 0;
914*e5436536SAndroid Build Coastguard Worker
915*e5436536SAndroid Build Coastguard Worker hs->codecFrameSize = codecFrameSize;
916*e5436536SAndroid Build Coastguard Worker
917*e5436536SAndroid Build Coastguard Worker /*
918*e5436536SAndroid Build Coastguard Worker create envelope calculator
919*e5436536SAndroid Build Coastguard Worker */
920*e5436536SAndroid Build Coastguard Worker err = createSbrEnvelopeCalc(&hs->SbrCalculateEnvelope, hHeaderData, chan,
921*e5436536SAndroid Build Coastguard Worker flags);
922*e5436536SAndroid Build Coastguard Worker if (err != SBRDEC_OK) {
923*e5436536SAndroid Build Coastguard Worker return err;
924*e5436536SAndroid Build Coastguard Worker }
925*e5436536SAndroid Build Coastguard Worker
926*e5436536SAndroid Build Coastguard Worker initSbrPrevFrameData(&hSbrChannel->prevFrameData, timeSlots);
927*e5436536SAndroid Build Coastguard Worker
928*e5436536SAndroid Build Coastguard Worker /*
929*e5436536SAndroid Build Coastguard Worker create transposer
930*e5436536SAndroid Build Coastguard Worker */
931*e5436536SAndroid Build Coastguard Worker err = createLppTransposer(
932*e5436536SAndroid Build Coastguard Worker &hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband,
933*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster,
934*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.highSubband, timeSlots, noCols,
935*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.freqBandTableNoise,
936*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan,
937*e5436536SAndroid Build Coastguard Worker overlap);
938*e5436536SAndroid Build Coastguard Worker if (err != SBRDEC_OK) {
939*e5436536SAndroid Build Coastguard Worker return err;
940*e5436536SAndroid Build Coastguard Worker }
941*e5436536SAndroid Build Coastguard Worker
942*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_USAC_HARMONICSBR) {
943*e5436536SAndroid Build Coastguard Worker int noChannels, bSbr41 = flags & SBRDEC_QUAD_RATE ? 1 : 0;
944*e5436536SAndroid Build Coastguard Worker
945*e5436536SAndroid Build Coastguard Worker noChannels =
946*e5436536SAndroid Build Coastguard Worker QMF_SYNTH_CHANNELS /
947*e5436536SAndroid Build Coastguard Worker ((bSbr41 + 1) * 2); /* 32 for (32:64 and 24:64) and 16 for 16:64 */
948*e5436536SAndroid Build Coastguard Worker
949*e5436536SAndroid Build Coastguard Worker /* shared memory between hbeLightTimeDelayBuffer and hQmfHBESlotsReal if
950*e5436536SAndroid Build Coastguard Worker * SBRDEC_HBE_ENABLE */
951*e5436536SAndroid Build Coastguard Worker hSbrChannel->SbrDec.tmp_memory = (FIXP_DBL **)fdkCallocMatrix2D_aligned(
952*e5436536SAndroid Build Coastguard Worker noCols, noChannels, sizeof(FIXP_DBL));
953*e5436536SAndroid Build Coastguard Worker if (hSbrChannel->SbrDec.tmp_memory == NULL) {
954*e5436536SAndroid Build Coastguard Worker return SBRDEC_MEM_ALLOC_FAILED;
955*e5436536SAndroid Build Coastguard Worker }
956*e5436536SAndroid Build Coastguard Worker
957*e5436536SAndroid Build Coastguard Worker hSbrChannel->SbrDec.hQmfHBESlotsReal = hSbrChannel->SbrDec.tmp_memory;
958*e5436536SAndroid Build Coastguard Worker hSbrChannel->SbrDec.hQmfHBESlotsImag =
959*e5436536SAndroid Build Coastguard Worker (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels,
960*e5436536SAndroid Build Coastguard Worker sizeof(FIXP_DBL));
961*e5436536SAndroid Build Coastguard Worker if (hSbrChannel->SbrDec.hQmfHBESlotsImag == NULL) {
962*e5436536SAndroid Build Coastguard Worker return SBRDEC_MEM_ALLOC_FAILED;
963*e5436536SAndroid Build Coastguard Worker }
964*e5436536SAndroid Build Coastguard Worker
965*e5436536SAndroid Build Coastguard Worker /* buffers containing unmodified qmf data; required when switching from
966*e5436536SAndroid Build Coastguard Worker * legacy SBR to HBE */
967*e5436536SAndroid Build Coastguard Worker /* buffer can be used as LPCFilterstates buffer because legacy SBR needs
968*e5436536SAndroid Build Coastguard Worker * exactly these values for LPC filtering */
969*e5436536SAndroid Build Coastguard Worker hSbrChannel->SbrDec.codecQMFBufferReal =
970*e5436536SAndroid Build Coastguard Worker (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels,
971*e5436536SAndroid Build Coastguard Worker sizeof(FIXP_DBL));
972*e5436536SAndroid Build Coastguard Worker if (hSbrChannel->SbrDec.codecQMFBufferReal == NULL) {
973*e5436536SAndroid Build Coastguard Worker return SBRDEC_MEM_ALLOC_FAILED;
974*e5436536SAndroid Build Coastguard Worker }
975*e5436536SAndroid Build Coastguard Worker
976*e5436536SAndroid Build Coastguard Worker hSbrChannel->SbrDec.codecQMFBufferImag =
977*e5436536SAndroid Build Coastguard Worker (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels,
978*e5436536SAndroid Build Coastguard Worker sizeof(FIXP_DBL));
979*e5436536SAndroid Build Coastguard Worker if (hSbrChannel->SbrDec.codecQMFBufferImag == NULL) {
980*e5436536SAndroid Build Coastguard Worker return SBRDEC_MEM_ALLOC_FAILED;
981*e5436536SAndroid Build Coastguard Worker }
982*e5436536SAndroid Build Coastguard Worker
983*e5436536SAndroid Build Coastguard Worker err = QmfTransposerCreate(&hs->hHBE, codecFrameSize, 0, bSbr41);
984*e5436536SAndroid Build Coastguard Worker if (err != SBRDEC_OK) {
985*e5436536SAndroid Build Coastguard Worker return err;
986*e5436536SAndroid Build Coastguard Worker }
987*e5436536SAndroid Build Coastguard Worker }
988*e5436536SAndroid Build Coastguard Worker
989*e5436536SAndroid Build Coastguard Worker return err;
990*e5436536SAndroid Build Coastguard Worker }
991*e5436536SAndroid Build Coastguard Worker
992*e5436536SAndroid Build Coastguard Worker /*!
993*e5436536SAndroid Build Coastguard Worker \brief Delete sbr decoder structure
994*e5436536SAndroid Build Coastguard Worker \return errorCode, 0 if successful
995*e5436536SAndroid Build Coastguard Worker */
deleteSbrDec(SBR_CHANNEL * hSbrChannel)996*e5436536SAndroid Build Coastguard Worker int deleteSbrDec(SBR_CHANNEL *hSbrChannel) {
997*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec;
998*e5436536SAndroid Build Coastguard Worker
999*e5436536SAndroid Build Coastguard Worker deleteSbrEnvelopeCalc(&hs->SbrCalculateEnvelope);
1000*e5436536SAndroid Build Coastguard Worker
1001*e5436536SAndroid Build Coastguard Worker if (hs->tmp_memory != NULL) {
1002*e5436536SAndroid Build Coastguard Worker FDK_FREE_MEMORY_2D_ALIGNED(hs->tmp_memory);
1003*e5436536SAndroid Build Coastguard Worker }
1004*e5436536SAndroid Build Coastguard Worker
1005*e5436536SAndroid Build Coastguard Worker /* modify here */
1006*e5436536SAndroid Build Coastguard Worker FDK_FREE_MEMORY_2D_ALIGNED(hs->hQmfHBESlotsImag);
1007*e5436536SAndroid Build Coastguard Worker
1008*e5436536SAndroid Build Coastguard Worker if (hs->hHBE != NULL) QmfTransposerClose(hs->hHBE);
1009*e5436536SAndroid Build Coastguard Worker
1010*e5436536SAndroid Build Coastguard Worker if (hs->codecQMFBufferReal != NULL) {
1011*e5436536SAndroid Build Coastguard Worker FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferReal);
1012*e5436536SAndroid Build Coastguard Worker }
1013*e5436536SAndroid Build Coastguard Worker
1014*e5436536SAndroid Build Coastguard Worker if (hs->codecQMFBufferImag != NULL) {
1015*e5436536SAndroid Build Coastguard Worker FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferImag);
1016*e5436536SAndroid Build Coastguard Worker }
1017*e5436536SAndroid Build Coastguard Worker
1018*e5436536SAndroid Build Coastguard Worker return 0;
1019*e5436536SAndroid Build Coastguard Worker }
1020*e5436536SAndroid Build Coastguard Worker
1021*e5436536SAndroid Build Coastguard Worker /*!
1022*e5436536SAndroid Build Coastguard Worker \brief resets sbr decoder structure
1023*e5436536SAndroid Build Coastguard Worker \return errorCode, 0 if successful
1024*e5436536SAndroid Build Coastguard Worker */
1025*e5436536SAndroid Build Coastguard Worker SBR_ERROR
resetSbrDec(HANDLE_SBR_DEC hSbrDec,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData,const int downsampleFac,const UINT flags,HANDLE_SBR_FRAME_DATA hFrameData)1026*e5436536SAndroid Build Coastguard Worker resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData,
1027*e5436536SAndroid Build Coastguard Worker HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac,
1028*e5436536SAndroid Build Coastguard Worker const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData) {
1029*e5436536SAndroid Build Coastguard Worker SBR_ERROR sbrError = SBRDEC_OK;
1030*e5436536SAndroid Build Coastguard Worker int i;
1031*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pLowBandReal[128];
1032*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pLowBandImag[128];
1033*e5436536SAndroid Build Coastguard Worker int useLP = flags & SBRDEC_LOW_POWER;
1034*e5436536SAndroid Build Coastguard Worker
1035*e5436536SAndroid Build Coastguard Worker int old_lsb = hSbrDec->qmfDomainInCh->fb.lsb;
1036*e5436536SAndroid Build Coastguard Worker int old_usb = hSbrDec->qmfDomainInCh->fb.usb;
1037*e5436536SAndroid Build Coastguard Worker int new_lsb = hHeaderData->freqBandData.lowSubband;
1038*e5436536SAndroid Build Coastguard Worker /* int new_usb = hHeaderData->freqBandData.highSubband; */
1039*e5436536SAndroid Build Coastguard Worker int l, startBand, stopBand, startSlot, size;
1040*e5436536SAndroid Build Coastguard Worker
1041*e5436536SAndroid Build Coastguard Worker FIXP_DBL **OverlapBufferReal = hSbrDec->qmfDomainInCh->hQmfSlotsReal;
1042*e5436536SAndroid Build Coastguard Worker FIXP_DBL **OverlapBufferImag = hSbrDec->qmfDomainInCh->hQmfSlotsImag;
1043*e5436536SAndroid Build Coastguard Worker
1044*e5436536SAndroid Build Coastguard Worker /* in case the previous frame was not active in terms of SBR processing, the
1045*e5436536SAndroid Build Coastguard Worker full band from 0 to no_channels was rescaled and not overwritten. Thats why
1046*e5436536SAndroid Build Coastguard Worker the scaling factor lb_scale can be seen as assigned to all bands from 0 to
1047*e5436536SAndroid Build Coastguard Worker no_channels in the previous frame. The same states for the current frame if
1048*e5436536SAndroid Build Coastguard Worker the current frame is not active in terms of SBR processing
1049*e5436536SAndroid Build Coastguard Worker */
1050*e5436536SAndroid Build Coastguard Worker int applySbrProc = (hHeaderData->syncState == SBR_ACTIVE ||
1051*e5436536SAndroid Build Coastguard Worker (hHeaderData->frameErrorFlag == 0 &&
1052*e5436536SAndroid Build Coastguard Worker hHeaderData->syncState == SBR_HEADER));
1053*e5436536SAndroid Build Coastguard Worker int applySbrProc_old = hSbrDec->applySbrProc_old;
1054*e5436536SAndroid Build Coastguard Worker
1055*e5436536SAndroid Build Coastguard Worker if (!applySbrProc) {
1056*e5436536SAndroid Build Coastguard Worker new_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels;
1057*e5436536SAndroid Build Coastguard Worker }
1058*e5436536SAndroid Build Coastguard Worker if (!applySbrProc_old) {
1059*e5436536SAndroid Build Coastguard Worker old_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels;
1060*e5436536SAndroid Build Coastguard Worker old_usb = old_lsb;
1061*e5436536SAndroid Build Coastguard Worker }
1062*e5436536SAndroid Build Coastguard Worker
1063*e5436536SAndroid Build Coastguard Worker resetSbrEnvelopeCalc(&hSbrDec->SbrCalculateEnvelope);
1064*e5436536SAndroid Build Coastguard Worker
1065*e5436536SAndroid Build Coastguard Worker /* Change lsb and usb */
1066*e5436536SAndroid Build Coastguard Worker /* Synthesis */
1067*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(hSbrDec->qmfDomainOutCh != NULL);
1068*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainOutCh->fb.lsb =
1069*e5436536SAndroid Build Coastguard Worker fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels,
1070*e5436536SAndroid Build Coastguard Worker (INT)hHeaderData->freqBandData.lowSubband);
1071*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainOutCh->fb.usb =
1072*e5436536SAndroid Build Coastguard Worker fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels,
1073*e5436536SAndroid Build Coastguard Worker (INT)hHeaderData->freqBandData.highSubband);
1074*e5436536SAndroid Build Coastguard Worker /* Analysis */
1075*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(hSbrDec->qmfDomainInCh != NULL);
1076*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->fb.lsb = hSbrDec->qmfDomainOutCh->fb.lsb;
1077*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->fb.usb = hSbrDec->qmfDomainOutCh->fb.usb;
1078*e5436536SAndroid Build Coastguard Worker
1079*e5436536SAndroid Build Coastguard Worker /*
1080*e5436536SAndroid Build Coastguard Worker The following initialization of spectral data in the overlap buffer
1081*e5436536SAndroid Build Coastguard Worker is required for dynamic x-over or a change of the start-freq for 2 reasons:
1082*e5436536SAndroid Build Coastguard Worker
1083*e5436536SAndroid Build Coastguard Worker 1. If the lowband gets _wider_, unadjusted data would remain
1084*e5436536SAndroid Build Coastguard Worker
1085*e5436536SAndroid Build Coastguard Worker 2. If the lowband becomes _smaller_, the highest bands of the old lowband
1086*e5436536SAndroid Build Coastguard Worker must be cleared because the whitening would be affected
1087*e5436536SAndroid Build Coastguard Worker */
1088*e5436536SAndroid Build Coastguard Worker startBand = old_lsb;
1089*e5436536SAndroid Build Coastguard Worker stopBand = new_lsb;
1090*e5436536SAndroid Build Coastguard Worker startSlot = fMax(0, hHeaderData->timeStep * (hPrevFrameData->stopPos -
1091*e5436536SAndroid Build Coastguard Worker hHeaderData->numberTimeSlots));
1092*e5436536SAndroid Build Coastguard Worker size = fMax(0, stopBand - startBand);
1093*e5436536SAndroid Build Coastguard Worker
1094*e5436536SAndroid Build Coastguard Worker /* in case of USAC we don't want to zero out the memory, as this can lead to
1095*e5436536SAndroid Build Coastguard Worker holes in the spectrum; fix shall only be applied for USAC not for MPEG-4
1096*e5436536SAndroid Build Coastguard Worker SBR, in this case setting zero remains */
1097*e5436536SAndroid Build Coastguard Worker if (!(flags & SBRDEC_SYNTAX_USAC)) {
1098*e5436536SAndroid Build Coastguard Worker /* keep already adjusted data in the x-over-area */
1099*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1100*e5436536SAndroid Build Coastguard Worker for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) {
1101*e5436536SAndroid Build Coastguard Worker FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL));
1102*e5436536SAndroid Build Coastguard Worker FDKmemclear(&OverlapBufferImag[l][startBand], size * sizeof(FIXP_DBL));
1103*e5436536SAndroid Build Coastguard Worker }
1104*e5436536SAndroid Build Coastguard Worker } else {
1105*e5436536SAndroid Build Coastguard Worker for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) {
1106*e5436536SAndroid Build Coastguard Worker FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL));
1107*e5436536SAndroid Build Coastguard Worker }
1108*e5436536SAndroid Build Coastguard Worker }
1109*e5436536SAndroid Build Coastguard Worker
1110*e5436536SAndroid Build Coastguard Worker /*
1111*e5436536SAndroid Build Coastguard Worker reset LPC filter states
1112*e5436536SAndroid Build Coastguard Worker */
1113*e5436536SAndroid Build Coastguard Worker startBand = fixMin(old_lsb, new_lsb);
1114*e5436536SAndroid Build Coastguard Worker stopBand = fixMax(old_lsb, new_lsb);
1115*e5436536SAndroid Build Coastguard Worker size = fixMax(0, stopBand - startBand);
1116*e5436536SAndroid Build Coastguard Worker
1117*e5436536SAndroid Build Coastguard Worker FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[0][startBand],
1118*e5436536SAndroid Build Coastguard Worker size * sizeof(FIXP_DBL));
1119*e5436536SAndroid Build Coastguard Worker FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[1][startBand],
1120*e5436536SAndroid Build Coastguard Worker size * sizeof(FIXP_DBL));
1121*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1122*e5436536SAndroid Build Coastguard Worker FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[0][startBand],
1123*e5436536SAndroid Build Coastguard Worker size * sizeof(FIXP_DBL));
1124*e5436536SAndroid Build Coastguard Worker FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[1][startBand],
1125*e5436536SAndroid Build Coastguard Worker size * sizeof(FIXP_DBL));
1126*e5436536SAndroid Build Coastguard Worker }
1127*e5436536SAndroid Build Coastguard Worker }
1128*e5436536SAndroid Build Coastguard Worker
1129*e5436536SAndroid Build Coastguard Worker if (startSlot != 0) {
1130*e5436536SAndroid Build Coastguard Worker int source_exp, target_exp, delta_exp, target_lsb, target_usb, reserve;
1131*e5436536SAndroid Build Coastguard Worker FIXP_DBL maxVal;
1132*e5436536SAndroid Build Coastguard Worker
1133*e5436536SAndroid Build Coastguard Worker /*
1134*e5436536SAndroid Build Coastguard Worker Rescale already processed spectral data between old and new x-over
1135*e5436536SAndroid Build Coastguard Worker frequency. This must be done because of the separate scalefactors for
1136*e5436536SAndroid Build Coastguard Worker lowband and highband.
1137*e5436536SAndroid Build Coastguard Worker */
1138*e5436536SAndroid Build Coastguard Worker
1139*e5436536SAndroid Build Coastguard Worker /* We have four relevant transitions to cover:
1140*e5436536SAndroid Build Coastguard Worker 1. old_usb is lower than new_lsb; old SBR area is completely below new SBR
1141*e5436536SAndroid Build Coastguard Worker area.
1142*e5436536SAndroid Build Coastguard Worker -> entire old area was highband and belongs to lowband now
1143*e5436536SAndroid Build Coastguard Worker and has to be rescaled.
1144*e5436536SAndroid Build Coastguard Worker 2. old_lsb is higher than new_usb; new SBR area is completely below old SBR
1145*e5436536SAndroid Build Coastguard Worker area.
1146*e5436536SAndroid Build Coastguard Worker -> old area between new_lsb and old_lsb was lowband and belongs to
1147*e5436536SAndroid Build Coastguard Worker highband now and has to be rescaled to match new highband scale.
1148*e5436536SAndroid Build Coastguard Worker 3. old_lsb is lower and old_usb is higher than new_lsb; old and new SBR
1149*e5436536SAndroid Build Coastguard Worker areas overlap.
1150*e5436536SAndroid Build Coastguard Worker -> old area between old_lsb and new_lsb was highband and belongs to
1151*e5436536SAndroid Build Coastguard Worker lowband now and has to be rescaled to match new lowband scale.
1152*e5436536SAndroid Build Coastguard Worker 4. new_lsb is lower and new_usb_is higher than old_lsb; old and new SBR
1153*e5436536SAndroid Build Coastguard Worker areas overlap.
1154*e5436536SAndroid Build Coastguard Worker -> old area between new_lsb and old_usb was lowband and belongs to
1155*e5436536SAndroid Build Coastguard Worker highband now and has to be rescaled to match new highband scale.
1156*e5436536SAndroid Build Coastguard Worker */
1157*e5436536SAndroid Build Coastguard Worker
1158*e5436536SAndroid Build Coastguard Worker if (new_lsb > old_lsb) {
1159*e5436536SAndroid Build Coastguard Worker /* case 1 and 3 */
1160*e5436536SAndroid Build Coastguard Worker source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale);
1161*e5436536SAndroid Build Coastguard Worker target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale);
1162*e5436536SAndroid Build Coastguard Worker
1163*e5436536SAndroid Build Coastguard Worker startBand = old_lsb;
1164*e5436536SAndroid Build Coastguard Worker
1165*e5436536SAndroid Build Coastguard Worker if (new_lsb >= old_usb) {
1166*e5436536SAndroid Build Coastguard Worker /* case 1 */
1167*e5436536SAndroid Build Coastguard Worker stopBand = old_usb;
1168*e5436536SAndroid Build Coastguard Worker } else {
1169*e5436536SAndroid Build Coastguard Worker /* case 3 */
1170*e5436536SAndroid Build Coastguard Worker stopBand = new_lsb;
1171*e5436536SAndroid Build Coastguard Worker }
1172*e5436536SAndroid Build Coastguard Worker
1173*e5436536SAndroid Build Coastguard Worker target_lsb = 0;
1174*e5436536SAndroid Build Coastguard Worker target_usb = old_lsb;
1175*e5436536SAndroid Build Coastguard Worker } else {
1176*e5436536SAndroid Build Coastguard Worker /* case 2 and 4 */
1177*e5436536SAndroid Build Coastguard Worker source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale);
1178*e5436536SAndroid Build Coastguard Worker target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale);
1179*e5436536SAndroid Build Coastguard Worker
1180*e5436536SAndroid Build Coastguard Worker startBand = new_lsb;
1181*e5436536SAndroid Build Coastguard Worker stopBand = old_lsb;
1182*e5436536SAndroid Build Coastguard Worker
1183*e5436536SAndroid Build Coastguard Worker target_lsb = old_lsb;
1184*e5436536SAndroid Build Coastguard Worker target_usb = old_usb;
1185*e5436536SAndroid Build Coastguard Worker }
1186*e5436536SAndroid Build Coastguard Worker
1187*e5436536SAndroid Build Coastguard Worker maxVal =
1188*e5436536SAndroid Build Coastguard Worker maxSubbandSample(OverlapBufferReal, (useLP) ? NULL : OverlapBufferImag,
1189*e5436536SAndroid Build Coastguard Worker startBand, stopBand, 0, startSlot);
1190*e5436536SAndroid Build Coastguard Worker
1191*e5436536SAndroid Build Coastguard Worker reserve = ((LONG)maxVal != 0 ? CntLeadingZeros(maxVal) - 1 : 0);
1192*e5436536SAndroid Build Coastguard Worker reserve = fixMin(
1193*e5436536SAndroid Build Coastguard Worker reserve,
1194*e5436536SAndroid Build Coastguard Worker DFRACT_BITS - 1 -
1195*e5436536SAndroid Build Coastguard Worker EXP2SCALE(
1196*e5436536SAndroid Build Coastguard Worker source_exp)); /* what is this line for, why do we need it? */
1197*e5436536SAndroid Build Coastguard Worker
1198*e5436536SAndroid Build Coastguard Worker /* process only if x-over-area is not dominant after rescale;
1199*e5436536SAndroid Build Coastguard Worker otherwise I'm not sure if all buffers are scaled correctly;
1200*e5436536SAndroid Build Coastguard Worker */
1201*e5436536SAndroid Build Coastguard Worker if (target_exp - (source_exp - reserve) >= 0) {
1202*e5436536SAndroid Build Coastguard Worker rescaleSubbandSamples(OverlapBufferReal,
1203*e5436536SAndroid Build Coastguard Worker (useLP) ? NULL : OverlapBufferImag, startBand,
1204*e5436536SAndroid Build Coastguard Worker stopBand, 0, startSlot, reserve);
1205*e5436536SAndroid Build Coastguard Worker source_exp -= reserve;
1206*e5436536SAndroid Build Coastguard Worker }
1207*e5436536SAndroid Build Coastguard Worker
1208*e5436536SAndroid Build Coastguard Worker delta_exp = target_exp - source_exp;
1209*e5436536SAndroid Build Coastguard Worker
1210*e5436536SAndroid Build Coastguard Worker if (delta_exp < 0) { /* x-over-area is dominant */
1211*e5436536SAndroid Build Coastguard Worker startBand = target_lsb;
1212*e5436536SAndroid Build Coastguard Worker stopBand = target_usb;
1213*e5436536SAndroid Build Coastguard Worker delta_exp = -delta_exp;
1214*e5436536SAndroid Build Coastguard Worker
1215*e5436536SAndroid Build Coastguard Worker if (new_lsb > old_lsb) {
1216*e5436536SAndroid Build Coastguard Worker /* The lowband has to be rescaled */
1217*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = EXP2SCALE(source_exp);
1218*e5436536SAndroid Build Coastguard Worker } else {
1219*e5436536SAndroid Build Coastguard Worker /* The highband has to be rescaled */
1220*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.ov_hb_scale = EXP2SCALE(source_exp);
1221*e5436536SAndroid Build Coastguard Worker }
1222*e5436536SAndroid Build Coastguard Worker }
1223*e5436536SAndroid Build Coastguard Worker
1224*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(startBand <= stopBand);
1225*e5436536SAndroid Build Coastguard Worker
1226*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1227*e5436536SAndroid Build Coastguard Worker for (l = 0; l < startSlot; l++) {
1228*e5436536SAndroid Build Coastguard Worker scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand,
1229*e5436536SAndroid Build Coastguard Worker -delta_exp);
1230*e5436536SAndroid Build Coastguard Worker scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand,
1231*e5436536SAndroid Build Coastguard Worker -delta_exp);
1232*e5436536SAndroid Build Coastguard Worker }
1233*e5436536SAndroid Build Coastguard Worker } else
1234*e5436536SAndroid Build Coastguard Worker for (l = 0; l < startSlot; l++) {
1235*e5436536SAndroid Build Coastguard Worker scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand,
1236*e5436536SAndroid Build Coastguard Worker -delta_exp);
1237*e5436536SAndroid Build Coastguard Worker }
1238*e5436536SAndroid Build Coastguard Worker } /* startSlot != 0 */
1239*e5436536SAndroid Build Coastguard Worker
1240*e5436536SAndroid Build Coastguard Worker /*
1241*e5436536SAndroid Build Coastguard Worker Initialize transposer and limiter
1242*e5436536SAndroid Build Coastguard Worker */
1243*e5436536SAndroid Build Coastguard Worker sbrError = resetLppTransposer(
1244*e5436536SAndroid Build Coastguard Worker &hSbrDec->LppTrans, hHeaderData->freqBandData.lowSubband,
1245*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster,
1246*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.freqBandTableNoise,
1247*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.nNfb, hHeaderData->freqBandData.highSubband,
1248*e5436536SAndroid Build Coastguard Worker hHeaderData->sbrProcSmplRate);
1249*e5436536SAndroid Build Coastguard Worker if (sbrError != SBRDEC_OK) return sbrError;
1250*e5436536SAndroid Build Coastguard Worker
1251*e5436536SAndroid Build Coastguard Worker hSbrDec->savedStates = 0;
1252*e5436536SAndroid Build Coastguard Worker
1253*e5436536SAndroid Build Coastguard Worker if ((flags & SBRDEC_USAC_HARMONICSBR) && applySbrProc) {
1254*e5436536SAndroid Build Coastguard Worker sbrError = QmfTransposerReInit(hSbrDec->hHBE,
1255*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.freqBandTable,
1256*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.nSfb);
1257*e5436536SAndroid Build Coastguard Worker if (sbrError != SBRDEC_OK) return sbrError;
1258*e5436536SAndroid Build Coastguard Worker
1259*e5436536SAndroid Build Coastguard Worker /* copy saved states from previous frame to legacy SBR lpc filterstate
1260*e5436536SAndroid Build Coastguard Worker * buffer */
1261*e5436536SAndroid Build Coastguard Worker for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) {
1262*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
1263*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i],
1264*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - LPC_ORDER -
1265*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + i],
1266*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
1267*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
1268*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i],
1269*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - LPC_ORDER -
1270*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + i],
1271*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL));
1272*e5436536SAndroid Build Coastguard Worker }
1273*e5436536SAndroid Build Coastguard Worker hSbrDec->savedStates = 1;
1274*e5436536SAndroid Build Coastguard Worker
1275*e5436536SAndroid Build Coastguard Worker {
1276*e5436536SAndroid Build Coastguard Worker /* map QMF buffer to pointer array (Overlap + Frame)*/
1277*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) {
1278*e5436536SAndroid Build Coastguard Worker pLowBandReal[i] = hSbrDec->LppTrans.lpcFilterStatesRealHBE[i];
1279*e5436536SAndroid Build Coastguard Worker pLowBandImag[i] = hSbrDec->LppTrans.lpcFilterStatesImagHBE[i];
1280*e5436536SAndroid Build Coastguard Worker }
1281*e5436536SAndroid Build Coastguard Worker
1282*e5436536SAndroid Build Coastguard Worker /* map QMF buffer to pointer array (Overlap + Frame)*/
1283*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->hHBE->noCols; i++) {
1284*e5436536SAndroid Build Coastguard Worker pLowBandReal[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1285*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferReal[i];
1286*e5436536SAndroid Build Coastguard Worker pLowBandImag[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1287*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferImag[i];
1288*e5436536SAndroid Build Coastguard Worker }
1289*e5436536SAndroid Build Coastguard Worker
1290*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_QUAD_RATE) {
1291*e5436536SAndroid Build Coastguard Worker if (hFrameData->sbrPatchingMode == 0) {
1292*e5436536SAndroid Build Coastguard Worker int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE);
1293*e5436536SAndroid Build Coastguard Worker
1294*e5436536SAndroid Build Coastguard Worker /* in case of harmonic SBR and no HBE_LP map additional buffer for
1295*e5436536SAndroid Build Coastguard Worker one more frame to pointer arry */
1296*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->hHBE->noCols / 2; i++) {
1297*e5436536SAndroid Build Coastguard Worker pLowBandReal[i + hSbrDec->hHBE->noCols +
1298*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1299*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsReal[i];
1300*e5436536SAndroid Build Coastguard Worker pLowBandImag[i + hSbrDec->hHBE->noCols +
1301*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1302*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsImag[i];
1303*e5436536SAndroid Build Coastguard Worker }
1304*e5436536SAndroid Build Coastguard Worker
1305*e5436536SAndroid Build Coastguard Worker QmfTransposerApply(
1306*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE,
1307*e5436536SAndroid Build Coastguard Worker pLowBandReal + hSbrDec->LppTrans.pSettings->overlap +
1308*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols / 2 + LPC_ORDER,
1309*e5436536SAndroid Build Coastguard Worker pLowBandImag + hSbrDec->LppTrans.pSettings->overlap +
1310*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols / 2 + LPC_ORDER,
1311*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag,
1312*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealHBE,
1313*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagHBE,
1314*e5436536SAndroid Build Coastguard Worker hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb,
1315*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale,
1316*e5436536SAndroid Build Coastguard Worker hHeaderData->timeStep, hFrameData->frameInfo.borders[0],
1317*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF);
1318*e5436536SAndroid Build Coastguard Worker
1319*e5436536SAndroid Build Coastguard Worker copyHarmonicSpectrum(
1320*e5436536SAndroid Build Coastguard Worker xOverQmf, pLowBandReal, pLowBandImag, hSbrDec->hHBE->noCols,
1321*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF);
1322*e5436536SAndroid Build Coastguard Worker }
1323*e5436536SAndroid Build Coastguard Worker } else {
1324*e5436536SAndroid Build Coastguard Worker /* in case of harmonic SBR and no HBE_LP map additional buffer for
1325*e5436536SAndroid Build Coastguard Worker one more frame to pointer arry */
1326*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->hHBE->noCols; i++) {
1327*e5436536SAndroid Build Coastguard Worker pLowBandReal[i + hSbrDec->hHBE->noCols +
1328*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1329*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsReal[i];
1330*e5436536SAndroid Build Coastguard Worker pLowBandImag[i + hSbrDec->hHBE->noCols +
1331*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] =
1332*e5436536SAndroid Build Coastguard Worker hSbrDec->hQmfHBESlotsImag[i];
1333*e5436536SAndroid Build Coastguard Worker }
1334*e5436536SAndroid Build Coastguard Worker
1335*e5436536SAndroid Build Coastguard Worker if (hFrameData->sbrPatchingMode == 0) {
1336*e5436536SAndroid Build Coastguard Worker QmfTransposerApply(
1337*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE,
1338*e5436536SAndroid Build Coastguard Worker pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER,
1339*e5436536SAndroid Build Coastguard Worker pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER,
1340*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag,
1341*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealHBE,
1342*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagHBE,
1343*e5436536SAndroid Build Coastguard Worker 0 /* not required for keeping states updated in this frame*/,
1344*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_lb, hSbrDec->scale_lb,
1345*e5436536SAndroid Build Coastguard Worker &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep,
1346*e5436536SAndroid Build Coastguard Worker hFrameData->frameInfo.borders[0],
1347*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_NOOUT);
1348*e5436536SAndroid Build Coastguard Worker }
1349*e5436536SAndroid Build Coastguard Worker
1350*e5436536SAndroid Build Coastguard Worker QmfTransposerApply(
1351*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE,
1352*e5436536SAndroid Build Coastguard Worker pLowBandReal + hSbrDec->LppTrans.pSettings->overlap +
1353*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols + LPC_ORDER,
1354*e5436536SAndroid Build Coastguard Worker pLowBandImag + hSbrDec->LppTrans.pSettings->overlap +
1355*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols + LPC_ORDER,
1356*e5436536SAndroid Build Coastguard Worker hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag,
1357*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealHBE,
1358*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagHBE,
1359*e5436536SAndroid Build Coastguard Worker hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb,
1360*e5436536SAndroid Build Coastguard Worker hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale,
1361*e5436536SAndroid Build Coastguard Worker hHeaderData->timeStep, hFrameData->frameInfo.borders[0],
1362*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF);
1363*e5436536SAndroid Build Coastguard Worker }
1364*e5436536SAndroid Build Coastguard Worker
1365*e5436536SAndroid Build Coastguard Worker if (hFrameData->sbrPatchingMode == 0) {
1366*e5436536SAndroid Build Coastguard Worker for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) {
1367*e5436536SAndroid Build Coastguard Worker /*
1368*e5436536SAndroid Build Coastguard Worker Store the unmodified qmf Slots values for upper part of spectrum
1369*e5436536SAndroid Build Coastguard Worker (required for LPC filtering) required if next frame is a HBE frame
1370*e5436536SAndroid Build Coastguard Worker */
1371*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsReal[i],
1372*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesRealHBE[i + LPC_ORDER],
1373*e5436536SAndroid Build Coastguard Worker (64) * sizeof(FIXP_DBL));
1374*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsImag[i],
1375*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.lpcFilterStatesImagHBE[i + LPC_ORDER],
1376*e5436536SAndroid Build Coastguard Worker (64) * sizeof(FIXP_DBL));
1377*e5436536SAndroid Build Coastguard Worker }
1378*e5436536SAndroid Build Coastguard Worker
1379*e5436536SAndroid Build Coastguard Worker for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) {
1380*e5436536SAndroid Build Coastguard Worker /*
1381*e5436536SAndroid Build Coastguard Worker Store the unmodified qmf Slots values for upper part of spectrum
1382*e5436536SAndroid Build Coastguard Worker (required for LPC filtering) required if next frame is a HBE frame
1383*e5436536SAndroid Build Coastguard Worker */
1384*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
1385*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->hQmfSlotsReal[i],
1386*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols -
1387*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap +
1388*e5436536SAndroid Build Coastguard Worker i],
1389*e5436536SAndroid Build Coastguard Worker new_lsb * sizeof(FIXP_DBL));
1390*e5436536SAndroid Build Coastguard Worker FDKmemcpy(
1391*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->hQmfSlotsImag[i],
1392*e5436536SAndroid Build Coastguard Worker hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols -
1393*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->overlap +
1394*e5436536SAndroid Build Coastguard Worker i],
1395*e5436536SAndroid Build Coastguard Worker new_lsb * sizeof(FIXP_DBL));
1396*e5436536SAndroid Build Coastguard Worker }
1397*e5436536SAndroid Build Coastguard Worker }
1398*e5436536SAndroid Build Coastguard Worker }
1399*e5436536SAndroid Build Coastguard Worker }
1400*e5436536SAndroid Build Coastguard Worker
1401*e5436536SAndroid Build Coastguard Worker {
1402*e5436536SAndroid Build Coastguard Worker int adapt_lb = 0, diff = 0,
1403*e5436536SAndroid Build Coastguard Worker new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale;
1404*e5436536SAndroid Build Coastguard Worker
1405*e5436536SAndroid Build Coastguard Worker if ((hSbrDec->qmfDomainInCh->scaling.ov_lb_scale !=
1406*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.lb_scale) &&
1407*e5436536SAndroid Build Coastguard Worker startSlot != 0) {
1408*e5436536SAndroid Build Coastguard Worker /* we need to adapt spectrum to have equal scale factor, always larger
1409*e5436536SAndroid Build Coastguard Worker * than zero */
1410*e5436536SAndroid Build Coastguard Worker diff = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale) -
1411*e5436536SAndroid Build Coastguard Worker SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale);
1412*e5436536SAndroid Build Coastguard Worker
1413*e5436536SAndroid Build Coastguard Worker if (diff > 0) {
1414*e5436536SAndroid Build Coastguard Worker adapt_lb = 1;
1415*e5436536SAndroid Build Coastguard Worker diff = -diff;
1416*e5436536SAndroid Build Coastguard Worker new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale;
1417*e5436536SAndroid Build Coastguard Worker }
1418*e5436536SAndroid Build Coastguard Worker
1419*e5436536SAndroid Build Coastguard Worker stopBand = new_lsb;
1420*e5436536SAndroid Build Coastguard Worker }
1421*e5436536SAndroid Build Coastguard Worker
1422*e5436536SAndroid Build Coastguard Worker if (hFrameData->sbrPatchingMode == 1) {
1423*e5436536SAndroid Build Coastguard Worker /* scale states from LegSBR filterstates buffer */
1424*e5436536SAndroid Build Coastguard Worker for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) {
1425*e5436536SAndroid Build Coastguard Worker scaleValues(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], new_lsb,
1426*e5436536SAndroid Build Coastguard Worker diff);
1427*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1428*e5436536SAndroid Build Coastguard Worker scaleValues(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], new_lsb,
1429*e5436536SAndroid Build Coastguard Worker diff);
1430*e5436536SAndroid Build Coastguard Worker }
1431*e5436536SAndroid Build Coastguard Worker }
1432*e5436536SAndroid Build Coastguard Worker
1433*e5436536SAndroid Build Coastguard Worker if (flags & SBRDEC_SYNTAX_USAC) {
1434*e5436536SAndroid Build Coastguard Worker /* get missing states between old and new x_over from LegSBR
1435*e5436536SAndroid Build Coastguard Worker * filterstates buffer */
1436*e5436536SAndroid Build Coastguard Worker /* in case of legacy SBR we leave these values zeroed out */
1437*e5436536SAndroid Build Coastguard Worker for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) {
1438*e5436536SAndroid Build Coastguard Worker FDKmemcpy(&OverlapBufferReal[i][old_lsb],
1439*e5436536SAndroid Build Coastguard Worker &hSbrDec->LppTrans
1440*e5436536SAndroid Build Coastguard Worker .lpcFilterStatesRealLegSBR[LPC_ORDER + i][old_lsb],
1441*e5436536SAndroid Build Coastguard Worker fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL));
1442*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1443*e5436536SAndroid Build Coastguard Worker FDKmemcpy(&OverlapBufferImag[i][old_lsb],
1444*e5436536SAndroid Build Coastguard Worker &hSbrDec->LppTrans
1445*e5436536SAndroid Build Coastguard Worker .lpcFilterStatesImagLegSBR[LPC_ORDER + i][old_lsb],
1446*e5436536SAndroid Build Coastguard Worker fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL));
1447*e5436536SAndroid Build Coastguard Worker }
1448*e5436536SAndroid Build Coastguard Worker }
1449*e5436536SAndroid Build Coastguard Worker }
1450*e5436536SAndroid Build Coastguard Worker
1451*e5436536SAndroid Build Coastguard Worker if (new_lsb > old_lsb) {
1452*e5436536SAndroid Build Coastguard Worker stopBand = old_lsb;
1453*e5436536SAndroid Build Coastguard Worker }
1454*e5436536SAndroid Build Coastguard Worker }
1455*e5436536SAndroid Build Coastguard Worker if ((adapt_lb == 1) && (stopBand > startBand)) {
1456*e5436536SAndroid Build Coastguard Worker for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) {
1457*e5436536SAndroid Build Coastguard Worker scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand,
1458*e5436536SAndroid Build Coastguard Worker diff);
1459*e5436536SAndroid Build Coastguard Worker if (!useLP) {
1460*e5436536SAndroid Build Coastguard Worker scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand,
1461*e5436536SAndroid Build Coastguard Worker diff);
1462*e5436536SAndroid Build Coastguard Worker }
1463*e5436536SAndroid Build Coastguard Worker }
1464*e5436536SAndroid Build Coastguard Worker }
1465*e5436536SAndroid Build Coastguard Worker hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = new_scale;
1466*e5436536SAndroid Build Coastguard Worker }
1467*e5436536SAndroid Build Coastguard Worker
1468*e5436536SAndroid Build Coastguard Worker sbrError = ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable,
1469*e5436536SAndroid Build Coastguard Worker &hHeaderData->freqBandData.noLimiterBands,
1470*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.freqBandTable[0],
1471*e5436536SAndroid Build Coastguard Worker hHeaderData->freqBandData.nSfb[0],
1472*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->patchParam,
1473*e5436536SAndroid Build Coastguard Worker hSbrDec->LppTrans.pSettings->noOfPatches,
1474*e5436536SAndroid Build Coastguard Worker hHeaderData->bs_data.limiterBands,
1475*e5436536SAndroid Build Coastguard Worker hFrameData->sbrPatchingMode,
1476*e5436536SAndroid Build Coastguard Worker GetxOverBandQmfTransposer(hSbrDec->hHBE),
1477*e5436536SAndroid Build Coastguard Worker Get41SbrQmfTransposer(hSbrDec->hHBE));
1478*e5436536SAndroid Build Coastguard Worker
1479*e5436536SAndroid Build Coastguard Worker hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = hFrameData->sbrPatchingMode;
1480*e5436536SAndroid Build Coastguard Worker
1481*e5436536SAndroid Build Coastguard Worker return sbrError;
1482*e5436536SAndroid Build Coastguard Worker }
1483