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