xref: /aosp_15_r20/external/aac/libSBRdec/src/env_extr.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2018 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  Envelope extraction
106*e5436536SAndroid Build Coastguard Worker   The functions provided by this module are mostly called by applySBR(). After
107*e5436536SAndroid Build Coastguard Worker   it is determined that there is valid SBR data, sbrGetHeaderData() might be
108*e5436536SAndroid Build Coastguard Worker   called if the current SBR data contains an \ref SBR_HEADER_ELEMENT as opposed
109*e5436536SAndroid Build Coastguard Worker   to a \ref SBR_STANDARD_ELEMENT. This function may return various error codes
110*e5436536SAndroid Build Coastguard Worker   as defined in #SBR_HEADER_STATUS . Most importantly it returns HEADER_RESET
111*e5436536SAndroid Build Coastguard Worker   when decoder settings need to be recalculated according to the SBR
112*e5436536SAndroid Build Coastguard Worker   specifications. In that case applySBR() will initiatite the required
113*e5436536SAndroid Build Coastguard Worker   re-configuration.
114*e5436536SAndroid Build Coastguard Worker 
115*e5436536SAndroid Build Coastguard Worker   The header data is stored in a #SBR_HEADER_DATA structure.
116*e5436536SAndroid Build Coastguard Worker 
117*e5436536SAndroid Build Coastguard Worker   The actual SBR data for the current frame is decoded into SBR_FRAME_DATA
118*e5436536SAndroid Build Coastguard Worker   stuctures by sbrGetChannelPairElement() [for stereo streams] and
119*e5436536SAndroid Build Coastguard Worker   sbrGetSingleChannelElement() [for mono streams]. There is no fractional
120*e5436536SAndroid Build Coastguard Worker   arithmetic involved.
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker   Once the information is extracted, the data needs to be further prepared
123*e5436536SAndroid Build Coastguard Worker   before the actual decoding process. This is done in decodeSbrData().
124*e5436536SAndroid Build Coastguard Worker 
125*e5436536SAndroid Build Coastguard Worker   \sa Description of buffer management in applySBR(). \ref documentationOverview
126*e5436536SAndroid Build Coastguard Worker 
127*e5436536SAndroid Build Coastguard Worker   <h1>About the SBR data format:</h1>
128*e5436536SAndroid Build Coastguard Worker 
129*e5436536SAndroid Build Coastguard Worker   Each frame includes SBR data (side chain information), and can be either the
130*e5436536SAndroid Build Coastguard Worker   \ref SBR_HEADER_ELEMENT or the \ref SBR_STANDARD_ELEMENT. Parts of the data
131*e5436536SAndroid Build Coastguard Worker   can be protected by a CRC checksum.
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker   \anchor SBR_HEADER_ELEMENT <h2>The SBR_HEADER_ELEMENT</h2>
134*e5436536SAndroid Build Coastguard Worker 
135*e5436536SAndroid Build Coastguard Worker   The SBR_HEADER_ELEMENT can be transmitted with every frame, however, it
136*e5436536SAndroid Build Coastguard Worker   typically is send every second or so. It contains fundamental information such
137*e5436536SAndroid Build Coastguard Worker   as SBR sampling frequency and frequency range as well as control signals that
138*e5436536SAndroid Build Coastguard Worker   do not require frequent changes. It also includes the \ref
139*e5436536SAndroid Build Coastguard Worker   SBR_STANDARD_ELEMENT.
140*e5436536SAndroid Build Coastguard Worker 
141*e5436536SAndroid Build Coastguard Worker   Depending on the changes between the information in a current
142*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_ELEMENT and the previous SBR_HEADER_ELEMENT, the SBR decoder might
143*e5436536SAndroid Build Coastguard Worker   need to be reset and reconfigured (e.g. new tables need to be calculated).
144*e5436536SAndroid Build Coastguard Worker 
145*e5436536SAndroid Build Coastguard Worker   \anchor SBR_STANDARD_ELEMENT <h2>The SBR_STANDARD_ELEMENT</h2>
146*e5436536SAndroid Build Coastguard Worker 
147*e5436536SAndroid Build Coastguard Worker   This data can be subdivided into "side info" and "raw data", where side info
148*e5436536SAndroid Build Coastguard Worker   is defined as signals needed to decode the raw data and some decoder tuning
149*e5436536SAndroid Build Coastguard Worker   signals. Raw data is referred to as PCM and Huffman coded envelope and noise
150*e5436536SAndroid Build Coastguard Worker   floor estimates. The side info also includes information about the
151*e5436536SAndroid Build Coastguard Worker   time-frequency grid for the current frame.
152*e5436536SAndroid Build Coastguard Worker 
153*e5436536SAndroid Build Coastguard Worker   \sa \ref documentationOverview
154*e5436536SAndroid Build Coastguard Worker */
155*e5436536SAndroid Build Coastguard Worker 
156*e5436536SAndroid Build Coastguard Worker #include "env_extr.h"
157*e5436536SAndroid Build Coastguard Worker 
158*e5436536SAndroid Build Coastguard Worker #include "sbr_ram.h"
159*e5436536SAndroid Build Coastguard Worker #include "sbr_rom.h"
160*e5436536SAndroid Build Coastguard Worker #include "huff_dec.h"
161*e5436536SAndroid Build Coastguard Worker 
162*e5436536SAndroid Build Coastguard Worker #include "psbitdec.h"
163*e5436536SAndroid Build Coastguard Worker 
164*e5436536SAndroid Build Coastguard Worker #define DRM_PARAMETRIC_STEREO 0
165*e5436536SAndroid Build Coastguard Worker #define EXTENSION_ID_PS_CODING 2
166*e5436536SAndroid Build Coastguard Worker 
167*e5436536SAndroid Build Coastguard Worker static int extractPvcFrameInfo(
168*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< bitbuffer handle */
169*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
170*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
171*e5436536SAndroid Build Coastguard Worker                                            frame-info will be stored */
172*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where
173*e5436536SAndroid Build Coastguard Worker                                                      the previous frame-info
174*e5436536SAndroid Build Coastguard Worker                                                      will be stored */
175*e5436536SAndroid Build Coastguard Worker     UCHAR pvc_mode_last,                          /**< PVC mode of last frame */
176*e5436536SAndroid Build Coastguard Worker     const UINT flags);
177*e5436536SAndroid Build Coastguard Worker static int extractFrameInfo(HANDLE_FDK_BITSTREAM hBs,
178*e5436536SAndroid Build Coastguard Worker                             HANDLE_SBR_HEADER_DATA hHeaderData,
179*e5436536SAndroid Build Coastguard Worker                             HANDLE_SBR_FRAME_DATA h_frame_data,
180*e5436536SAndroid Build Coastguard Worker                             const UINT nrOfChannels, const UINT flags);
181*e5436536SAndroid Build Coastguard Worker 
182*e5436536SAndroid Build Coastguard Worker static int sbrGetPvcEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,
183*e5436536SAndroid Build Coastguard Worker                              HANDLE_SBR_FRAME_DATA h_frame_data,
184*e5436536SAndroid Build Coastguard Worker                              HANDLE_FDK_BITSTREAM hBs, const UINT flags,
185*e5436536SAndroid Build Coastguard Worker                              const UINT pvcMode);
186*e5436536SAndroid Build Coastguard Worker static int sbrGetEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,
187*e5436536SAndroid Build Coastguard Worker                           HANDLE_SBR_FRAME_DATA h_frame_data,
188*e5436536SAndroid Build Coastguard Worker                           HANDLE_FDK_BITSTREAM hBs, const UINT flags);
189*e5436536SAndroid Build Coastguard Worker 
190*e5436536SAndroid Build Coastguard Worker static void sbrGetDirectionControlData(HANDLE_SBR_FRAME_DATA hFrameData,
191*e5436536SAndroid Build Coastguard Worker                                        HANDLE_FDK_BITSTREAM hBs,
192*e5436536SAndroid Build Coastguard Worker                                        const UINT flags, const int bs_pvc_mode);
193*e5436536SAndroid Build Coastguard Worker 
194*e5436536SAndroid Build Coastguard Worker static void sbrGetNoiseFloorData(HANDLE_SBR_HEADER_DATA hHeaderData,
195*e5436536SAndroid Build Coastguard Worker                                  HANDLE_SBR_FRAME_DATA h_frame_data,
196*e5436536SAndroid Build Coastguard Worker                                  HANDLE_FDK_BITSTREAM hBs);
197*e5436536SAndroid Build Coastguard Worker 
198*e5436536SAndroid Build Coastguard Worker static int checkFrameInfo(FRAME_INFO *pFrameInfo, int numberOfTimeSlots,
199*e5436536SAndroid Build Coastguard Worker                           int overlap, int timeStep);
200*e5436536SAndroid Build Coastguard Worker 
201*e5436536SAndroid Build Coastguard Worker /* Mapping to std samplerate table according to 14496-3 (4.6.18.2.6) */
202*e5436536SAndroid Build Coastguard Worker typedef struct SR_MAPPING {
203*e5436536SAndroid Build Coastguard Worker   UINT fsRangeLo; /* If fsRangeLo(n+1)>fs>=fsRangeLo(n), it will be mapped to...
204*e5436536SAndroid Build Coastguard Worker                    */
205*e5436536SAndroid Build Coastguard Worker   UINT fsMapped;  /* fsMapped. */
206*e5436536SAndroid Build Coastguard Worker } SR_MAPPING;
207*e5436536SAndroid Build Coastguard Worker 
208*e5436536SAndroid Build Coastguard Worker static const SR_MAPPING stdSampleRatesMapping[] = {
209*e5436536SAndroid Build Coastguard Worker     {0, 8000},      {9391, 11025},  {11502, 12000}, {13856, 16000},
210*e5436536SAndroid Build Coastguard Worker     {18783, 22050}, {23004, 24000}, {27713, 32000}, {37566, 44100},
211*e5436536SAndroid Build Coastguard Worker     {46009, 48000}, {55426, 64000}, {75132, 88200}, {92017, 96000}};
212*e5436536SAndroid Build Coastguard Worker static const SR_MAPPING stdSampleRatesMappingUsac[] = {
213*e5436536SAndroid Build Coastguard Worker     {0, 16000},     {18783, 22050}, {23004, 24000}, {27713, 32000},
214*e5436536SAndroid Build Coastguard Worker     {35777, 40000}, {42000, 44100}, {46009, 48000}, {55426, 64000},
215*e5436536SAndroid Build Coastguard Worker     {75132, 88200}, {92017, 96000}};
216*e5436536SAndroid Build Coastguard Worker 
sbrdec_mapToStdSampleRate(UINT fs,UINT isUsac)217*e5436536SAndroid Build Coastguard Worker UINT sbrdec_mapToStdSampleRate(UINT fs,
218*e5436536SAndroid Build Coastguard Worker                                UINT isUsac) /*!< Output sampling frequency */
219*e5436536SAndroid Build Coastguard Worker {
220*e5436536SAndroid Build Coastguard Worker   UINT fsMapped = fs, tableSize = 0;
221*e5436536SAndroid Build Coastguard Worker   const SR_MAPPING *mappingTable;
222*e5436536SAndroid Build Coastguard Worker   int i;
223*e5436536SAndroid Build Coastguard Worker 
224*e5436536SAndroid Build Coastguard Worker   if (!isUsac) {
225*e5436536SAndroid Build Coastguard Worker     mappingTable = stdSampleRatesMapping;
226*e5436536SAndroid Build Coastguard Worker     tableSize = sizeof(stdSampleRatesMapping) / sizeof(SR_MAPPING);
227*e5436536SAndroid Build Coastguard Worker   } else {
228*e5436536SAndroid Build Coastguard Worker     mappingTable = stdSampleRatesMappingUsac;
229*e5436536SAndroid Build Coastguard Worker     tableSize = sizeof(stdSampleRatesMappingUsac) / sizeof(SR_MAPPING);
230*e5436536SAndroid Build Coastguard Worker   }
231*e5436536SAndroid Build Coastguard Worker 
232*e5436536SAndroid Build Coastguard Worker   for (i = tableSize - 1; i >= 0; i--) {
233*e5436536SAndroid Build Coastguard Worker     if (fs >= mappingTable[i].fsRangeLo) {
234*e5436536SAndroid Build Coastguard Worker       fsMapped = mappingTable[i].fsMapped;
235*e5436536SAndroid Build Coastguard Worker       break;
236*e5436536SAndroid Build Coastguard Worker     }
237*e5436536SAndroid Build Coastguard Worker   }
238*e5436536SAndroid Build Coastguard Worker 
239*e5436536SAndroid Build Coastguard Worker   return (fsMapped);
240*e5436536SAndroid Build Coastguard Worker }
241*e5436536SAndroid Build Coastguard Worker 
242*e5436536SAndroid Build Coastguard Worker SBR_ERROR
initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData,const int sampleRateIn,const int sampleRateOut,const INT downscaleFactor,const int samplesPerFrame,const UINT flags,const int setDefaultHdr)243*e5436536SAndroid Build Coastguard Worker initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn,
244*e5436536SAndroid Build Coastguard Worker                const int sampleRateOut, const INT downscaleFactor,
245*e5436536SAndroid Build Coastguard Worker                const int samplesPerFrame, const UINT flags,
246*e5436536SAndroid Build Coastguard Worker                const int setDefaultHdr) {
247*e5436536SAndroid Build Coastguard Worker   HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData;
248*e5436536SAndroid Build Coastguard Worker   SBR_ERROR sbrError = SBRDEC_OK;
249*e5436536SAndroid Build Coastguard Worker   int numAnalysisBands;
250*e5436536SAndroid Build Coastguard Worker   int sampleRateProc;
251*e5436536SAndroid Build Coastguard Worker 
252*e5436536SAndroid Build Coastguard Worker   if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
253*e5436536SAndroid Build Coastguard Worker     sampleRateProc =
254*e5436536SAndroid Build Coastguard Worker         sbrdec_mapToStdSampleRate(sampleRateOut * downscaleFactor, 0);
255*e5436536SAndroid Build Coastguard Worker   } else {
256*e5436536SAndroid Build Coastguard Worker     sampleRateProc = sampleRateOut * downscaleFactor;
257*e5436536SAndroid Build Coastguard Worker   }
258*e5436536SAndroid Build Coastguard Worker 
259*e5436536SAndroid Build Coastguard Worker   if (sampleRateIn == sampleRateOut) {
260*e5436536SAndroid Build Coastguard Worker     hHeaderData->sbrProcSmplRate = sampleRateProc << 1;
261*e5436536SAndroid Build Coastguard Worker     numAnalysisBands = 32;
262*e5436536SAndroid Build Coastguard Worker   } else {
263*e5436536SAndroid Build Coastguard Worker     hHeaderData->sbrProcSmplRate = sampleRateProc;
264*e5436536SAndroid Build Coastguard Worker     if ((sampleRateOut >> 1) == sampleRateIn) {
265*e5436536SAndroid Build Coastguard Worker       /* 1:2 */
266*e5436536SAndroid Build Coastguard Worker       numAnalysisBands = 32;
267*e5436536SAndroid Build Coastguard Worker     } else if ((sampleRateOut >> 2) == sampleRateIn) {
268*e5436536SAndroid Build Coastguard Worker       /* 1:4 */
269*e5436536SAndroid Build Coastguard Worker       numAnalysisBands = 16;
270*e5436536SAndroid Build Coastguard Worker     } else if ((sampleRateOut * 3) >> 3 == (sampleRateIn * 8) >> 3) {
271*e5436536SAndroid Build Coastguard Worker       /* 3:8, 3/4 core frame length */
272*e5436536SAndroid Build Coastguard Worker       numAnalysisBands = 24;
273*e5436536SAndroid Build Coastguard Worker     } else {
274*e5436536SAndroid Build Coastguard Worker       sbrError = SBRDEC_UNSUPPORTED_CONFIG;
275*e5436536SAndroid Build Coastguard Worker       goto bail;
276*e5436536SAndroid Build Coastguard Worker     }
277*e5436536SAndroid Build Coastguard Worker   }
278*e5436536SAndroid Build Coastguard Worker   numAnalysisBands /= downscaleFactor;
279*e5436536SAndroid Build Coastguard Worker 
280*e5436536SAndroid Build Coastguard Worker   if (setDefaultHdr) {
281*e5436536SAndroid Build Coastguard Worker     /* Fill in default values first */
282*e5436536SAndroid Build Coastguard Worker     hHeaderData->syncState = SBR_NOT_INITIALIZED;
283*e5436536SAndroid Build Coastguard Worker     hHeaderData->status = 0;
284*e5436536SAndroid Build Coastguard Worker     hHeaderData->frameErrorFlag = 0;
285*e5436536SAndroid Build Coastguard Worker 
286*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.ampResolution = 1;
287*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.xover_band = 0;
288*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.sbr_preprocessing = 0;
289*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.pvc_mode = 0;
290*e5436536SAndroid Build Coastguard Worker 
291*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.startFreq = 5;
292*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.stopFreq = 0;
293*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.freqScale =
294*e5436536SAndroid Build Coastguard Worker         0; /* previously 2; for ELD reduced delay bitstreams
295*e5436536SAndroid Build Coastguard Worker            /samplerates initializing of the sbr decoder instance fails if
296*e5436536SAndroid Build Coastguard Worker            freqScale is set to 2 because no master table can be generated; in
297*e5436536SAndroid Build Coastguard Worker            ELD reduced delay bitstreams this value is always 0; gets overwritten
298*e5436536SAndroid Build Coastguard Worker            when header is read */
299*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.alterScale = 1;
300*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.noise_bands = 2;
301*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.limiterBands = 2;
302*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.limiterGains = 2;
303*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.interpolFreq = 1;
304*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_data.smoothingLength = 1;
305*e5436536SAndroid Build Coastguard Worker 
306*e5436536SAndroid Build Coastguard Worker     /* Patch some entries */
307*e5436536SAndroid Build Coastguard Worker     if (sampleRateOut * downscaleFactor >= 96000) {
308*e5436536SAndroid Build Coastguard Worker       hHeaderData->bs_data.startFreq =
309*e5436536SAndroid Build Coastguard Worker           4; /*   having read these frequency values from bit stream before. */
310*e5436536SAndroid Build Coastguard Worker       hHeaderData->bs_data.stopFreq = 3;
311*e5436536SAndroid Build Coastguard Worker     } else if (sampleRateOut * downscaleFactor >
312*e5436536SAndroid Build Coastguard Worker                24000) { /* Trigger an error if SBR is going to be processed
313*e5436536SAndroid Build Coastguard Worker                            without     */
314*e5436536SAndroid Build Coastguard Worker       hHeaderData->bs_data.startFreq =
315*e5436536SAndroid Build Coastguard Worker           7; /*   having read these frequency values from bit stream before. */
316*e5436536SAndroid Build Coastguard Worker       hHeaderData->bs_data.stopFreq = 3;
317*e5436536SAndroid Build Coastguard Worker     }
318*e5436536SAndroid Build Coastguard Worker   }
319*e5436536SAndroid Build Coastguard Worker 
320*e5436536SAndroid Build Coastguard Worker   if ((sampleRateOut >> 2) == sampleRateIn) {
321*e5436536SAndroid Build Coastguard Worker     hHeaderData->timeStep = 4;
322*e5436536SAndroid Build Coastguard Worker   } else {
323*e5436536SAndroid Build Coastguard Worker     hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2;
324*e5436536SAndroid Build Coastguard Worker   }
325*e5436536SAndroid Build Coastguard Worker 
326*e5436536SAndroid Build Coastguard Worker   /* Setup pointers to frequency band tables */
327*e5436536SAndroid Build Coastguard Worker   hFreq->freqBandTable[0] = hFreq->freqBandTableLo;
328*e5436536SAndroid Build Coastguard Worker   hFreq->freqBandTable[1] = hFreq->freqBandTableHi;
329*e5436536SAndroid Build Coastguard Worker 
330*e5436536SAndroid Build Coastguard Worker   /* One SBR timeslot corresponds to the amount of samples equal to the amount
331*e5436536SAndroid Build Coastguard Worker    * of analysis bands, divided by the timestep. */
332*e5436536SAndroid Build Coastguard Worker   hHeaderData->numberTimeSlots =
333*e5436536SAndroid Build Coastguard Worker       (samplesPerFrame / numAnalysisBands) >> (hHeaderData->timeStep - 1);
334*e5436536SAndroid Build Coastguard Worker   if (hHeaderData->numberTimeSlots > (16)) {
335*e5436536SAndroid Build Coastguard Worker     sbrError = SBRDEC_UNSUPPORTED_CONFIG;
336*e5436536SAndroid Build Coastguard Worker   }
337*e5436536SAndroid Build Coastguard Worker 
338*e5436536SAndroid Build Coastguard Worker   hHeaderData->numberOfAnalysisBands = numAnalysisBands;
339*e5436536SAndroid Build Coastguard Worker   if ((sampleRateOut >> 2) == sampleRateIn) {
340*e5436536SAndroid Build Coastguard Worker     hHeaderData->numberTimeSlots <<= 1;
341*e5436536SAndroid Build Coastguard Worker   }
342*e5436536SAndroid Build Coastguard Worker 
343*e5436536SAndroid Build Coastguard Worker bail:
344*e5436536SAndroid Build Coastguard Worker   return sbrError;
345*e5436536SAndroid Build Coastguard Worker }
346*e5436536SAndroid Build Coastguard Worker 
347*e5436536SAndroid Build Coastguard Worker /*!
348*e5436536SAndroid Build Coastguard Worker   \brief   Initialize the SBR_PREV_FRAME_DATA struct
349*e5436536SAndroid Build Coastguard Worker */
initSbrPrevFrameData(HANDLE_SBR_PREV_FRAME_DATA h_prev_data,int timeSlots)350*e5436536SAndroid Build Coastguard Worker void initSbrPrevFrameData(
351*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_PREV_FRAME_DATA
352*e5436536SAndroid Build Coastguard Worker         h_prev_data, /*!< handle to struct SBR_PREV_FRAME_DATA */
353*e5436536SAndroid Build Coastguard Worker     int timeSlots)   /*!< Framelength in SBR-timeslots */
354*e5436536SAndroid Build Coastguard Worker {
355*e5436536SAndroid Build Coastguard Worker   int i;
356*e5436536SAndroid Build Coastguard Worker 
357*e5436536SAndroid Build Coastguard Worker   /* Set previous energy and noise levels to 0 for the case
358*e5436536SAndroid Build Coastguard Worker      that decoding starts in the middle of a bitstream */
359*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < MAX_FREQ_COEFFS; i++)
360*e5436536SAndroid Build Coastguard Worker     h_prev_data->sfb_nrg_prev[i] = (FIXP_DBL)0;
361*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < MAX_NOISE_COEFFS; i++)
362*e5436536SAndroid Build Coastguard Worker     h_prev_data->prevNoiseLevel[i] = (FIXP_DBL)0;
363*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < MAX_INVF_BANDS; i++) h_prev_data->sbr_invf_mode[i] = INVF_OFF;
364*e5436536SAndroid Build Coastguard Worker 
365*e5436536SAndroid Build Coastguard Worker   h_prev_data->stopPos = timeSlots;
366*e5436536SAndroid Build Coastguard Worker   h_prev_data->coupling = COUPLING_OFF;
367*e5436536SAndroid Build Coastguard Worker   h_prev_data->ampRes = 0;
368*e5436536SAndroid Build Coastguard Worker 
369*e5436536SAndroid Build Coastguard Worker   FDKmemclear(&h_prev_data->prevFrameInfo, sizeof(h_prev_data->prevFrameInfo));
370*e5436536SAndroid Build Coastguard Worker }
371*e5436536SAndroid Build Coastguard Worker 
372*e5436536SAndroid Build Coastguard Worker /*!
373*e5436536SAndroid Build Coastguard Worker   \brief   Read header data from bitstream
374*e5436536SAndroid Build Coastguard Worker 
375*e5436536SAndroid Build Coastguard Worker   \return  error status - 0 if ok
376*e5436536SAndroid Build Coastguard Worker */
377*e5436536SAndroid Build Coastguard Worker SBR_HEADER_STATUS
sbrGetHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_FDK_BITSTREAM hBs,const UINT flags,const int fIsSbrData,const UCHAR configMode)378*e5436536SAndroid Build Coastguard Worker sbrGetHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_FDK_BITSTREAM hBs,
379*e5436536SAndroid Build Coastguard Worker                  const UINT flags, const int fIsSbrData,
380*e5436536SAndroid Build Coastguard Worker                  const UCHAR configMode) {
381*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_DATA_BS *pBsData;
382*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_DATA_BS lastHeader;
383*e5436536SAndroid Build Coastguard Worker   SBR_HEADER_DATA_BS_INFO lastInfo;
384*e5436536SAndroid Build Coastguard Worker   int headerExtra1 = 0, headerExtra2 = 0;
385*e5436536SAndroid Build Coastguard Worker 
386*e5436536SAndroid Build Coastguard Worker   /* Read and discard new header in config change detection mode */
387*e5436536SAndroid Build Coastguard Worker   if (configMode & AC_CM_DET_CFG_CHANGE) {
388*e5436536SAndroid Build Coastguard Worker     if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
389*e5436536SAndroid Build Coastguard Worker       /* ampResolution */
390*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 1);
391*e5436536SAndroid Build Coastguard Worker     }
392*e5436536SAndroid Build Coastguard Worker     /* startFreq, stopFreq */
393*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 8);
394*e5436536SAndroid Build Coastguard Worker     if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
395*e5436536SAndroid Build Coastguard Worker       /* xover_band */
396*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 3);
397*e5436536SAndroid Build Coastguard Worker       /* reserved bits */
398*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 2);
399*e5436536SAndroid Build Coastguard Worker     }
400*e5436536SAndroid Build Coastguard Worker     headerExtra1 = FDKreadBit(hBs);
401*e5436536SAndroid Build Coastguard Worker     headerExtra2 = FDKreadBit(hBs);
402*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 5 * headerExtra1 + 6 * headerExtra2);
403*e5436536SAndroid Build Coastguard Worker 
404*e5436536SAndroid Build Coastguard Worker     return HEADER_OK;
405*e5436536SAndroid Build Coastguard Worker   }
406*e5436536SAndroid Build Coastguard Worker 
407*e5436536SAndroid Build Coastguard Worker   /* Copy SBR bit stream header to temporary header */
408*e5436536SAndroid Build Coastguard Worker   lastHeader = hHeaderData->bs_data;
409*e5436536SAndroid Build Coastguard Worker   lastInfo = hHeaderData->bs_info;
410*e5436536SAndroid Build Coastguard Worker 
411*e5436536SAndroid Build Coastguard Worker   /* Read new header from bitstream */
412*e5436536SAndroid Build Coastguard Worker   if ((flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) && !fIsSbrData) {
413*e5436536SAndroid Build Coastguard Worker     pBsData = &hHeaderData->bs_dflt;
414*e5436536SAndroid Build Coastguard Worker   } else {
415*e5436536SAndroid Build Coastguard Worker     pBsData = &hHeaderData->bs_data;
416*e5436536SAndroid Build Coastguard Worker   }
417*e5436536SAndroid Build Coastguard Worker 
418*e5436536SAndroid Build Coastguard Worker   if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
419*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.ampResolution = FDKreadBits(hBs, 1);
420*e5436536SAndroid Build Coastguard Worker   }
421*e5436536SAndroid Build Coastguard Worker 
422*e5436536SAndroid Build Coastguard Worker   pBsData->startFreq = FDKreadBits(hBs, 4);
423*e5436536SAndroid Build Coastguard Worker   pBsData->stopFreq = FDKreadBits(hBs, 4);
424*e5436536SAndroid Build Coastguard Worker 
425*e5436536SAndroid Build Coastguard Worker   if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
426*e5436536SAndroid Build Coastguard Worker     hHeaderData->bs_info.xover_band = FDKreadBits(hBs, 3);
427*e5436536SAndroid Build Coastguard Worker     FDKreadBits(hBs, 2);
428*e5436536SAndroid Build Coastguard Worker   }
429*e5436536SAndroid Build Coastguard Worker 
430*e5436536SAndroid Build Coastguard Worker   headerExtra1 = FDKreadBits(hBs, 1);
431*e5436536SAndroid Build Coastguard Worker   headerExtra2 = FDKreadBits(hBs, 1);
432*e5436536SAndroid Build Coastguard Worker 
433*e5436536SAndroid Build Coastguard Worker   /* Handle extra header information */
434*e5436536SAndroid Build Coastguard Worker   if (headerExtra1) {
435*e5436536SAndroid Build Coastguard Worker     pBsData->freqScale = FDKreadBits(hBs, 2);
436*e5436536SAndroid Build Coastguard Worker     pBsData->alterScale = FDKreadBits(hBs, 1);
437*e5436536SAndroid Build Coastguard Worker     pBsData->noise_bands = FDKreadBits(hBs, 2);
438*e5436536SAndroid Build Coastguard Worker   } else {
439*e5436536SAndroid Build Coastguard Worker     pBsData->freqScale = 2;
440*e5436536SAndroid Build Coastguard Worker     pBsData->alterScale = 1;
441*e5436536SAndroid Build Coastguard Worker     pBsData->noise_bands = 2;
442*e5436536SAndroid Build Coastguard Worker   }
443*e5436536SAndroid Build Coastguard Worker 
444*e5436536SAndroid Build Coastguard Worker   if (headerExtra2) {
445*e5436536SAndroid Build Coastguard Worker     pBsData->limiterBands = FDKreadBits(hBs, 2);
446*e5436536SAndroid Build Coastguard Worker     pBsData->limiterGains = FDKreadBits(hBs, 2);
447*e5436536SAndroid Build Coastguard Worker     pBsData->interpolFreq = FDKreadBits(hBs, 1);
448*e5436536SAndroid Build Coastguard Worker     pBsData->smoothingLength = FDKreadBits(hBs, 1);
449*e5436536SAndroid Build Coastguard Worker   } else {
450*e5436536SAndroid Build Coastguard Worker     pBsData->limiterBands = 2;
451*e5436536SAndroid Build Coastguard Worker     pBsData->limiterGains = 2;
452*e5436536SAndroid Build Coastguard Worker     pBsData->interpolFreq = 1;
453*e5436536SAndroid Build Coastguard Worker     pBsData->smoothingLength = 1;
454*e5436536SAndroid Build Coastguard Worker   }
455*e5436536SAndroid Build Coastguard Worker 
456*e5436536SAndroid Build Coastguard Worker   /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */
457*e5436536SAndroid Build Coastguard Worker   if (hHeaderData->syncState < SBR_HEADER ||
458*e5436536SAndroid Build Coastguard Worker       lastHeader.startFreq != pBsData->startFreq ||
459*e5436536SAndroid Build Coastguard Worker       lastHeader.stopFreq != pBsData->stopFreq ||
460*e5436536SAndroid Build Coastguard Worker       lastHeader.freqScale != pBsData->freqScale ||
461*e5436536SAndroid Build Coastguard Worker       lastHeader.alterScale != pBsData->alterScale ||
462*e5436536SAndroid Build Coastguard Worker       lastHeader.noise_bands != pBsData->noise_bands ||
463*e5436536SAndroid Build Coastguard Worker       lastInfo.xover_band != hHeaderData->bs_info.xover_band) {
464*e5436536SAndroid Build Coastguard Worker     return HEADER_RESET; /* New settings */
465*e5436536SAndroid Build Coastguard Worker   }
466*e5436536SAndroid Build Coastguard Worker 
467*e5436536SAndroid Build Coastguard Worker   return HEADER_OK;
468*e5436536SAndroid Build Coastguard Worker }
469*e5436536SAndroid Build Coastguard Worker 
470*e5436536SAndroid Build Coastguard Worker /*!
471*e5436536SAndroid Build Coastguard Worker   \brief   Get missing harmonics parameters (only used for AAC+SBR)
472*e5436536SAndroid Build Coastguard Worker 
473*e5436536SAndroid Build Coastguard Worker   \return  error status - 0 if ok
474*e5436536SAndroid Build Coastguard Worker */
sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA hFrameData,HANDLE_FDK_BITSTREAM hBs,const UINT flags)475*e5436536SAndroid Build Coastguard Worker int sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData,
476*e5436536SAndroid Build Coastguard Worker                              HANDLE_SBR_FRAME_DATA hFrameData,
477*e5436536SAndroid Build Coastguard Worker                              HANDLE_FDK_BITSTREAM hBs, const UINT flags) {
478*e5436536SAndroid Build Coastguard Worker   int i, bitsRead = 0;
479*e5436536SAndroid Build Coastguard Worker 
480*e5436536SAndroid Build Coastguard Worker   int add_harmonic_flag = FDKreadBits(hBs, 1);
481*e5436536SAndroid Build Coastguard Worker   bitsRead++;
482*e5436536SAndroid Build Coastguard Worker 
483*e5436536SAndroid Build Coastguard Worker   if (add_harmonic_flag) {
484*e5436536SAndroid Build Coastguard Worker     int nSfb = hHeaderData->freqBandData.nSfb[1];
485*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) {
486*e5436536SAndroid Build Coastguard Worker       /* read maximum 32 bits and align them to the MSB */
487*e5436536SAndroid Build Coastguard Worker       int readBits = fMin(32, nSfb);
488*e5436536SAndroid Build Coastguard Worker       nSfb -= readBits;
489*e5436536SAndroid Build Coastguard Worker       if (readBits > 0) {
490*e5436536SAndroid Build Coastguard Worker         hFrameData->addHarmonics[i] = FDKreadBits(hBs, readBits)
491*e5436536SAndroid Build Coastguard Worker                                       << (32 - readBits);
492*e5436536SAndroid Build Coastguard Worker       } else {
493*e5436536SAndroid Build Coastguard Worker         hFrameData->addHarmonics[i] = 0;
494*e5436536SAndroid Build Coastguard Worker       }
495*e5436536SAndroid Build Coastguard Worker 
496*e5436536SAndroid Build Coastguard Worker       bitsRead += readBits;
497*e5436536SAndroid Build Coastguard Worker     }
498*e5436536SAndroid Build Coastguard Worker     /* bs_pvc_mode = 0 for Rsvd50 */
499*e5436536SAndroid Build Coastguard Worker     if (flags & SBRDEC_SYNTAX_USAC) {
500*e5436536SAndroid Build Coastguard Worker       if (hHeaderData->bs_info.pvc_mode) {
501*e5436536SAndroid Build Coastguard Worker         int bs_sinusoidal_position = 31;
502*e5436536SAndroid Build Coastguard Worker         if (FDKreadBit(hBs) /* bs_sinusoidal_position_flag */) {
503*e5436536SAndroid Build Coastguard Worker           bs_sinusoidal_position = FDKreadBits(hBs, 5);
504*e5436536SAndroid Build Coastguard Worker         }
505*e5436536SAndroid Build Coastguard Worker         hFrameData->sinusoidal_position = bs_sinusoidal_position;
506*e5436536SAndroid Build Coastguard Worker       }
507*e5436536SAndroid Build Coastguard Worker     }
508*e5436536SAndroid Build Coastguard Worker   } else {
509*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++)
510*e5436536SAndroid Build Coastguard Worker       hFrameData->addHarmonics[i] = 0;
511*e5436536SAndroid Build Coastguard Worker   }
512*e5436536SAndroid Build Coastguard Worker 
513*e5436536SAndroid Build Coastguard Worker   return (bitsRead);
514*e5436536SAndroid Build Coastguard Worker }
515*e5436536SAndroid Build Coastguard Worker 
516*e5436536SAndroid Build Coastguard Worker /*!
517*e5436536SAndroid Build Coastguard Worker   \brief      Reads extension data from the bitstream
518*e5436536SAndroid Build Coastguard Worker 
519*e5436536SAndroid Build Coastguard Worker   The bitstream format allows up to 4 kinds of extended data element.
520*e5436536SAndroid Build Coastguard Worker   Extended data may contain several elements, each identified by a 2-bit-ID.
521*e5436536SAndroid Build Coastguard Worker   So far, no extended data elements are defined hence the first 2 parameters
522*e5436536SAndroid Build Coastguard Worker   are unused. The data should be skipped in order to update the number
523*e5436536SAndroid Build Coastguard Worker   of read bits for the consistency check in applySBR().
524*e5436536SAndroid Build Coastguard Worker */
extractExtendedData(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_FDK_BITSTREAM hBs,HANDLE_PS_DEC hParametricStereoDec)525*e5436536SAndroid Build Coastguard Worker static int extractExtendedData(
526*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< handle to SBR header */
527*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs            /*!< Handle to the bit buffer */
528*e5436536SAndroid Build Coastguard Worker     ,
529*e5436536SAndroid Build Coastguard Worker     HANDLE_PS_DEC hParametricStereoDec /*!< Parametric Stereo Decoder */
530*e5436536SAndroid Build Coastguard Worker ) {
531*e5436536SAndroid Build Coastguard Worker   INT nBitsLeft;
532*e5436536SAndroid Build Coastguard Worker   int extended_data;
533*e5436536SAndroid Build Coastguard Worker   int i, frameOk = 1;
534*e5436536SAndroid Build Coastguard Worker 
535*e5436536SAndroid Build Coastguard Worker   extended_data = FDKreadBits(hBs, 1);
536*e5436536SAndroid Build Coastguard Worker 
537*e5436536SAndroid Build Coastguard Worker   if (extended_data) {
538*e5436536SAndroid Build Coastguard Worker     int cnt;
539*e5436536SAndroid Build Coastguard Worker     int bPsRead = 0;
540*e5436536SAndroid Build Coastguard Worker 
541*e5436536SAndroid Build Coastguard Worker     cnt = FDKreadBits(hBs, 4);
542*e5436536SAndroid Build Coastguard Worker     if (cnt == (1 << 4) - 1) cnt += FDKreadBits(hBs, 8);
543*e5436536SAndroid Build Coastguard Worker 
544*e5436536SAndroid Build Coastguard Worker     nBitsLeft = 8 * cnt;
545*e5436536SAndroid Build Coastguard Worker 
546*e5436536SAndroid Build Coastguard Worker     /* sanity check for cnt */
547*e5436536SAndroid Build Coastguard Worker     if (nBitsLeft > (INT)FDKgetValidBits(hBs)) {
548*e5436536SAndroid Build Coastguard Worker       /* limit nBitsLeft */
549*e5436536SAndroid Build Coastguard Worker       nBitsLeft = (INT)FDKgetValidBits(hBs);
550*e5436536SAndroid Build Coastguard Worker       /* set frame error */
551*e5436536SAndroid Build Coastguard Worker       frameOk = 0;
552*e5436536SAndroid Build Coastguard Worker     }
553*e5436536SAndroid Build Coastguard Worker 
554*e5436536SAndroid Build Coastguard Worker     while (nBitsLeft > 7) {
555*e5436536SAndroid Build Coastguard Worker       int extension_id = FDKreadBits(hBs, 2);
556*e5436536SAndroid Build Coastguard Worker       nBitsLeft -= 2;
557*e5436536SAndroid Build Coastguard Worker 
558*e5436536SAndroid Build Coastguard Worker       switch (extension_id) {
559*e5436536SAndroid Build Coastguard Worker         case EXTENSION_ID_PS_CODING:
560*e5436536SAndroid Build Coastguard Worker 
561*e5436536SAndroid Build Coastguard Worker           /* Read PS data from bitstream */
562*e5436536SAndroid Build Coastguard Worker 
563*e5436536SAndroid Build Coastguard Worker           if (hParametricStereoDec != NULL) {
564*e5436536SAndroid Build Coastguard Worker             if (bPsRead &&
565*e5436536SAndroid Build Coastguard Worker                 !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot]
566*e5436536SAndroid Build Coastguard Worker                      .mpeg.bPsHeaderValid) {
567*e5436536SAndroid Build Coastguard Worker               cnt = nBitsLeft >> 3; /* number of remaining bytes */
568*e5436536SAndroid Build Coastguard Worker               for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8);
569*e5436536SAndroid Build Coastguard Worker               nBitsLeft -= cnt * 8;
570*e5436536SAndroid Build Coastguard Worker             } else {
571*e5436536SAndroid Build Coastguard Worker               nBitsLeft -=
572*e5436536SAndroid Build Coastguard Worker                   (INT)ReadPsData(hParametricStereoDec, hBs, nBitsLeft);
573*e5436536SAndroid Build Coastguard Worker               bPsRead = 1;
574*e5436536SAndroid Build Coastguard Worker             }
575*e5436536SAndroid Build Coastguard Worker           }
576*e5436536SAndroid Build Coastguard Worker 
577*e5436536SAndroid Build Coastguard Worker           /* parametric stereo detected, could set channelMode accordingly here
578*e5436536SAndroid Build Coastguard Worker            */
579*e5436536SAndroid Build Coastguard Worker           /*                                                                     */
580*e5436536SAndroid Build Coastguard Worker           /* "The usage of this parametric stereo extension to HE-AAC is */
581*e5436536SAndroid Build Coastguard Worker           /* signalled implicitly in the bitstream. Hence, if an sbr_extension()
582*e5436536SAndroid Build Coastguard Worker            */
583*e5436536SAndroid Build Coastguard Worker           /* with bs_extension_id==EXTENSION_ID_PS is found in the SBR part of
584*e5436536SAndroid Build Coastguard Worker            */
585*e5436536SAndroid Build Coastguard Worker           /* the bitstream, a decoder supporting the combination of SBR and PS
586*e5436536SAndroid Build Coastguard Worker            */
587*e5436536SAndroid Build Coastguard Worker           /* shall operate the PS tool to generate a stereo output signal." */
588*e5436536SAndroid Build Coastguard Worker           /* source: ISO/IEC 14496-3:2001/FDAM 2:2004(E) */
589*e5436536SAndroid Build Coastguard Worker 
590*e5436536SAndroid Build Coastguard Worker           break;
591*e5436536SAndroid Build Coastguard Worker 
592*e5436536SAndroid Build Coastguard Worker         default:
593*e5436536SAndroid Build Coastguard Worker           cnt = nBitsLeft >> 3; /* number of remaining bytes */
594*e5436536SAndroid Build Coastguard Worker           for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8);
595*e5436536SAndroid Build Coastguard Worker           nBitsLeft -= cnt * 8;
596*e5436536SAndroid Build Coastguard Worker           break;
597*e5436536SAndroid Build Coastguard Worker       }
598*e5436536SAndroid Build Coastguard Worker     }
599*e5436536SAndroid Build Coastguard Worker 
600*e5436536SAndroid Build Coastguard Worker     if (nBitsLeft < 0) {
601*e5436536SAndroid Build Coastguard Worker       frameOk = 0;
602*e5436536SAndroid Build Coastguard Worker       goto bail;
603*e5436536SAndroid Build Coastguard Worker     } else {
604*e5436536SAndroid Build Coastguard Worker       /* Read fill bits for byte alignment */
605*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, nBitsLeft);
606*e5436536SAndroid Build Coastguard Worker     }
607*e5436536SAndroid Build Coastguard Worker   }
608*e5436536SAndroid Build Coastguard Worker 
609*e5436536SAndroid Build Coastguard Worker bail:
610*e5436536SAndroid Build Coastguard Worker   return (frameOk);
611*e5436536SAndroid Build Coastguard Worker }
612*e5436536SAndroid Build Coastguard Worker 
613*e5436536SAndroid Build Coastguard Worker /*!
614*e5436536SAndroid Build Coastguard Worker   \brief      Read bitstream elements of a SBR channel element
615*e5436536SAndroid Build Coastguard Worker   \return     SbrFrameOK
616*e5436536SAndroid Build Coastguard Worker */
sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA hFrameDataLeft,HANDLE_SBR_FRAME_DATA hFrameDataRight,HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev,UCHAR pvc_mode_last,HANDLE_FDK_BITSTREAM hBs,HANDLE_PS_DEC hParametricStereoDec,const UINT flags,const int overlap)617*e5436536SAndroid Build Coastguard Worker int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData,
618*e5436536SAndroid Build Coastguard Worker                          HANDLE_SBR_FRAME_DATA hFrameDataLeft,
619*e5436536SAndroid Build Coastguard Worker                          HANDLE_SBR_FRAME_DATA hFrameDataRight,
620*e5436536SAndroid Build Coastguard Worker                          HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev,
621*e5436536SAndroid Build Coastguard Worker                          UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBs,
622*e5436536SAndroid Build Coastguard Worker                          HANDLE_PS_DEC hParametricStereoDec, const UINT flags,
623*e5436536SAndroid Build Coastguard Worker                          const int overlap) {
624*e5436536SAndroid Build Coastguard Worker   int i, bs_coupling = COUPLING_OFF;
625*e5436536SAndroid Build Coastguard Worker   const int nCh = (hFrameDataRight == NULL) ? 1 : 2;
626*e5436536SAndroid Build Coastguard Worker 
627*e5436536SAndroid Build Coastguard Worker   if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
628*e5436536SAndroid Build Coastguard Worker     /* Reserved bits */
629*e5436536SAndroid Build Coastguard Worker     if (FDKreadBits(hBs, 1)) { /* bs_data_extra */
630*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 4);
631*e5436536SAndroid Build Coastguard Worker       if ((flags & SBRDEC_SYNTAX_SCAL) || (nCh == 2)) {
632*e5436536SAndroid Build Coastguard Worker         FDKreadBits(hBs, 4);
633*e5436536SAndroid Build Coastguard Worker       }
634*e5436536SAndroid Build Coastguard Worker     }
635*e5436536SAndroid Build Coastguard Worker   }
636*e5436536SAndroid Build Coastguard Worker 
637*e5436536SAndroid Build Coastguard Worker   if (nCh == 2) {
638*e5436536SAndroid Build Coastguard Worker     /* Read coupling flag */
639*e5436536SAndroid Build Coastguard Worker     bs_coupling = FDKreadBits(hBs, 1);
640*e5436536SAndroid Build Coastguard Worker     if (bs_coupling) {
641*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->coupling = COUPLING_LEVEL;
642*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->coupling = COUPLING_BAL;
643*e5436536SAndroid Build Coastguard Worker     } else {
644*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->coupling = COUPLING_OFF;
645*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->coupling = COUPLING_OFF;
646*e5436536SAndroid Build Coastguard Worker     }
647*e5436536SAndroid Build Coastguard Worker   } else {
648*e5436536SAndroid Build Coastguard Worker     if (flags & SBRDEC_SYNTAX_SCAL) {
649*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 1); /* bs_coupling */
650*e5436536SAndroid Build Coastguard Worker     }
651*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->coupling = COUPLING_OFF;
652*e5436536SAndroid Build Coastguard Worker   }
653*e5436536SAndroid Build Coastguard Worker 
654*e5436536SAndroid Build Coastguard Worker   if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
655*e5436536SAndroid Build Coastguard Worker     if (flags & SBRDEC_USAC_HARMONICSBR) {
656*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->sbrPatchingMode = FDKreadBit(hBs);
657*e5436536SAndroid Build Coastguard Worker       if (hFrameDataLeft->sbrPatchingMode == 0) {
658*e5436536SAndroid Build Coastguard Worker         hFrameDataLeft->sbrOversamplingFlag = FDKreadBit(hBs);
659*e5436536SAndroid Build Coastguard Worker         if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */
660*e5436536SAndroid Build Coastguard Worker           hFrameDataLeft->sbrPitchInBins = FDKreadBits(hBs, 7);
661*e5436536SAndroid Build Coastguard Worker         } else {
662*e5436536SAndroid Build Coastguard Worker           hFrameDataLeft->sbrPitchInBins = 0;
663*e5436536SAndroid Build Coastguard Worker         }
664*e5436536SAndroid Build Coastguard Worker       } else {
665*e5436536SAndroid Build Coastguard Worker         hFrameDataLeft->sbrOversamplingFlag = 0;
666*e5436536SAndroid Build Coastguard Worker         hFrameDataLeft->sbrPitchInBins = 0;
667*e5436536SAndroid Build Coastguard Worker       }
668*e5436536SAndroid Build Coastguard Worker 
669*e5436536SAndroid Build Coastguard Worker       if (nCh == 2) {
670*e5436536SAndroid Build Coastguard Worker         if (bs_coupling) {
671*e5436536SAndroid Build Coastguard Worker           hFrameDataRight->sbrPatchingMode = hFrameDataLeft->sbrPatchingMode;
672*e5436536SAndroid Build Coastguard Worker           hFrameDataRight->sbrOversamplingFlag =
673*e5436536SAndroid Build Coastguard Worker               hFrameDataLeft->sbrOversamplingFlag;
674*e5436536SAndroid Build Coastguard Worker           hFrameDataRight->sbrPitchInBins = hFrameDataLeft->sbrPitchInBins;
675*e5436536SAndroid Build Coastguard Worker         } else {
676*e5436536SAndroid Build Coastguard Worker           hFrameDataRight->sbrPatchingMode = FDKreadBit(hBs);
677*e5436536SAndroid Build Coastguard Worker           if (hFrameDataRight->sbrPatchingMode == 0) {
678*e5436536SAndroid Build Coastguard Worker             hFrameDataRight->sbrOversamplingFlag = FDKreadBit(hBs);
679*e5436536SAndroid Build Coastguard Worker             if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */
680*e5436536SAndroid Build Coastguard Worker               hFrameDataRight->sbrPitchInBins = FDKreadBits(hBs, 7);
681*e5436536SAndroid Build Coastguard Worker             } else {
682*e5436536SAndroid Build Coastguard Worker               hFrameDataRight->sbrPitchInBins = 0;
683*e5436536SAndroid Build Coastguard Worker             }
684*e5436536SAndroid Build Coastguard Worker           } else {
685*e5436536SAndroid Build Coastguard Worker             hFrameDataRight->sbrOversamplingFlag = 0;
686*e5436536SAndroid Build Coastguard Worker             hFrameDataRight->sbrPitchInBins = 0;
687*e5436536SAndroid Build Coastguard Worker           }
688*e5436536SAndroid Build Coastguard Worker         }
689*e5436536SAndroid Build Coastguard Worker       }
690*e5436536SAndroid Build Coastguard Worker     } else {
691*e5436536SAndroid Build Coastguard Worker       if (nCh == 2) {
692*e5436536SAndroid Build Coastguard Worker         hFrameDataRight->sbrPatchingMode = 1;
693*e5436536SAndroid Build Coastguard Worker         hFrameDataRight->sbrOversamplingFlag = 0;
694*e5436536SAndroid Build Coastguard Worker         hFrameDataRight->sbrPitchInBins = 0;
695*e5436536SAndroid Build Coastguard Worker       }
696*e5436536SAndroid Build Coastguard Worker 
697*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->sbrPatchingMode = 1;
698*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->sbrOversamplingFlag = 0;
699*e5436536SAndroid Build Coastguard Worker       hFrameDataLeft->sbrPitchInBins = 0;
700*e5436536SAndroid Build Coastguard Worker     }
701*e5436536SAndroid Build Coastguard Worker   } else {
702*e5436536SAndroid Build Coastguard Worker     if (nCh == 2) {
703*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->sbrPatchingMode = 1;
704*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->sbrOversamplingFlag = 0;
705*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->sbrPitchInBins = 0;
706*e5436536SAndroid Build Coastguard Worker     }
707*e5436536SAndroid Build Coastguard Worker 
708*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->sbrPatchingMode = 1;
709*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->sbrOversamplingFlag = 0;
710*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->sbrPitchInBins = 0;
711*e5436536SAndroid Build Coastguard Worker   }
712*e5436536SAndroid Build Coastguard Worker 
713*e5436536SAndroid Build Coastguard Worker   /*
714*e5436536SAndroid Build Coastguard Worker     sbr_grid(): Grid control
715*e5436536SAndroid Build Coastguard Worker   */
716*e5436536SAndroid Build Coastguard Worker   if (hHeaderData->bs_info.pvc_mode) {
717*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(nCh == 1); /* PVC not possible for CPE */
718*e5436536SAndroid Build Coastguard Worker     if (!extractPvcFrameInfo(hBs, hHeaderData, hFrameDataLeft,
719*e5436536SAndroid Build Coastguard Worker                              hFrameDataLeftPrev, pvc_mode_last, flags))
720*e5436536SAndroid Build Coastguard Worker       return 0;
721*e5436536SAndroid Build Coastguard Worker 
722*e5436536SAndroid Build Coastguard Worker     if (!checkFrameInfo(&hFrameDataLeft->frameInfo,
723*e5436536SAndroid Build Coastguard Worker                         hHeaderData->numberTimeSlots, overlap,
724*e5436536SAndroid Build Coastguard Worker                         hHeaderData->timeStep))
725*e5436536SAndroid Build Coastguard Worker       return 0;
726*e5436536SAndroid Build Coastguard Worker   } else {
727*e5436536SAndroid Build Coastguard Worker     if (!extractFrameInfo(hBs, hHeaderData, hFrameDataLeft, 1, flags)) return 0;
728*e5436536SAndroid Build Coastguard Worker 
729*e5436536SAndroid Build Coastguard Worker     if (!checkFrameInfo(&hFrameDataLeft->frameInfo,
730*e5436536SAndroid Build Coastguard Worker                         hHeaderData->numberTimeSlots, overlap,
731*e5436536SAndroid Build Coastguard Worker                         hHeaderData->timeStep))
732*e5436536SAndroid Build Coastguard Worker       return 0;
733*e5436536SAndroid Build Coastguard Worker   }
734*e5436536SAndroid Build Coastguard Worker   if (nCh == 2) {
735*e5436536SAndroid Build Coastguard Worker     if (hFrameDataLeft->coupling) {
736*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo,
737*e5436536SAndroid Build Coastguard Worker                 sizeof(FRAME_INFO));
738*e5436536SAndroid Build Coastguard Worker       hFrameDataRight->ampResolutionCurrentFrame =
739*e5436536SAndroid Build Coastguard Worker           hFrameDataLeft->ampResolutionCurrentFrame;
740*e5436536SAndroid Build Coastguard Worker     } else {
741*e5436536SAndroid Build Coastguard Worker       if (!extractFrameInfo(hBs, hHeaderData, hFrameDataRight, 2, flags))
742*e5436536SAndroid Build Coastguard Worker         return 0;
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker       if (!checkFrameInfo(&hFrameDataRight->frameInfo,
745*e5436536SAndroid Build Coastguard Worker                           hHeaderData->numberTimeSlots, overlap,
746*e5436536SAndroid Build Coastguard Worker                           hHeaderData->timeStep))
747*e5436536SAndroid Build Coastguard Worker         return 0;
748*e5436536SAndroid Build Coastguard Worker     }
749*e5436536SAndroid Build Coastguard Worker   }
750*e5436536SAndroid Build Coastguard Worker 
751*e5436536SAndroid Build Coastguard Worker   /*
752*e5436536SAndroid Build Coastguard Worker     sbr_dtdf(): Fetch domain vectors (time or frequency direction for
753*e5436536SAndroid Build Coastguard Worker     delta-coding)
754*e5436536SAndroid Build Coastguard Worker   */
755*e5436536SAndroid Build Coastguard Worker   sbrGetDirectionControlData(hFrameDataLeft, hBs, flags,
756*e5436536SAndroid Build Coastguard Worker                              hHeaderData->bs_info.pvc_mode);
757*e5436536SAndroid Build Coastguard Worker   if (nCh == 2) {
758*e5436536SAndroid Build Coastguard Worker     sbrGetDirectionControlData(hFrameDataRight, hBs, flags, 0);
759*e5436536SAndroid Build Coastguard Worker   }
760*e5436536SAndroid Build Coastguard Worker 
761*e5436536SAndroid Build Coastguard Worker   /* sbr_invf() */
762*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
763*e5436536SAndroid Build Coastguard Worker     hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2);
764*e5436536SAndroid Build Coastguard Worker   }
765*e5436536SAndroid Build Coastguard Worker   if (nCh == 2) {
766*e5436536SAndroid Build Coastguard Worker     if (hFrameDataLeft->coupling) {
767*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
768*e5436536SAndroid Build Coastguard Worker         hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i];
769*e5436536SAndroid Build Coastguard Worker       }
770*e5436536SAndroid Build Coastguard Worker     } else {
771*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
772*e5436536SAndroid Build Coastguard Worker         hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2);
773*e5436536SAndroid Build Coastguard Worker       }
774*e5436536SAndroid Build Coastguard Worker     }
775*e5436536SAndroid Build Coastguard Worker   }
776*e5436536SAndroid Build Coastguard Worker 
777*e5436536SAndroid Build Coastguard Worker   if (nCh == 1) {
778*e5436536SAndroid Build Coastguard Worker     if (hHeaderData->bs_info.pvc_mode) {
779*e5436536SAndroid Build Coastguard Worker       if (!sbrGetPvcEnvelope(hHeaderData, hFrameDataLeft, hBs, flags,
780*e5436536SAndroid Build Coastguard Worker                              hHeaderData->bs_info.pvc_mode))
781*e5436536SAndroid Build Coastguard Worker         return 0;
782*e5436536SAndroid Build Coastguard Worker     } else if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags))
783*e5436536SAndroid Build Coastguard Worker       return 0;
784*e5436536SAndroid Build Coastguard Worker 
785*e5436536SAndroid Build Coastguard Worker     sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
786*e5436536SAndroid Build Coastguard Worker   } else if (hFrameDataLeft->coupling) {
787*e5436536SAndroid Build Coastguard Worker     if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) {
788*e5436536SAndroid Build Coastguard Worker       return 0;
789*e5436536SAndroid Build Coastguard Worker     }
790*e5436536SAndroid Build Coastguard Worker 
791*e5436536SAndroid Build Coastguard Worker     sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
792*e5436536SAndroid Build Coastguard Worker 
793*e5436536SAndroid Build Coastguard Worker     if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) {
794*e5436536SAndroid Build Coastguard Worker       return 0;
795*e5436536SAndroid Build Coastguard Worker     }
796*e5436536SAndroid Build Coastguard Worker     sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs);
797*e5436536SAndroid Build Coastguard Worker   } else { /* nCh == 2 && no coupling */
798*e5436536SAndroid Build Coastguard Worker 
799*e5436536SAndroid Build Coastguard Worker     if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) return 0;
800*e5436536SAndroid Build Coastguard Worker 
801*e5436536SAndroid Build Coastguard Worker     if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) return 0;
802*e5436536SAndroid Build Coastguard Worker 
803*e5436536SAndroid Build Coastguard Worker     sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
804*e5436536SAndroid Build Coastguard Worker 
805*e5436536SAndroid Build Coastguard Worker     sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs);
806*e5436536SAndroid Build Coastguard Worker   }
807*e5436536SAndroid Build Coastguard Worker 
808*e5436536SAndroid Build Coastguard Worker   sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs, flags);
809*e5436536SAndroid Build Coastguard Worker   if (nCh == 2) {
810*e5436536SAndroid Build Coastguard Worker     sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs, flags);
811*e5436536SAndroid Build Coastguard Worker   }
812*e5436536SAndroid Build Coastguard Worker 
813*e5436536SAndroid Build Coastguard Worker   if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
814*e5436536SAndroid Build Coastguard Worker     if (!extractExtendedData(hHeaderData, hBs, hParametricStereoDec)) {
815*e5436536SAndroid Build Coastguard Worker       return 0;
816*e5436536SAndroid Build Coastguard Worker     }
817*e5436536SAndroid Build Coastguard Worker   }
818*e5436536SAndroid Build Coastguard Worker 
819*e5436536SAndroid Build Coastguard Worker   return 1;
820*e5436536SAndroid Build Coastguard Worker }
821*e5436536SAndroid Build Coastguard Worker 
822*e5436536SAndroid Build Coastguard Worker /*!
823*e5436536SAndroid Build Coastguard Worker   \brief   Read direction control data from bitstream
824*e5436536SAndroid Build Coastguard Worker */
sbrGetDirectionControlData(HANDLE_SBR_FRAME_DATA h_frame_data,HANDLE_FDK_BITSTREAM hBs,const UINT flags,const int bs_pvc_mode)825*e5436536SAndroid Build Coastguard Worker void sbrGetDirectionControlData(
826*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
827*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< handle to struct BIT_BUF */
828*e5436536SAndroid Build Coastguard Worker     const UINT flags, const int bs_pvc_mode)
829*e5436536SAndroid Build Coastguard Worker 
830*e5436536SAndroid Build Coastguard Worker {
831*e5436536SAndroid Build Coastguard Worker   int i;
832*e5436536SAndroid Build Coastguard Worker   int indepFlag = 0;
833*e5436536SAndroid Build Coastguard Worker 
834*e5436536SAndroid Build Coastguard Worker   if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
835*e5436536SAndroid Build Coastguard Worker     indepFlag = flags & SBRDEC_USAC_INDEP;
836*e5436536SAndroid Build Coastguard Worker   }
837*e5436536SAndroid Build Coastguard Worker 
838*e5436536SAndroid Build Coastguard Worker   if (bs_pvc_mode == 0) {
839*e5436536SAndroid Build Coastguard Worker     i = 0;
840*e5436536SAndroid Build Coastguard Worker     if (indepFlag) {
841*e5436536SAndroid Build Coastguard Worker       h_frame_data->domain_vec[i++] = 0;
842*e5436536SAndroid Build Coastguard Worker     }
843*e5436536SAndroid Build Coastguard Worker     for (; i < h_frame_data->frameInfo.nEnvelopes; i++) {
844*e5436536SAndroid Build Coastguard Worker       h_frame_data->domain_vec[i] = FDKreadBits(hBs, 1);
845*e5436536SAndroid Build Coastguard Worker     }
846*e5436536SAndroid Build Coastguard Worker   }
847*e5436536SAndroid Build Coastguard Worker 
848*e5436536SAndroid Build Coastguard Worker   i = 0;
849*e5436536SAndroid Build Coastguard Worker   if (indepFlag) {
850*e5436536SAndroid Build Coastguard Worker     h_frame_data->domain_vec_noise[i++] = 0;
851*e5436536SAndroid Build Coastguard Worker   }
852*e5436536SAndroid Build Coastguard Worker   for (; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) {
853*e5436536SAndroid Build Coastguard Worker     h_frame_data->domain_vec_noise[i] = FDKreadBits(hBs, 1);
854*e5436536SAndroid Build Coastguard Worker   }
855*e5436536SAndroid Build Coastguard Worker }
856*e5436536SAndroid Build Coastguard Worker 
857*e5436536SAndroid Build Coastguard Worker /*!
858*e5436536SAndroid Build Coastguard Worker   \brief   Read noise-floor-level data from bitstream
859*e5436536SAndroid Build Coastguard Worker */
sbrGetNoiseFloorData(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,HANDLE_FDK_BITSTREAM hBs)860*e5436536SAndroid Build Coastguard Worker void sbrGetNoiseFloorData(
861*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
862*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
863*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs)           /*!< handle to struct BIT_BUF */
864*e5436536SAndroid Build Coastguard Worker {
865*e5436536SAndroid Build Coastguard Worker   int i, j;
866*e5436536SAndroid Build Coastguard Worker   int delta;
867*e5436536SAndroid Build Coastguard Worker   COUPLING_MODE coupling;
868*e5436536SAndroid Build Coastguard Worker   int noNoiseBands = hHeaderData->freqBandData.nNfb;
869*e5436536SAndroid Build Coastguard Worker 
870*e5436536SAndroid Build Coastguard Worker   Huffman hcb_noiseF;
871*e5436536SAndroid Build Coastguard Worker   Huffman hcb_noise;
872*e5436536SAndroid Build Coastguard Worker   int envDataTableCompFactor;
873*e5436536SAndroid Build Coastguard Worker 
874*e5436536SAndroid Build Coastguard Worker   coupling = h_frame_data->coupling;
875*e5436536SAndroid Build Coastguard Worker 
876*e5436536SAndroid Build Coastguard Worker   /*
877*e5436536SAndroid Build Coastguard Worker     Select huffman codebook depending on coupling mode
878*e5436536SAndroid Build Coastguard Worker   */
879*e5436536SAndroid Build Coastguard Worker   if (coupling == COUPLING_BAL) {
880*e5436536SAndroid Build Coastguard Worker     hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T;
881*e5436536SAndroid Build Coastguard Worker     hcb_noiseF =
882*e5436536SAndroid Build Coastguard Worker         (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F"
883*e5436536SAndroid Build Coastguard Worker                                                               */
884*e5436536SAndroid Build Coastguard Worker     envDataTableCompFactor = 1;
885*e5436536SAndroid Build Coastguard Worker   } else {
886*e5436536SAndroid Build Coastguard Worker     hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T;
887*e5436536SAndroid Build Coastguard Worker     hcb_noiseF =
888*e5436536SAndroid Build Coastguard Worker         (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F"
889*e5436536SAndroid Build Coastguard Worker                                                             */
890*e5436536SAndroid Build Coastguard Worker     envDataTableCompFactor = 0;
891*e5436536SAndroid Build Coastguard Worker   }
892*e5436536SAndroid Build Coastguard Worker 
893*e5436536SAndroid Build Coastguard Worker   /*
894*e5436536SAndroid Build Coastguard Worker     Read raw noise-envelope data
895*e5436536SAndroid Build Coastguard Worker   */
896*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) {
897*e5436536SAndroid Build Coastguard Worker     if (h_frame_data->domain_vec_noise[i] == 0) {
898*e5436536SAndroid Build Coastguard Worker       if (coupling == COUPLING_BAL) {
899*e5436536SAndroid Build Coastguard Worker         h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] =
900*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(((int)FDKreadBits(hBs, 5)) << envDataTableCompFactor);
901*e5436536SAndroid Build Coastguard Worker       } else {
902*e5436536SAndroid Build Coastguard Worker         h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] =
903*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(int)FDKreadBits(hBs, 5);
904*e5436536SAndroid Build Coastguard Worker       }
905*e5436536SAndroid Build Coastguard Worker 
906*e5436536SAndroid Build Coastguard Worker       for (j = 1; j < noNoiseBands; j++) {
907*e5436536SAndroid Build Coastguard Worker         delta = DecodeHuffmanCW(hcb_noiseF, hBs);
908*e5436536SAndroid Build Coastguard Worker         h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] =
909*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(delta << envDataTableCompFactor);
910*e5436536SAndroid Build Coastguard Worker       }
911*e5436536SAndroid Build Coastguard Worker     } else {
912*e5436536SAndroid Build Coastguard Worker       for (j = 0; j < noNoiseBands; j++) {
913*e5436536SAndroid Build Coastguard Worker         delta = DecodeHuffmanCW(hcb_noise, hBs);
914*e5436536SAndroid Build Coastguard Worker         h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] =
915*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(delta << envDataTableCompFactor);
916*e5436536SAndroid Build Coastguard Worker       }
917*e5436536SAndroid Build Coastguard Worker     }
918*e5436536SAndroid Build Coastguard Worker   }
919*e5436536SAndroid Build Coastguard Worker }
920*e5436536SAndroid Build Coastguard Worker 
921*e5436536SAndroid Build Coastguard Worker /* ns = mapNsMode2ns[pvcMode-1][nsMode] */
922*e5436536SAndroid Build Coastguard Worker static const UCHAR mapNsMode2ns[2][2] = {
923*e5436536SAndroid Build Coastguard Worker     {16, 4}, /* pvcMode = 1 */
924*e5436536SAndroid Build Coastguard Worker     {12, 3}  /* pvcMode = 2 */
925*e5436536SAndroid Build Coastguard Worker };
926*e5436536SAndroid Build Coastguard Worker 
sbrGetPvcEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,HANDLE_FDK_BITSTREAM hBs,const UINT flags,const UINT pvcMode)927*e5436536SAndroid Build Coastguard Worker static int sbrGetPvcEnvelope(
928*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
929*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
930*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< handle to struct BIT_BUF */
931*e5436536SAndroid Build Coastguard Worker     const UINT flags, const UINT pvcMode) {
932*e5436536SAndroid Build Coastguard Worker   int divMode, nsMode;
933*e5436536SAndroid Build Coastguard Worker   int indepFlag = flags & SBRDEC_USAC_INDEP;
934*e5436536SAndroid Build Coastguard Worker   UCHAR *pvcID = h_frame_data->pvcID;
935*e5436536SAndroid Build Coastguard Worker 
936*e5436536SAndroid Build Coastguard Worker   divMode = FDKreadBits(hBs, PVC_DIVMODE_BITS);
937*e5436536SAndroid Build Coastguard Worker   nsMode = FDKreadBit(hBs);
938*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((pvcMode == 1) || (pvcMode == 2));
939*e5436536SAndroid Build Coastguard Worker   h_frame_data->ns = mapNsMode2ns[pvcMode - 1][nsMode];
940*e5436536SAndroid Build Coastguard Worker 
941*e5436536SAndroid Build Coastguard Worker   if (divMode <= 3) {
942*e5436536SAndroid Build Coastguard Worker     int i, k = 1, sum_length = 0, reuse_pcvID;
943*e5436536SAndroid Build Coastguard Worker 
944*e5436536SAndroid Build Coastguard Worker     /* special treatment for first time slot k=0 */
945*e5436536SAndroid Build Coastguard Worker     indepFlag ? (reuse_pcvID = 0) : (reuse_pcvID = FDKreadBit(hBs));
946*e5436536SAndroid Build Coastguard Worker     if (reuse_pcvID) {
947*e5436536SAndroid Build Coastguard Worker       pvcID[0] = hHeaderData->pvcIDprev;
948*e5436536SAndroid Build Coastguard Worker     } else {
949*e5436536SAndroid Build Coastguard Worker       pvcID[0] = FDKreadBits(hBs, PVC_PVCID_BITS);
950*e5436536SAndroid Build Coastguard Worker     }
951*e5436536SAndroid Build Coastguard Worker 
952*e5436536SAndroid Build Coastguard Worker     /* other time slots k>0 */
953*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < divMode; i++) {
954*e5436536SAndroid Build Coastguard Worker       int length, numBits = 4;
955*e5436536SAndroid Build Coastguard Worker 
956*e5436536SAndroid Build Coastguard Worker       if (sum_length >= 13) {
957*e5436536SAndroid Build Coastguard Worker         numBits = 1;
958*e5436536SAndroid Build Coastguard Worker       } else if (sum_length >= 11) {
959*e5436536SAndroid Build Coastguard Worker         numBits = 2;
960*e5436536SAndroid Build Coastguard Worker       } else if (sum_length >= 7) {
961*e5436536SAndroid Build Coastguard Worker         numBits = 3;
962*e5436536SAndroid Build Coastguard Worker       }
963*e5436536SAndroid Build Coastguard Worker 
964*e5436536SAndroid Build Coastguard Worker       length = FDKreadBits(hBs, numBits);
965*e5436536SAndroid Build Coastguard Worker       sum_length += length + 1;
966*e5436536SAndroid Build Coastguard Worker       if (sum_length >= PVC_NTIMESLOT) {
967*e5436536SAndroid Build Coastguard Worker         return 0; /* parse error */
968*e5436536SAndroid Build Coastguard Worker       }
969*e5436536SAndroid Build Coastguard Worker       for (; length--; k++) {
970*e5436536SAndroid Build Coastguard Worker         pvcID[k] = pvcID[k - 1];
971*e5436536SAndroid Build Coastguard Worker       }
972*e5436536SAndroid Build Coastguard Worker       pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
973*e5436536SAndroid Build Coastguard Worker     }
974*e5436536SAndroid Build Coastguard Worker     for (; k < 16; k++) {
975*e5436536SAndroid Build Coastguard Worker       pvcID[k] = pvcID[k - 1];
976*e5436536SAndroid Build Coastguard Worker     }
977*e5436536SAndroid Build Coastguard Worker   } else { /* divMode >= 4 */
978*e5436536SAndroid Build Coastguard Worker     int num_grid_info, fixed_length, grid_info, j, k = 0;
979*e5436536SAndroid Build Coastguard Worker 
980*e5436536SAndroid Build Coastguard Worker     divMode -= 4;
981*e5436536SAndroid Build Coastguard Worker     num_grid_info = 2 << divMode;
982*e5436536SAndroid Build Coastguard Worker     fixed_length = 8 >> divMode;
983*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(num_grid_info * fixed_length == PVC_NTIMESLOT);
984*e5436536SAndroid Build Coastguard Worker 
985*e5436536SAndroid Build Coastguard Worker     /* special treatment for first time slot k=0 */
986*e5436536SAndroid Build Coastguard Worker     indepFlag ? (grid_info = 1) : (grid_info = FDKreadBit(hBs));
987*e5436536SAndroid Build Coastguard Worker     if (grid_info) {
988*e5436536SAndroid Build Coastguard Worker       pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
989*e5436536SAndroid Build Coastguard Worker     } else {
990*e5436536SAndroid Build Coastguard Worker       pvcID[k++] = hHeaderData->pvcIDprev;
991*e5436536SAndroid Build Coastguard Worker     }
992*e5436536SAndroid Build Coastguard Worker     j = fixed_length - 1;
993*e5436536SAndroid Build Coastguard Worker     for (; j--; k++) {
994*e5436536SAndroid Build Coastguard Worker       pvcID[k] = pvcID[k - 1];
995*e5436536SAndroid Build Coastguard Worker     }
996*e5436536SAndroid Build Coastguard Worker     num_grid_info--;
997*e5436536SAndroid Build Coastguard Worker 
998*e5436536SAndroid Build Coastguard Worker     /* other time slots k>0 */
999*e5436536SAndroid Build Coastguard Worker     for (; num_grid_info--;) {
1000*e5436536SAndroid Build Coastguard Worker       j = fixed_length;
1001*e5436536SAndroid Build Coastguard Worker       grid_info = FDKreadBit(hBs);
1002*e5436536SAndroid Build Coastguard Worker       if (grid_info) {
1003*e5436536SAndroid Build Coastguard Worker         pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
1004*e5436536SAndroid Build Coastguard Worker         j--;
1005*e5436536SAndroid Build Coastguard Worker       }
1006*e5436536SAndroid Build Coastguard Worker       for (; j--; k++) {
1007*e5436536SAndroid Build Coastguard Worker         pvcID[k] = pvcID[k - 1];
1008*e5436536SAndroid Build Coastguard Worker       }
1009*e5436536SAndroid Build Coastguard Worker     }
1010*e5436536SAndroid Build Coastguard Worker   }
1011*e5436536SAndroid Build Coastguard Worker 
1012*e5436536SAndroid Build Coastguard Worker   hHeaderData->pvcIDprev = pvcID[PVC_NTIMESLOT - 1];
1013*e5436536SAndroid Build Coastguard Worker 
1014*e5436536SAndroid Build Coastguard Worker   /* usage of PVC excludes inter-TES tool */
1015*e5436536SAndroid Build Coastguard Worker   h_frame_data->iTESactive = (UCHAR)0;
1016*e5436536SAndroid Build Coastguard Worker 
1017*e5436536SAndroid Build Coastguard Worker   return 1;
1018*e5436536SAndroid Build Coastguard Worker }
1019*e5436536SAndroid Build Coastguard Worker /*!
1020*e5436536SAndroid Build Coastguard Worker   \brief   Read envelope data from bitstream
1021*e5436536SAndroid Build Coastguard Worker */
sbrGetEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,HANDLE_FDK_BITSTREAM hBs,const UINT flags)1022*e5436536SAndroid Build Coastguard Worker static int sbrGetEnvelope(
1023*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
1024*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
1025*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< handle to struct BIT_BUF */
1026*e5436536SAndroid Build Coastguard Worker     const UINT flags) {
1027*e5436536SAndroid Build Coastguard Worker   int i, j;
1028*e5436536SAndroid Build Coastguard Worker   UCHAR no_band[MAX_ENVELOPES];
1029*e5436536SAndroid Build Coastguard Worker   int delta = 0;
1030*e5436536SAndroid Build Coastguard Worker   int offset = 0;
1031*e5436536SAndroid Build Coastguard Worker   COUPLING_MODE coupling = h_frame_data->coupling;
1032*e5436536SAndroid Build Coastguard Worker   int ampRes = hHeaderData->bs_info.ampResolution;
1033*e5436536SAndroid Build Coastguard Worker   int nEnvelopes = h_frame_data->frameInfo.nEnvelopes;
1034*e5436536SAndroid Build Coastguard Worker   int envDataTableCompFactor;
1035*e5436536SAndroid Build Coastguard Worker   int start_bits, start_bits_balance;
1036*e5436536SAndroid Build Coastguard Worker   Huffman hcb_t, hcb_f;
1037*e5436536SAndroid Build Coastguard Worker 
1038*e5436536SAndroid Build Coastguard Worker   h_frame_data->nScaleFactors = 0;
1039*e5436536SAndroid Build Coastguard Worker 
1040*e5436536SAndroid Build Coastguard Worker   if ((h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1)) {
1041*e5436536SAndroid Build Coastguard Worker     if (flags & SBRDEC_ELD_GRID)
1042*e5436536SAndroid Build Coastguard Worker       ampRes = h_frame_data->ampResolutionCurrentFrame;
1043*e5436536SAndroid Build Coastguard Worker     else
1044*e5436536SAndroid Build Coastguard Worker       ampRes = 0;
1045*e5436536SAndroid Build Coastguard Worker   }
1046*e5436536SAndroid Build Coastguard Worker   h_frame_data->ampResolutionCurrentFrame = ampRes;
1047*e5436536SAndroid Build Coastguard Worker 
1048*e5436536SAndroid Build Coastguard Worker   /*
1049*e5436536SAndroid Build Coastguard Worker     Set number of bits for first value depending on amplitude resolution
1050*e5436536SAndroid Build Coastguard Worker   */
1051*e5436536SAndroid Build Coastguard Worker   if (ampRes == 1) {
1052*e5436536SAndroid Build Coastguard Worker     start_bits = 6;
1053*e5436536SAndroid Build Coastguard Worker     start_bits_balance = 5;
1054*e5436536SAndroid Build Coastguard Worker   } else {
1055*e5436536SAndroid Build Coastguard Worker     start_bits = 7;
1056*e5436536SAndroid Build Coastguard Worker     start_bits_balance = 6;
1057*e5436536SAndroid Build Coastguard Worker   }
1058*e5436536SAndroid Build Coastguard Worker 
1059*e5436536SAndroid Build Coastguard Worker   /*
1060*e5436536SAndroid Build Coastguard Worker     Calculate number of values for each envelope and alltogether
1061*e5436536SAndroid Build Coastguard Worker   */
1062*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nEnvelopes; i++) {
1063*e5436536SAndroid Build Coastguard Worker     no_band[i] =
1064*e5436536SAndroid Build Coastguard Worker         hHeaderData->freqBandData.nSfb[h_frame_data->frameInfo.freqRes[i]];
1065*e5436536SAndroid Build Coastguard Worker     h_frame_data->nScaleFactors += no_band[i];
1066*e5436536SAndroid Build Coastguard Worker   }
1067*e5436536SAndroid Build Coastguard Worker   if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) return 0;
1068*e5436536SAndroid Build Coastguard Worker 
1069*e5436536SAndroid Build Coastguard Worker   /*
1070*e5436536SAndroid Build Coastguard Worker     Select Huffman codebook depending on coupling mode and amplitude resolution
1071*e5436536SAndroid Build Coastguard Worker   */
1072*e5436536SAndroid Build Coastguard Worker   if (coupling == COUPLING_BAL) {
1073*e5436536SAndroid Build Coastguard Worker     envDataTableCompFactor = 1;
1074*e5436536SAndroid Build Coastguard Worker     if (ampRes == 0) {
1075*e5436536SAndroid Build Coastguard Worker       hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T;
1076*e5436536SAndroid Build Coastguard Worker       hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F;
1077*e5436536SAndroid Build Coastguard Worker     } else {
1078*e5436536SAndroid Build Coastguard Worker       hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T;
1079*e5436536SAndroid Build Coastguard Worker       hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F;
1080*e5436536SAndroid Build Coastguard Worker     }
1081*e5436536SAndroid Build Coastguard Worker   } else {
1082*e5436536SAndroid Build Coastguard Worker     envDataTableCompFactor = 0;
1083*e5436536SAndroid Build Coastguard Worker     if (ampRes == 0) {
1084*e5436536SAndroid Build Coastguard Worker       hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T;
1085*e5436536SAndroid Build Coastguard Worker       hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F;
1086*e5436536SAndroid Build Coastguard Worker     } else {
1087*e5436536SAndroid Build Coastguard Worker       hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11T;
1088*e5436536SAndroid Build Coastguard Worker       hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F;
1089*e5436536SAndroid Build Coastguard Worker     }
1090*e5436536SAndroid Build Coastguard Worker   }
1091*e5436536SAndroid Build Coastguard Worker 
1092*e5436536SAndroid Build Coastguard Worker   h_frame_data->iTESactive = (UCHAR)0; /* disable inter-TES by default */
1093*e5436536SAndroid Build Coastguard Worker   /*
1094*e5436536SAndroid Build Coastguard Worker     Now read raw envelope data
1095*e5436536SAndroid Build Coastguard Worker   */
1096*e5436536SAndroid Build Coastguard Worker   for (j = 0, offset = 0; j < nEnvelopes; j++) {
1097*e5436536SAndroid Build Coastguard Worker     if (h_frame_data->domain_vec[j] == 0) {
1098*e5436536SAndroid Build Coastguard Worker       if (coupling == COUPLING_BAL) {
1099*e5436536SAndroid Build Coastguard Worker         h_frame_data->iEnvelope[offset] =
1100*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(((int)FDKreadBits(hBs, start_bits_balance))
1101*e5436536SAndroid Build Coastguard Worker                        << envDataTableCompFactor);
1102*e5436536SAndroid Build Coastguard Worker       } else {
1103*e5436536SAndroid Build Coastguard Worker         h_frame_data->iEnvelope[offset] =
1104*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)(int)FDKreadBits(hBs, start_bits);
1105*e5436536SAndroid Build Coastguard Worker       }
1106*e5436536SAndroid Build Coastguard Worker     }
1107*e5436536SAndroid Build Coastguard Worker 
1108*e5436536SAndroid Build Coastguard Worker     for (i = (1 - h_frame_data->domain_vec[j]); i < no_band[j]; i++) {
1109*e5436536SAndroid Build Coastguard Worker       if (h_frame_data->domain_vec[j] == 0) {
1110*e5436536SAndroid Build Coastguard Worker         delta = DecodeHuffmanCW(hcb_f, hBs);
1111*e5436536SAndroid Build Coastguard Worker       } else {
1112*e5436536SAndroid Build Coastguard Worker         delta = DecodeHuffmanCW(hcb_t, hBs);
1113*e5436536SAndroid Build Coastguard Worker       }
1114*e5436536SAndroid Build Coastguard Worker 
1115*e5436536SAndroid Build Coastguard Worker       h_frame_data->iEnvelope[offset + i] =
1116*e5436536SAndroid Build Coastguard Worker           (FIXP_SGL)(delta << envDataTableCompFactor);
1117*e5436536SAndroid Build Coastguard Worker     }
1118*e5436536SAndroid Build Coastguard Worker     if ((flags & SBRDEC_SYNTAX_USAC) && (flags & SBRDEC_USAC_ITES)) {
1119*e5436536SAndroid Build Coastguard Worker       int bs_temp_shape = FDKreadBit(hBs);
1120*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(j < 8);
1121*e5436536SAndroid Build Coastguard Worker       h_frame_data->iTESactive |= (UCHAR)(bs_temp_shape << j);
1122*e5436536SAndroid Build Coastguard Worker       if (bs_temp_shape) {
1123*e5436536SAndroid Build Coastguard Worker         h_frame_data->interTempShapeMode[j] =
1124*e5436536SAndroid Build Coastguard Worker             FDKread2Bits(hBs); /* bs_inter_temp_shape_mode */
1125*e5436536SAndroid Build Coastguard Worker       } else {
1126*e5436536SAndroid Build Coastguard Worker         h_frame_data->interTempShapeMode[j] = 0;
1127*e5436536SAndroid Build Coastguard Worker       }
1128*e5436536SAndroid Build Coastguard Worker     }
1129*e5436536SAndroid Build Coastguard Worker     offset += no_band[j];
1130*e5436536SAndroid Build Coastguard Worker   }
1131*e5436536SAndroid Build Coastguard Worker 
1132*e5436536SAndroid Build Coastguard Worker #if ENV_EXP_FRACT
1133*e5436536SAndroid Build Coastguard Worker   /* Convert from int to scaled fract (ENV_EXP_FRACT bits for the fractional
1134*e5436536SAndroid Build Coastguard Worker    * part) */
1135*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < h_frame_data->nScaleFactors; i++) {
1136*e5436536SAndroid Build Coastguard Worker     h_frame_data->iEnvelope[i] <<= ENV_EXP_FRACT;
1137*e5436536SAndroid Build Coastguard Worker   }
1138*e5436536SAndroid Build Coastguard Worker #endif
1139*e5436536SAndroid Build Coastguard Worker 
1140*e5436536SAndroid Build Coastguard Worker   return 1;
1141*e5436536SAndroid Build Coastguard Worker }
1142*e5436536SAndroid Build Coastguard Worker 
1143*e5436536SAndroid Build Coastguard Worker /***************************************************************************/
1144*e5436536SAndroid Build Coastguard Worker /*!
1145*e5436536SAndroid Build Coastguard Worker   \brief    Generates frame info for FIXFIXonly frame class used for low delay
1146*e5436536SAndroid Build Coastguard Worker  version
1147*e5436536SAndroid Build Coastguard Worker 
1148*e5436536SAndroid Build Coastguard Worker   \return   zero for error, one for correct.
1149*e5436536SAndroid Build Coastguard Worker  ****************************************************************************/
generateFixFixOnly(FRAME_INFO * hSbrFrameInfo,int tranPosInternal,int numberTimeSlots,const UINT flags)1150*e5436536SAndroid Build Coastguard Worker static int generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal,
1151*e5436536SAndroid Build Coastguard Worker                               int numberTimeSlots, const UINT flags) {
1152*e5436536SAndroid Build Coastguard Worker   int nEnv, i, tranIdx;
1153*e5436536SAndroid Build Coastguard Worker   const int *pTable;
1154*e5436536SAndroid Build Coastguard Worker 
1155*e5436536SAndroid Build Coastguard Worker   if (tranPosInternal >= numberTimeSlots) {
1156*e5436536SAndroid Build Coastguard Worker     return 0;
1157*e5436536SAndroid Build Coastguard Worker   }
1158*e5436536SAndroid Build Coastguard Worker 
1159*e5436536SAndroid Build Coastguard Worker   switch (numberTimeSlots) {
1160*e5436536SAndroid Build Coastguard Worker     case 8:
1161*e5436536SAndroid Build Coastguard Worker       pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal];
1162*e5436536SAndroid Build Coastguard Worker       break;
1163*e5436536SAndroid Build Coastguard Worker     case 15:
1164*e5436536SAndroid Build Coastguard Worker       pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal];
1165*e5436536SAndroid Build Coastguard Worker       break;
1166*e5436536SAndroid Build Coastguard Worker     case 16:
1167*e5436536SAndroid Build Coastguard Worker       pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal];
1168*e5436536SAndroid Build Coastguard Worker       break;
1169*e5436536SAndroid Build Coastguard Worker     default:
1170*e5436536SAndroid Build Coastguard Worker       return 0;
1171*e5436536SAndroid Build Coastguard Worker   }
1172*e5436536SAndroid Build Coastguard Worker 
1173*e5436536SAndroid Build Coastguard Worker   /* look number of envelopes in table */
1174*e5436536SAndroid Build Coastguard Worker   nEnv = pTable[0];
1175*e5436536SAndroid Build Coastguard Worker   /* look up envelope distribution in table */
1176*e5436536SAndroid Build Coastguard Worker   for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2];
1177*e5436536SAndroid Build Coastguard Worker   /* open and close frame border */
1178*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->borders[0] = 0;
1179*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->borders[nEnv] = numberTimeSlots;
1180*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->nEnvelopes = nEnv;
1181*e5436536SAndroid Build Coastguard Worker 
1182*e5436536SAndroid Build Coastguard Worker   /* transient idx */
1183*e5436536SAndroid Build Coastguard Worker   tranIdx = hSbrFrameInfo->tranEnv = pTable[1];
1184*e5436536SAndroid Build Coastguard Worker 
1185*e5436536SAndroid Build Coastguard Worker   /* add noise floors */
1186*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->bordersNoise[0] = 0;
1187*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->bordersNoise[1] =
1188*e5436536SAndroid Build Coastguard Worker       hSbrFrameInfo->borders[tranIdx ? tranIdx : 1];
1189*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->bordersNoise[2] = numberTimeSlots;
1190*e5436536SAndroid Build Coastguard Worker   /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2)
1191*e5436536SAndroid Build Coastguard Worker    */
1192*e5436536SAndroid Build Coastguard Worker   hSbrFrameInfo->nNoiseEnvelopes = 2;
1193*e5436536SAndroid Build Coastguard Worker 
1194*e5436536SAndroid Build Coastguard Worker   return 1;
1195*e5436536SAndroid Build Coastguard Worker }
1196*e5436536SAndroid Build Coastguard Worker 
1197*e5436536SAndroid Build Coastguard Worker /*!
1198*e5436536SAndroid Build Coastguard Worker   \brief  Extracts LowDelaySBR control data from the bitstream.
1199*e5436536SAndroid Build Coastguard Worker 
1200*e5436536SAndroid Build Coastguard Worker   \return zero for bitstream error, one for correct.
1201*e5436536SAndroid Build Coastguard Worker */
extractLowDelayGrid(HANDLE_FDK_BITSTREAM hBitBuf,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,int timeSlots,const UINT flags)1202*e5436536SAndroid Build Coastguard Worker static int extractLowDelayGrid(
1203*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */
1204*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData,
1205*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA
1206*e5436536SAndroid Build Coastguard Worker         h_frame_data, /*!< contains the FRAME_INFO struct to be filled */
1207*e5436536SAndroid Build Coastguard Worker     int timeSlots, const UINT flags) {
1208*e5436536SAndroid Build Coastguard Worker   FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
1209*e5436536SAndroid Build Coastguard Worker   INT numberTimeSlots = hHeaderData->numberTimeSlots;
1210*e5436536SAndroid Build Coastguard Worker   INT temp = 0, k;
1211*e5436536SAndroid Build Coastguard Worker 
1212*e5436536SAndroid Build Coastguard Worker   /* FIXFIXonly framing case */
1213*e5436536SAndroid Build Coastguard Worker   h_frame_data->frameInfo.frameClass = 0;
1214*e5436536SAndroid Build Coastguard Worker 
1215*e5436536SAndroid Build Coastguard Worker   /* get the transient position from the bitstream */
1216*e5436536SAndroid Build Coastguard Worker   switch (timeSlots) {
1217*e5436536SAndroid Build Coastguard Worker     case 8:
1218*e5436536SAndroid Build Coastguard Worker       /* 3bit transient position (temp={0;..;7}) */
1219*e5436536SAndroid Build Coastguard Worker       temp = FDKreadBits(hBitBuf, 3);
1220*e5436536SAndroid Build Coastguard Worker       break;
1221*e5436536SAndroid Build Coastguard Worker 
1222*e5436536SAndroid Build Coastguard Worker     case 16:
1223*e5436536SAndroid Build Coastguard Worker     case 15:
1224*e5436536SAndroid Build Coastguard Worker       /* 4bit transient position (temp={0;..;15}) */
1225*e5436536SAndroid Build Coastguard Worker       temp = FDKreadBits(hBitBuf, 4);
1226*e5436536SAndroid Build Coastguard Worker       break;
1227*e5436536SAndroid Build Coastguard Worker 
1228*e5436536SAndroid Build Coastguard Worker     default:
1229*e5436536SAndroid Build Coastguard Worker       return 0;
1230*e5436536SAndroid Build Coastguard Worker   }
1231*e5436536SAndroid Build Coastguard Worker 
1232*e5436536SAndroid Build Coastguard Worker   /* For "case 15" only*/
1233*e5436536SAndroid Build Coastguard Worker   if (temp >= timeSlots) {
1234*e5436536SAndroid Build Coastguard Worker     return 0;
1235*e5436536SAndroid Build Coastguard Worker   }
1236*e5436536SAndroid Build Coastguard Worker 
1237*e5436536SAndroid Build Coastguard Worker   /* calculate borders according to the transient position */
1238*e5436536SAndroid Build Coastguard Worker   if (!generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags)) {
1239*e5436536SAndroid Build Coastguard Worker     return 0;
1240*e5436536SAndroid Build Coastguard Worker   }
1241*e5436536SAndroid Build Coastguard Worker 
1242*e5436536SAndroid Build Coastguard Worker   /* decode freq res: */
1243*e5436536SAndroid Build Coastguard Worker   for (k = 0; k < pFrameInfo->nEnvelopes; k++) {
1244*e5436536SAndroid Build Coastguard Worker     pFrameInfo->freqRes[k] =
1245*e5436536SAndroid Build Coastguard Worker         (UCHAR)FDKreadBits(hBitBuf, 1); /* f = F [1 bits] */
1246*e5436536SAndroid Build Coastguard Worker   }
1247*e5436536SAndroid Build Coastguard Worker 
1248*e5436536SAndroid Build Coastguard Worker   return 1;
1249*e5436536SAndroid Build Coastguard Worker }
1250*e5436536SAndroid Build Coastguard Worker 
1251*e5436536SAndroid Build Coastguard Worker /*!
1252*e5436536SAndroid Build Coastguard Worker   \brief   Extract the PVC frame information (structure FRAME_INFO) from the
1253*e5436536SAndroid Build Coastguard Worker   bitstream \return  Zero for bitstream error, one for correct.
1254*e5436536SAndroid Build Coastguard Worker */
extractPvcFrameInfo(HANDLE_FDK_BITSTREAM hBs,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data,UCHAR pvc_mode_last,const UINT flags)1255*e5436536SAndroid Build Coastguard Worker int extractPvcFrameInfo(
1256*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< bitbuffer handle */
1257*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
1258*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
1259*e5436536SAndroid Build Coastguard Worker                                            frame-info will be stored */
1260*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where
1261*e5436536SAndroid Build Coastguard Worker                                                      the previous frame-info
1262*e5436536SAndroid Build Coastguard Worker                                                      will be stored */
1263*e5436536SAndroid Build Coastguard Worker     UCHAR pvc_mode_last,                          /**< PVC mode of last frame */
1264*e5436536SAndroid Build Coastguard Worker     const UINT flags) {
1265*e5436536SAndroid Build Coastguard Worker   FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
1266*e5436536SAndroid Build Coastguard Worker   FRAME_INFO *pPrevFrameInfo = &h_prev_frame_data->prevFrameInfo;
1267*e5436536SAndroid Build Coastguard Worker   int bs_var_len_hf, bs_noise_position;
1268*e5436536SAndroid Build Coastguard Worker   bs_noise_position = FDKreadBits(hBs, 4); /* SBR_PVC_NOISEPOSITION_BITS 4 */
1269*e5436536SAndroid Build Coastguard Worker   bs_var_len_hf = FDKreadBit(hBs);
1270*e5436536SAndroid Build Coastguard Worker   pFrameInfo->noisePosition = bs_noise_position;
1271*e5436536SAndroid Build Coastguard Worker   pFrameInfo->tranEnv = -1;
1272*e5436536SAndroid Build Coastguard Worker 
1273*e5436536SAndroid Build Coastguard Worker   /* Init for bs_noise_position == 0 in case a parse error is found below. */
1274*e5436536SAndroid Build Coastguard Worker   pFrameInfo->nEnvelopes = 1;
1275*e5436536SAndroid Build Coastguard Worker   pFrameInfo->nNoiseEnvelopes = 1;
1276*e5436536SAndroid Build Coastguard Worker   pFrameInfo->freqRes[0] = 0;
1277*e5436536SAndroid Build Coastguard Worker 
1278*e5436536SAndroid Build Coastguard Worker   if (bs_var_len_hf) { /* 1 or 3 Bits */
1279*e5436536SAndroid Build Coastguard Worker     pFrameInfo->varLength = FDKreadBits(hBs, 2) + 1;
1280*e5436536SAndroid Build Coastguard Worker     if (pFrameInfo->varLength > 3) {
1281*e5436536SAndroid Build Coastguard Worker       pFrameInfo->varLength =
1282*e5436536SAndroid Build Coastguard Worker           0;    /* assume bs_var_len_hf == 0 in case of error */
1283*e5436536SAndroid Build Coastguard Worker       return 0; /* reserved value -> parse error */
1284*e5436536SAndroid Build Coastguard Worker     }
1285*e5436536SAndroid Build Coastguard Worker   } else {
1286*e5436536SAndroid Build Coastguard Worker     pFrameInfo->varLength = 0;
1287*e5436536SAndroid Build Coastguard Worker   }
1288*e5436536SAndroid Build Coastguard Worker 
1289*e5436536SAndroid Build Coastguard Worker   if (bs_noise_position) {
1290*e5436536SAndroid Build Coastguard Worker     pFrameInfo->nEnvelopes = 2;
1291*e5436536SAndroid Build Coastguard Worker     pFrameInfo->nNoiseEnvelopes = 2;
1292*e5436536SAndroid Build Coastguard Worker     FDKmemclear(pFrameInfo->freqRes, sizeof(pFrameInfo->freqRes));
1293*e5436536SAndroid Build Coastguard Worker   }
1294*e5436536SAndroid Build Coastguard Worker 
1295*e5436536SAndroid Build Coastguard Worker   /* frame border calculation */
1296*e5436536SAndroid Build Coastguard Worker   if (hHeaderData->bs_info.pvc_mode > 0) {
1297*e5436536SAndroid Build Coastguard Worker     /* See "7.5.1.4 HF adjustment of SBR envelope scalefactors" for reference.
1298*e5436536SAndroid Build Coastguard Worker      */
1299*e5436536SAndroid Build Coastguard Worker 
1300*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT((pFrameInfo->nEnvelopes == 1) || (pFrameInfo->nEnvelopes == 2));
1301*e5436536SAndroid Build Coastguard Worker 
1302*e5436536SAndroid Build Coastguard Worker     /* left timeborder-offset: use the timeborder of prev SBR frame */
1303*e5436536SAndroid Build Coastguard Worker     if (pPrevFrameInfo->nEnvelopes > 0) {
1304*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[0] =
1305*e5436536SAndroid Build Coastguard Worker           pPrevFrameInfo->borders[pPrevFrameInfo->nEnvelopes] - PVC_NTIMESLOT;
1306*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(pFrameInfo->borders[0] <= 3);
1307*e5436536SAndroid Build Coastguard Worker     } else {
1308*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[0] = 0;
1309*e5436536SAndroid Build Coastguard Worker     }
1310*e5436536SAndroid Build Coastguard Worker 
1311*e5436536SAndroid Build Coastguard Worker     /* right timeborder-offset: */
1312*e5436536SAndroid Build Coastguard Worker     pFrameInfo->borders[pFrameInfo->nEnvelopes] = 16 + pFrameInfo->varLength;
1313*e5436536SAndroid Build Coastguard Worker 
1314*e5436536SAndroid Build Coastguard Worker     if (pFrameInfo->nEnvelopes == 2) {
1315*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[1] = pFrameInfo->noisePosition;
1316*e5436536SAndroid Build Coastguard Worker     }
1317*e5436536SAndroid Build Coastguard Worker 
1318*e5436536SAndroid Build Coastguard Worker     /* Calculation of PVC time borders t_EPVC */
1319*e5436536SAndroid Build Coastguard Worker     if (pvc_mode_last == 0) {
1320*e5436536SAndroid Build Coastguard Worker       /* there was a legacy SBR frame before this frame => use bs_var_len' for
1321*e5436536SAndroid Build Coastguard Worker        * first PVC timeslot */
1322*e5436536SAndroid Build Coastguard Worker       pFrameInfo->pvcBorders[0] = pFrameInfo->borders[0];
1323*e5436536SAndroid Build Coastguard Worker     } else {
1324*e5436536SAndroid Build Coastguard Worker       pFrameInfo->pvcBorders[0] = 0;
1325*e5436536SAndroid Build Coastguard Worker     }
1326*e5436536SAndroid Build Coastguard Worker     if (pFrameInfo->nEnvelopes == 2) {
1327*e5436536SAndroid Build Coastguard Worker       pFrameInfo->pvcBorders[1] = pFrameInfo->borders[1];
1328*e5436536SAndroid Build Coastguard Worker     }
1329*e5436536SAndroid Build Coastguard Worker     pFrameInfo->pvcBorders[pFrameInfo->nEnvelopes] = 16;
1330*e5436536SAndroid Build Coastguard Worker 
1331*e5436536SAndroid Build Coastguard Worker     /* calculation of SBR noise-floor time-border vector: */
1332*e5436536SAndroid Build Coastguard Worker     for (INT i = 0; i <= pFrameInfo->nNoiseEnvelopes; i++) {
1333*e5436536SAndroid Build Coastguard Worker       pFrameInfo->bordersNoise[i] = pFrameInfo->borders[i];
1334*e5436536SAndroid Build Coastguard Worker     }
1335*e5436536SAndroid Build Coastguard Worker 
1336*e5436536SAndroid Build Coastguard Worker     pFrameInfo->tranEnv = -1; /* tranEnv not used */
1337*e5436536SAndroid Build Coastguard Worker   }
1338*e5436536SAndroid Build Coastguard Worker   return 1;
1339*e5436536SAndroid Build Coastguard Worker }
1340*e5436536SAndroid Build Coastguard Worker 
1341*e5436536SAndroid Build Coastguard Worker /*!
1342*e5436536SAndroid Build Coastguard Worker   \brief   Extract the frame information (structure FRAME_INFO) from the
1343*e5436536SAndroid Build Coastguard Worker   bitstream \return  Zero for bitstream error, one for correct.
1344*e5436536SAndroid Build Coastguard Worker */
extractFrameInfo(HANDLE_FDK_BITSTREAM hBs,HANDLE_SBR_HEADER_DATA hHeaderData,HANDLE_SBR_FRAME_DATA h_frame_data,const UINT nrOfChannels,const UINT flags)1345*e5436536SAndroid Build Coastguard Worker int extractFrameInfo(
1346*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs,           /*!< bitbuffer handle */
1347*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
1348*e5436536SAndroid Build Coastguard Worker     HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
1349*e5436536SAndroid Build Coastguard Worker                                            frame-info will be stored */
1350*e5436536SAndroid Build Coastguard Worker     const UINT nrOfChannels, const UINT flags) {
1351*e5436536SAndroid Build Coastguard Worker   FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
1352*e5436536SAndroid Build Coastguard Worker   int numberTimeSlots = hHeaderData->numberTimeSlots;
1353*e5436536SAndroid Build Coastguard Worker   int pointer_bits = 0, nEnv = 0, b = 0, border, i, n = 0, k, p, aL, aR, nL, nR,
1354*e5436536SAndroid Build Coastguard Worker       temp = 0, staticFreqRes;
1355*e5436536SAndroid Build Coastguard Worker   UCHAR frameClass;
1356*e5436536SAndroid Build Coastguard Worker 
1357*e5436536SAndroid Build Coastguard Worker   if (flags & SBRDEC_ELD_GRID) {
1358*e5436536SAndroid Build Coastguard Worker     /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames
1359*e5436536SAndroid Build Coastguard Worker      * and the LowDelayGrid for transient Frames */
1360*e5436536SAndroid Build Coastguard Worker     frameClass = FDKreadBits(hBs, 1); /* frameClass = [1 bit] */
1361*e5436536SAndroid Build Coastguard Worker     if (frameClass == 1) {
1362*e5436536SAndroid Build Coastguard Worker       /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal
1363*e5436536SAndroid Build Coastguard Worker        * SBR-Grid for FIXIFX */
1364*e5436536SAndroid Build Coastguard Worker       /* extract the AACLD-Sbr-Grid */
1365*e5436536SAndroid Build Coastguard Worker       pFrameInfo->frameClass = frameClass;
1366*e5436536SAndroid Build Coastguard Worker       int err = 1;
1367*e5436536SAndroid Build Coastguard Worker       err = extractLowDelayGrid(hBs, hHeaderData, h_frame_data, numberTimeSlots,
1368*e5436536SAndroid Build Coastguard Worker                                 flags);
1369*e5436536SAndroid Build Coastguard Worker       return err;
1370*e5436536SAndroid Build Coastguard Worker     }
1371*e5436536SAndroid Build Coastguard Worker   } else {
1372*e5436536SAndroid Build Coastguard Worker     frameClass = FDKreadBits(hBs, 2); /* frameClass = C [2 bits] */
1373*e5436536SAndroid Build Coastguard Worker   }
1374*e5436536SAndroid Build Coastguard Worker 
1375*e5436536SAndroid Build Coastguard Worker   switch (frameClass) {
1376*e5436536SAndroid Build Coastguard Worker     case 0:
1377*e5436536SAndroid Build Coastguard Worker       temp = FDKreadBits(hBs, 2); /* E [2 bits ] */
1378*e5436536SAndroid Build Coastguard Worker       nEnv = (int)(1 << temp);    /* E -> e */
1379*e5436536SAndroid Build Coastguard Worker 
1380*e5436536SAndroid Build Coastguard Worker       if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1))
1381*e5436536SAndroid Build Coastguard Worker         h_frame_data->ampResolutionCurrentFrame =
1382*e5436536SAndroid Build Coastguard Worker             FDKreadBits(hBs, 1); /* new ELD Syntax 07-11-09 */
1383*e5436536SAndroid Build Coastguard Worker 
1384*e5436536SAndroid Build Coastguard Worker       staticFreqRes = FDKreadBits(hBs, 1);
1385*e5436536SAndroid Build Coastguard Worker 
1386*e5436536SAndroid Build Coastguard Worker       if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
1387*e5436536SAndroid Build Coastguard Worker         if (nEnv > MAX_ENVELOPES_USAC) return 0;
1388*e5436536SAndroid Build Coastguard Worker       } else
1389*e5436536SAndroid Build Coastguard Worker 
1390*e5436536SAndroid Build Coastguard Worker         b = nEnv + 1;
1391*e5436536SAndroid Build Coastguard Worker       switch (nEnv) {
1392*e5436536SAndroid Build Coastguard Worker         case 1:
1393*e5436536SAndroid Build Coastguard Worker           switch (numberTimeSlots) {
1394*e5436536SAndroid Build Coastguard Worker             case 15:
1395*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_15,
1396*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1397*e5436536SAndroid Build Coastguard Worker               break;
1398*e5436536SAndroid Build Coastguard Worker             case 16:
1399*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_16,
1400*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1401*e5436536SAndroid Build Coastguard Worker               break;
1402*e5436536SAndroid Build Coastguard Worker             default:
1403*e5436536SAndroid Build Coastguard Worker               FDK_ASSERT(0);
1404*e5436536SAndroid Build Coastguard Worker           }
1405*e5436536SAndroid Build Coastguard Worker           break;
1406*e5436536SAndroid Build Coastguard Worker         case 2:
1407*e5436536SAndroid Build Coastguard Worker           switch (numberTimeSlots) {
1408*e5436536SAndroid Build Coastguard Worker             case 15:
1409*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_15,
1410*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1411*e5436536SAndroid Build Coastguard Worker               break;
1412*e5436536SAndroid Build Coastguard Worker             case 16:
1413*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_16,
1414*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1415*e5436536SAndroid Build Coastguard Worker               break;
1416*e5436536SAndroid Build Coastguard Worker             default:
1417*e5436536SAndroid Build Coastguard Worker               FDK_ASSERT(0);
1418*e5436536SAndroid Build Coastguard Worker           }
1419*e5436536SAndroid Build Coastguard Worker           break;
1420*e5436536SAndroid Build Coastguard Worker         case 4:
1421*e5436536SAndroid Build Coastguard Worker           switch (numberTimeSlots) {
1422*e5436536SAndroid Build Coastguard Worker             case 15:
1423*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_15,
1424*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1425*e5436536SAndroid Build Coastguard Worker               break;
1426*e5436536SAndroid Build Coastguard Worker             case 16:
1427*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_16,
1428*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1429*e5436536SAndroid Build Coastguard Worker               break;
1430*e5436536SAndroid Build Coastguard Worker             default:
1431*e5436536SAndroid Build Coastguard Worker               FDK_ASSERT(0);
1432*e5436536SAndroid Build Coastguard Worker           }
1433*e5436536SAndroid Build Coastguard Worker           break;
1434*e5436536SAndroid Build Coastguard Worker         case 8:
1435*e5436536SAndroid Build Coastguard Worker #if (MAX_ENVELOPES >= 8)
1436*e5436536SAndroid Build Coastguard Worker           switch (numberTimeSlots) {
1437*e5436536SAndroid Build Coastguard Worker             case 15:
1438*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_15,
1439*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1440*e5436536SAndroid Build Coastguard Worker               break;
1441*e5436536SAndroid Build Coastguard Worker             case 16:
1442*e5436536SAndroid Build Coastguard Worker               FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_16,
1443*e5436536SAndroid Build Coastguard Worker                         sizeof(FRAME_INFO));
1444*e5436536SAndroid Build Coastguard Worker               break;
1445*e5436536SAndroid Build Coastguard Worker             default:
1446*e5436536SAndroid Build Coastguard Worker               FDK_ASSERT(0);
1447*e5436536SAndroid Build Coastguard Worker           }
1448*e5436536SAndroid Build Coastguard Worker           break;
1449*e5436536SAndroid Build Coastguard Worker #else
1450*e5436536SAndroid Build Coastguard Worker           return 0;
1451*e5436536SAndroid Build Coastguard Worker #endif
1452*e5436536SAndroid Build Coastguard Worker       }
1453*e5436536SAndroid Build Coastguard Worker       /* Apply correct freqRes (High is default) */
1454*e5436536SAndroid Build Coastguard Worker       if (!staticFreqRes) {
1455*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < nEnv; i++) pFrameInfo->freqRes[i] = 0;
1456*e5436536SAndroid Build Coastguard Worker       }
1457*e5436536SAndroid Build Coastguard Worker 
1458*e5436536SAndroid Build Coastguard Worker       break;
1459*e5436536SAndroid Build Coastguard Worker     case 1:
1460*e5436536SAndroid Build Coastguard Worker     case 2:
1461*e5436536SAndroid Build Coastguard Worker       temp = FDKreadBits(hBs, 2); /* A [2 bits] */
1462*e5436536SAndroid Build Coastguard Worker 
1463*e5436536SAndroid Build Coastguard Worker       n = FDKreadBits(hBs, 2); /* n = N [2 bits] */
1464*e5436536SAndroid Build Coastguard Worker 
1465*e5436536SAndroid Build Coastguard Worker       nEnv = n + 1; /* # envelopes */
1466*e5436536SAndroid Build Coastguard Worker       b = nEnv + 1; /* # borders   */
1467*e5436536SAndroid Build Coastguard Worker 
1468*e5436536SAndroid Build Coastguard Worker       break;
1469*e5436536SAndroid Build Coastguard Worker   }
1470*e5436536SAndroid Build Coastguard Worker 
1471*e5436536SAndroid Build Coastguard Worker   switch (frameClass) {
1472*e5436536SAndroid Build Coastguard Worker     case 1:
1473*e5436536SAndroid Build Coastguard Worker       /* Decode borders: */
1474*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[0] = 0;      /* first border          */
1475*e5436536SAndroid Build Coastguard Worker       border = temp + numberTimeSlots; /* A -> aR               */
1476*e5436536SAndroid Build Coastguard Worker       i = b - 1;                       /* frame info index for last border */
1477*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[i] = border; /* last border                      */
1478*e5436536SAndroid Build Coastguard Worker 
1479*e5436536SAndroid Build Coastguard Worker       for (k = 0; k < n; k++) {
1480*e5436536SAndroid Build Coastguard Worker         temp = FDKreadBits(hBs, 2); /* R [2 bits] */
1481*e5436536SAndroid Build Coastguard Worker         border -= (2 * temp + 2);   /* R -> r                */
1482*e5436536SAndroid Build Coastguard Worker         pFrameInfo->borders[--i] = border;
1483*e5436536SAndroid Build Coastguard Worker       }
1484*e5436536SAndroid Build Coastguard Worker 
1485*e5436536SAndroid Build Coastguard Worker       /* Decode pointer: */
1486*e5436536SAndroid Build Coastguard Worker       pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1));
1487*e5436536SAndroid Build Coastguard Worker       p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
1488*e5436536SAndroid Build Coastguard Worker 
1489*e5436536SAndroid Build Coastguard Worker       if (p > n + 1) return 0;
1490*e5436536SAndroid Build Coastguard Worker 
1491*e5436536SAndroid Build Coastguard Worker       pFrameInfo->tranEnv = p ? n + 2 - p : -1;
1492*e5436536SAndroid Build Coastguard Worker 
1493*e5436536SAndroid Build Coastguard Worker       /* Decode freq res: */
1494*e5436536SAndroid Build Coastguard Worker       for (k = n; k >= 0; k--) {
1495*e5436536SAndroid Build Coastguard Worker         pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
1496*e5436536SAndroid Build Coastguard Worker       }
1497*e5436536SAndroid Build Coastguard Worker 
1498*e5436536SAndroid Build Coastguard Worker       /* Calculate noise floor middle border: */
1499*e5436536SAndroid Build Coastguard Worker       if (p == 0 || p == 1)
1500*e5436536SAndroid Build Coastguard Worker         pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n];
1501*e5436536SAndroid Build Coastguard Worker       else
1502*e5436536SAndroid Build Coastguard Worker         pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv];
1503*e5436536SAndroid Build Coastguard Worker 
1504*e5436536SAndroid Build Coastguard Worker       break;
1505*e5436536SAndroid Build Coastguard Worker 
1506*e5436536SAndroid Build Coastguard Worker     case 2:
1507*e5436536SAndroid Build Coastguard Worker       /* Decode borders: */
1508*e5436536SAndroid Build Coastguard Worker       border = temp;                   /* A -> aL */
1509*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[0] = border; /* first border */
1510*e5436536SAndroid Build Coastguard Worker 
1511*e5436536SAndroid Build Coastguard Worker       for (k = 1; k <= n; k++) {
1512*e5436536SAndroid Build Coastguard Worker         temp = FDKreadBits(hBs, 2); /* R [2 bits] */
1513*e5436536SAndroid Build Coastguard Worker         border += (2 * temp + 2);   /* R -> r                */
1514*e5436536SAndroid Build Coastguard Worker         pFrameInfo->borders[k] = border;
1515*e5436536SAndroid Build Coastguard Worker       }
1516*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[k] = numberTimeSlots; /* last border */
1517*e5436536SAndroid Build Coastguard Worker 
1518*e5436536SAndroid Build Coastguard Worker       /* Decode pointer: */
1519*e5436536SAndroid Build Coastguard Worker       pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1));
1520*e5436536SAndroid Build Coastguard Worker       p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
1521*e5436536SAndroid Build Coastguard Worker       if (p > n + 1) return 0;
1522*e5436536SAndroid Build Coastguard Worker 
1523*e5436536SAndroid Build Coastguard Worker       if (p == 0 || p == 1)
1524*e5436536SAndroid Build Coastguard Worker         pFrameInfo->tranEnv = -1;
1525*e5436536SAndroid Build Coastguard Worker       else
1526*e5436536SAndroid Build Coastguard Worker         pFrameInfo->tranEnv = p - 1;
1527*e5436536SAndroid Build Coastguard Worker 
1528*e5436536SAndroid Build Coastguard Worker       /* Decode freq res: */
1529*e5436536SAndroid Build Coastguard Worker       for (k = 0; k <= n; k++) {
1530*e5436536SAndroid Build Coastguard Worker         pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
1531*e5436536SAndroid Build Coastguard Worker       }
1532*e5436536SAndroid Build Coastguard Worker 
1533*e5436536SAndroid Build Coastguard Worker       /* Calculate noise floor middle border: */
1534*e5436536SAndroid Build Coastguard Worker       switch (p) {
1535*e5436536SAndroid Build Coastguard Worker         case 0:
1536*e5436536SAndroid Build Coastguard Worker           pFrameInfo->bordersNoise[1] = pFrameInfo->borders[1];
1537*e5436536SAndroid Build Coastguard Worker           break;
1538*e5436536SAndroid Build Coastguard Worker         case 1:
1539*e5436536SAndroid Build Coastguard Worker           pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n];
1540*e5436536SAndroid Build Coastguard Worker           break;
1541*e5436536SAndroid Build Coastguard Worker         default:
1542*e5436536SAndroid Build Coastguard Worker           pFrameInfo->bordersNoise[1] =
1543*e5436536SAndroid Build Coastguard Worker               pFrameInfo->borders[pFrameInfo->tranEnv];
1544*e5436536SAndroid Build Coastguard Worker           break;
1545*e5436536SAndroid Build Coastguard Worker       }
1546*e5436536SAndroid Build Coastguard Worker 
1547*e5436536SAndroid Build Coastguard Worker       break;
1548*e5436536SAndroid Build Coastguard Worker 
1549*e5436536SAndroid Build Coastguard Worker     case 3:
1550*e5436536SAndroid Build Coastguard Worker       /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */
1551*e5436536SAndroid Build Coastguard Worker 
1552*e5436536SAndroid Build Coastguard Worker       aL = FDKreadBits(hBs, 2); /* AL [2 bits], AL -> aL */
1553*e5436536SAndroid Build Coastguard Worker 
1554*e5436536SAndroid Build Coastguard Worker       aR = FDKreadBits(hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */
1555*e5436536SAndroid Build Coastguard Worker 
1556*e5436536SAndroid Build Coastguard Worker       nL = FDKreadBits(hBs, 2); /* nL = NL [2 bits] */
1557*e5436536SAndroid Build Coastguard Worker 
1558*e5436536SAndroid Build Coastguard Worker       nR = FDKreadBits(hBs, 2); /* nR = NR [2 bits] */
1559*e5436536SAndroid Build Coastguard Worker 
1560*e5436536SAndroid Build Coastguard Worker       /*-------------------------------------------------------------------------
1561*e5436536SAndroid Build Coastguard Worker         Calculate help variables
1562*e5436536SAndroid Build Coastguard Worker         --------------------------------------------------------------------------*/
1563*e5436536SAndroid Build Coastguard Worker 
1564*e5436536SAndroid Build Coastguard Worker       /* general: */
1565*e5436536SAndroid Build Coastguard Worker       nEnv = nL + nR + 1; /* # envelopes */
1566*e5436536SAndroid Build Coastguard Worker       if (nEnv > MAX_ENVELOPES) return 0;
1567*e5436536SAndroid Build Coastguard Worker       b = nEnv + 1; /* # borders   */
1568*e5436536SAndroid Build Coastguard Worker 
1569*e5436536SAndroid Build Coastguard Worker       /*-------------------------------------------------------------------------
1570*e5436536SAndroid Build Coastguard Worker         Decode envelopes
1571*e5436536SAndroid Build Coastguard Worker         --------------------------------------------------------------------------*/
1572*e5436536SAndroid Build Coastguard Worker 
1573*e5436536SAndroid Build Coastguard Worker       /* L-borders:   */
1574*e5436536SAndroid Build Coastguard Worker       border = aL; /* first border */
1575*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[0] = border;
1576*e5436536SAndroid Build Coastguard Worker 
1577*e5436536SAndroid Build Coastguard Worker       for (k = 1; k <= nL; k++) {
1578*e5436536SAndroid Build Coastguard Worker         temp = FDKreadBits(hBs, 2); /* R [2 bits] */
1579*e5436536SAndroid Build Coastguard Worker         border += (2 * temp + 2);   /* R -> r                */
1580*e5436536SAndroid Build Coastguard Worker         pFrameInfo->borders[k] = border;
1581*e5436536SAndroid Build Coastguard Worker       }
1582*e5436536SAndroid Build Coastguard Worker 
1583*e5436536SAndroid Build Coastguard Worker       /* R-borders:  */
1584*e5436536SAndroid Build Coastguard Worker       border = aR; /* last border */
1585*e5436536SAndroid Build Coastguard Worker       i = nEnv;
1586*e5436536SAndroid Build Coastguard Worker 
1587*e5436536SAndroid Build Coastguard Worker       pFrameInfo->borders[i] = border;
1588*e5436536SAndroid Build Coastguard Worker 
1589*e5436536SAndroid Build Coastguard Worker       for (k = 0; k < nR; k++) {
1590*e5436536SAndroid Build Coastguard Worker         temp = FDKreadBits(hBs, 2); /* R [2 bits] */
1591*e5436536SAndroid Build Coastguard Worker         border -= (2 * temp + 2);   /* R -> r                */
1592*e5436536SAndroid Build Coastguard Worker         pFrameInfo->borders[--i] = border;
1593*e5436536SAndroid Build Coastguard Worker       }
1594*e5436536SAndroid Build Coastguard Worker 
1595*e5436536SAndroid Build Coastguard Worker       /* decode pointer: */
1596*e5436536SAndroid Build Coastguard Worker       pointer_bits =
1597*e5436536SAndroid Build Coastguard Worker           DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL + nR + 1));
1598*e5436536SAndroid Build Coastguard Worker       p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
1599*e5436536SAndroid Build Coastguard Worker 
1600*e5436536SAndroid Build Coastguard Worker       if (p > nL + nR + 1) return 0;
1601*e5436536SAndroid Build Coastguard Worker 
1602*e5436536SAndroid Build Coastguard Worker       pFrameInfo->tranEnv = p ? b - p : -1;
1603*e5436536SAndroid Build Coastguard Worker 
1604*e5436536SAndroid Build Coastguard Worker       /* decode freq res: */
1605*e5436536SAndroid Build Coastguard Worker       for (k = 0; k < nEnv; k++) {
1606*e5436536SAndroid Build Coastguard Worker         pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
1607*e5436536SAndroid Build Coastguard Worker       }
1608*e5436536SAndroid Build Coastguard Worker 
1609*e5436536SAndroid Build Coastguard Worker       /*-------------------------------------------------------------------------
1610*e5436536SAndroid Build Coastguard Worker         Decode noise floors
1611*e5436536SAndroid Build Coastguard Worker         --------------------------------------------------------------------------*/
1612*e5436536SAndroid Build Coastguard Worker       pFrameInfo->bordersNoise[0] = aL;
1613*e5436536SAndroid Build Coastguard Worker 
1614*e5436536SAndroid Build Coastguard Worker       if (nEnv == 1) {
1615*e5436536SAndroid Build Coastguard Worker         /* 1 noise floor envelope: */
1616*e5436536SAndroid Build Coastguard Worker         pFrameInfo->bordersNoise[1] = aR;
1617*e5436536SAndroid Build Coastguard Worker       } else {
1618*e5436536SAndroid Build Coastguard Worker         /* 2 noise floor envelopes */
1619*e5436536SAndroid Build Coastguard Worker         if (p == 0 || p == 1)
1620*e5436536SAndroid Build Coastguard Worker           pFrameInfo->bordersNoise[1] = pFrameInfo->borders[nEnv - 1];
1621*e5436536SAndroid Build Coastguard Worker         else
1622*e5436536SAndroid Build Coastguard Worker           pFrameInfo->bordersNoise[1] =
1623*e5436536SAndroid Build Coastguard Worker               pFrameInfo->borders[pFrameInfo->tranEnv];
1624*e5436536SAndroid Build Coastguard Worker         pFrameInfo->bordersNoise[2] = aR;
1625*e5436536SAndroid Build Coastguard Worker       }
1626*e5436536SAndroid Build Coastguard Worker       break;
1627*e5436536SAndroid Build Coastguard Worker   }
1628*e5436536SAndroid Build Coastguard Worker 
1629*e5436536SAndroid Build Coastguard Worker   /*
1630*e5436536SAndroid Build Coastguard Worker     Store number of envelopes, noise floor envelopes and frame class
1631*e5436536SAndroid Build Coastguard Worker   */
1632*e5436536SAndroid Build Coastguard Worker   pFrameInfo->nEnvelopes = nEnv;
1633*e5436536SAndroid Build Coastguard Worker 
1634*e5436536SAndroid Build Coastguard Worker   if (nEnv == 1)
1635*e5436536SAndroid Build Coastguard Worker     pFrameInfo->nNoiseEnvelopes = 1;
1636*e5436536SAndroid Build Coastguard Worker   else
1637*e5436536SAndroid Build Coastguard Worker     pFrameInfo->nNoiseEnvelopes = 2;
1638*e5436536SAndroid Build Coastguard Worker 
1639*e5436536SAndroid Build Coastguard Worker   pFrameInfo->frameClass = frameClass;
1640*e5436536SAndroid Build Coastguard Worker 
1641*e5436536SAndroid Build Coastguard Worker   if (pFrameInfo->frameClass == 2 || pFrameInfo->frameClass == 1) {
1642*e5436536SAndroid Build Coastguard Worker     /* calculate noise floor first and last borders: */
1643*e5436536SAndroid Build Coastguard Worker     pFrameInfo->bordersNoise[0] = pFrameInfo->borders[0];
1644*e5436536SAndroid Build Coastguard Worker     pFrameInfo->bordersNoise[pFrameInfo->nNoiseEnvelopes] =
1645*e5436536SAndroid Build Coastguard Worker         pFrameInfo->borders[nEnv];
1646*e5436536SAndroid Build Coastguard Worker   }
1647*e5436536SAndroid Build Coastguard Worker 
1648*e5436536SAndroid Build Coastguard Worker   return 1;
1649*e5436536SAndroid Build Coastguard Worker }
1650*e5436536SAndroid Build Coastguard Worker 
1651*e5436536SAndroid Build Coastguard Worker /*!
1652*e5436536SAndroid Build Coastguard Worker   \brief   Check if the frameInfo vector has reasonable values.
1653*e5436536SAndroid Build Coastguard Worker   \return  Zero for error, one for correct
1654*e5436536SAndroid Build Coastguard Worker */
checkFrameInfo(FRAME_INFO * pFrameInfo,int numberOfTimeSlots,int overlap,int timeStep)1655*e5436536SAndroid Build Coastguard Worker static int checkFrameInfo(
1656*e5436536SAndroid Build Coastguard Worker     FRAME_INFO *pFrameInfo, /*!< pointer to frameInfo */
1657*e5436536SAndroid Build Coastguard Worker     int numberOfTimeSlots,  /*!< QMF time slots per frame */
1658*e5436536SAndroid Build Coastguard Worker     int overlap,            /*!< Amount of overlap QMF time slots */
1659*e5436536SAndroid Build Coastguard Worker     int timeStep)           /*!< QMF slots to SBR slots step factor */
1660*e5436536SAndroid Build Coastguard Worker {
1661*e5436536SAndroid Build Coastguard Worker   int maxPos, i, j;
1662*e5436536SAndroid Build Coastguard Worker   int startPos;
1663*e5436536SAndroid Build Coastguard Worker   int stopPos;
1664*e5436536SAndroid Build Coastguard Worker   int tranEnv;
1665*e5436536SAndroid Build Coastguard Worker   int startPosNoise;
1666*e5436536SAndroid Build Coastguard Worker   int stopPosNoise;
1667*e5436536SAndroid Build Coastguard Worker   int nEnvelopes = pFrameInfo->nEnvelopes;
1668*e5436536SAndroid Build Coastguard Worker   int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes;
1669*e5436536SAndroid Build Coastguard Worker 
1670*e5436536SAndroid Build Coastguard Worker   if (nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) return 0;
1671*e5436536SAndroid Build Coastguard Worker 
1672*e5436536SAndroid Build Coastguard Worker   if (nNoiseEnvelopes > MAX_NOISE_ENVELOPES) return 0;
1673*e5436536SAndroid Build Coastguard Worker 
1674*e5436536SAndroid Build Coastguard Worker   startPos = pFrameInfo->borders[0];
1675*e5436536SAndroid Build Coastguard Worker   stopPos = pFrameInfo->borders[nEnvelopes];
1676*e5436536SAndroid Build Coastguard Worker   tranEnv = pFrameInfo->tranEnv;
1677*e5436536SAndroid Build Coastguard Worker   startPosNoise = pFrameInfo->bordersNoise[0];
1678*e5436536SAndroid Build Coastguard Worker   stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes];
1679*e5436536SAndroid Build Coastguard Worker 
1680*e5436536SAndroid Build Coastguard Worker   if (overlap < 0 || overlap > (3 * (4))) {
1681*e5436536SAndroid Build Coastguard Worker     return 0;
1682*e5436536SAndroid Build Coastguard Worker   }
1683*e5436536SAndroid Build Coastguard Worker   if (timeStep < 1 || timeStep > (4)) {
1684*e5436536SAndroid Build Coastguard Worker     return 0;
1685*e5436536SAndroid Build Coastguard Worker   }
1686*e5436536SAndroid Build Coastguard Worker   maxPos = numberOfTimeSlots + (overlap / timeStep);
1687*e5436536SAndroid Build Coastguard Worker 
1688*e5436536SAndroid Build Coastguard Worker   /* Check that the start and stop positions of the frame are reasonable values.
1689*e5436536SAndroid Build Coastguard Worker    */
1690*e5436536SAndroid Build Coastguard Worker   if ((startPos < 0) || (startPos >= stopPos)) return 0;
1691*e5436536SAndroid Build Coastguard Worker   if (startPos > maxPos - numberOfTimeSlots) /* First env. must start in or
1692*e5436536SAndroid Build Coastguard Worker                                                 directly after the overlap
1693*e5436536SAndroid Build Coastguard Worker                                                 buffer */
1694*e5436536SAndroid Build Coastguard Worker     return 0;
1695*e5436536SAndroid Build Coastguard Worker   if (stopPos < numberOfTimeSlots) /* One complete frame must be ready for
1696*e5436536SAndroid Build Coastguard Worker                                       output after processing */
1697*e5436536SAndroid Build Coastguard Worker     return 0;
1698*e5436536SAndroid Build Coastguard Worker   if (stopPos > maxPos) return 0;
1699*e5436536SAndroid Build Coastguard Worker 
1700*e5436536SAndroid Build Coastguard Worker   /* Check that the  start border for every envelope is strictly later in time
1701*e5436536SAndroid Build Coastguard Worker    */
1702*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nEnvelopes; i++) {
1703*e5436536SAndroid Build Coastguard Worker     if (pFrameInfo->borders[i] >= pFrameInfo->borders[i + 1]) return 0;
1704*e5436536SAndroid Build Coastguard Worker   }
1705*e5436536SAndroid Build Coastguard Worker 
1706*e5436536SAndroid Build Coastguard Worker   /* Check that the envelope to be shortened is actually among the envelopes */
1707*e5436536SAndroid Build Coastguard Worker   if (tranEnv > nEnvelopes) return 0;
1708*e5436536SAndroid Build Coastguard Worker 
1709*e5436536SAndroid Build Coastguard Worker   /* Check the noise borders */
1710*e5436536SAndroid Build Coastguard Worker   if (nEnvelopes == 1 && nNoiseEnvelopes > 1) return 0;
1711*e5436536SAndroid Build Coastguard Worker 
1712*e5436536SAndroid Build Coastguard Worker   if (startPos != startPosNoise || stopPos != stopPosNoise) return 0;
1713*e5436536SAndroid Build Coastguard Worker 
1714*e5436536SAndroid Build Coastguard Worker   /* Check that the  start border for every noise-envelope is strictly later in
1715*e5436536SAndroid Build Coastguard Worker    * time*/
1716*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nNoiseEnvelopes; i++) {
1717*e5436536SAndroid Build Coastguard Worker     if (pFrameInfo->bordersNoise[i] >= pFrameInfo->bordersNoise[i + 1])
1718*e5436536SAndroid Build Coastguard Worker       return 0;
1719*e5436536SAndroid Build Coastguard Worker   }
1720*e5436536SAndroid Build Coastguard Worker 
1721*e5436536SAndroid Build Coastguard Worker   /* Check that every noise border is the same as an envelope border*/
1722*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < nNoiseEnvelopes; i++) {
1723*e5436536SAndroid Build Coastguard Worker     startPosNoise = pFrameInfo->bordersNoise[i];
1724*e5436536SAndroid Build Coastguard Worker 
1725*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < nEnvelopes; j++) {
1726*e5436536SAndroid Build Coastguard Worker       if (pFrameInfo->borders[j] == startPosNoise) break;
1727*e5436536SAndroid Build Coastguard Worker     }
1728*e5436536SAndroid Build Coastguard Worker     if (j == nEnvelopes) return 0;
1729*e5436536SAndroid Build Coastguard Worker   }
1730*e5436536SAndroid Build Coastguard Worker 
1731*e5436536SAndroid Build Coastguard Worker   return 1;
1732*e5436536SAndroid Build Coastguard Worker }
1733