xref: /aosp_15_r20/external/aac/libDRCdec/src/drcDec_reader.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /************************* MPEG-D DRC 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 #include "fixpoint_math.h"
104*e5436536SAndroid Build Coastguard Worker #include "drcDec_reader.h"
105*e5436536SAndroid Build Coastguard Worker #include "drcDec_tools.h"
106*e5436536SAndroid Build Coastguard Worker #include "drcDec_rom.h"
107*e5436536SAndroid Build Coastguard Worker #include "drcDecoder.h"
108*e5436536SAndroid Build Coastguard Worker 
109*e5436536SAndroid Build Coastguard Worker /* MPEG-D DRC AMD 1 */
110*e5436536SAndroid Build Coastguard Worker 
111*e5436536SAndroid Build Coastguard Worker #define UNIDRCCONFEXT_PARAM_DRC 0x1
112*e5436536SAndroid Build Coastguard Worker #define UNIDRCCONFEXT_V1 0x2
113*e5436536SAndroid Build Coastguard Worker #define UNIDRCLOUDEXT_EQ 0x1
114*e5436536SAndroid Build Coastguard Worker 
115*e5436536SAndroid Build Coastguard Worker #define UNIDRCGAINEXT_TERM 0x0
116*e5436536SAndroid Build Coastguard Worker #define UNIDRCLOUDEXT_TERM 0x0
117*e5436536SAndroid Build Coastguard Worker #define UNIDRCCONFEXT_TERM 0x0
118*e5436536SAndroid Build Coastguard Worker 
_getZ(const int nNodesMax)119*e5436536SAndroid Build Coastguard Worker static int _getZ(const int nNodesMax) {
120*e5436536SAndroid Build Coastguard Worker   /* Z is the minimum codeword length that is needed to encode all possible
121*e5436536SAndroid Build Coastguard Worker    * timeDelta values */
122*e5436536SAndroid Build Coastguard Worker   /* Z = ceil(log2(2*nNodesMax)) */
123*e5436536SAndroid Build Coastguard Worker   int Z = 1;
124*e5436536SAndroid Build Coastguard Worker   while ((1 << Z) < (2 * nNodesMax)) {
125*e5436536SAndroid Build Coastguard Worker     Z++;
126*e5436536SAndroid Build Coastguard Worker   }
127*e5436536SAndroid Build Coastguard Worker   return Z;
128*e5436536SAndroid Build Coastguard Worker }
129*e5436536SAndroid Build Coastguard Worker 
_getTimeDeltaMin(const GAIN_SET * pGset,const int deltaTminDefault)130*e5436536SAndroid Build Coastguard Worker static int _getTimeDeltaMin(const GAIN_SET* pGset, const int deltaTminDefault) {
131*e5436536SAndroid Build Coastguard Worker   if (pGset->timeDeltaMinPresent) {
132*e5436536SAndroid Build Coastguard Worker     return pGset->timeDeltaMin;
133*e5436536SAndroid Build Coastguard Worker   } else {
134*e5436536SAndroid Build Coastguard Worker     return deltaTminDefault;
135*e5436536SAndroid Build Coastguard Worker   }
136*e5436536SAndroid Build Coastguard Worker }
137*e5436536SAndroid Build Coastguard Worker 
138*e5436536SAndroid Build Coastguard Worker /* compare and assign */
_compAssign(UCHAR * dest,const UCHAR src)139*e5436536SAndroid Build Coastguard Worker static inline int _compAssign(UCHAR* dest, const UCHAR src) {
140*e5436536SAndroid Build Coastguard Worker   int diff = 0;
141*e5436536SAndroid Build Coastguard Worker   if (*dest != src) diff = 1;
142*e5436536SAndroid Build Coastguard Worker   *dest = src;
143*e5436536SAndroid Build Coastguard Worker   return diff;
144*e5436536SAndroid Build Coastguard Worker }
145*e5436536SAndroid Build Coastguard Worker 
_compAssign(ULONG * dest,const ULONG src)146*e5436536SAndroid Build Coastguard Worker static inline int _compAssign(ULONG* dest, const ULONG src) {
147*e5436536SAndroid Build Coastguard Worker   int diff = 0;
148*e5436536SAndroid Build Coastguard Worker   if (*dest != src) diff = 1;
149*e5436536SAndroid Build Coastguard Worker   *dest = src;
150*e5436536SAndroid Build Coastguard Worker   return diff;
151*e5436536SAndroid Build Coastguard Worker }
152*e5436536SAndroid Build Coastguard Worker 
153*e5436536SAndroid Build Coastguard Worker typedef const SCHAR (*Huffman)[2];
154*e5436536SAndroid Build Coastguard Worker 
_decodeHuffmanCW(Huffman h,HANDLE_FDK_BITSTREAM hBs)155*e5436536SAndroid Build Coastguard Worker int _decodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */
156*e5436536SAndroid Build Coastguard Worker                      HANDLE_FDK_BITSTREAM hBs) /*!< Handle to bitbuffer */
157*e5436536SAndroid Build Coastguard Worker {
158*e5436536SAndroid Build Coastguard Worker   SCHAR index = 0;
159*e5436536SAndroid Build Coastguard Worker   int value, bit;
160*e5436536SAndroid Build Coastguard Worker 
161*e5436536SAndroid Build Coastguard Worker   while (index >= 0) {
162*e5436536SAndroid Build Coastguard Worker     bit = FDKreadBits(hBs, 1);
163*e5436536SAndroid Build Coastguard Worker     index = h[index][bit];
164*e5436536SAndroid Build Coastguard Worker   }
165*e5436536SAndroid Build Coastguard Worker 
166*e5436536SAndroid Build Coastguard Worker   value = index + 64; /* Add offset */
167*e5436536SAndroid Build Coastguard Worker 
168*e5436536SAndroid Build Coastguard Worker   return value;
169*e5436536SAndroid Build Coastguard Worker }
170*e5436536SAndroid Build Coastguard Worker 
171*e5436536SAndroid Build Coastguard Worker /**********/
172*e5436536SAndroid Build Coastguard Worker /* uniDrc */
173*e5436536SAndroid Build Coastguard Worker /**********/
174*e5436536SAndroid Build Coastguard Worker 
175*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig,HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet,const int frameSize,const int deltaTminDefault,HANDLE_UNI_DRC_GAIN hUniDrcGain)176*e5436536SAndroid Build Coastguard Worker drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
177*e5436536SAndroid Build Coastguard Worker                   HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet,
178*e5436536SAndroid Build Coastguard Worker                   const int frameSize, const int deltaTminDefault,
179*e5436536SAndroid Build Coastguard Worker                   HANDLE_UNI_DRC_GAIN hUniDrcGain) {
180*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
181*e5436536SAndroid Build Coastguard Worker   int loudnessInfoSetPresent, uniDrcConfigPresent;
182*e5436536SAndroid Build Coastguard Worker 
183*e5436536SAndroid Build Coastguard Worker   loudnessInfoSetPresent = FDKreadBits(hBs, 1);
184*e5436536SAndroid Build Coastguard Worker   if (loudnessInfoSetPresent) {
185*e5436536SAndroid Build Coastguard Worker     uniDrcConfigPresent = FDKreadBits(hBs, 1);
186*e5436536SAndroid Build Coastguard Worker     if (uniDrcConfigPresent) {
187*e5436536SAndroid Build Coastguard Worker       err = drcDec_readUniDrcConfig(hBs, hUniDrcConfig);
188*e5436536SAndroid Build Coastguard Worker       if (err) {
189*e5436536SAndroid Build Coastguard Worker         /* clear config, if parsing error occured */
190*e5436536SAndroid Build Coastguard Worker         FDKmemclear(hUniDrcConfig, sizeof(UNI_DRC_CONFIG));
191*e5436536SAndroid Build Coastguard Worker         hUniDrcConfig->diff = 1;
192*e5436536SAndroid Build Coastguard Worker       }
193*e5436536SAndroid Build Coastguard Worker     }
194*e5436536SAndroid Build Coastguard Worker     err = drcDec_readLoudnessInfoSet(hBs, hLoudnessInfoSet);
195*e5436536SAndroid Build Coastguard Worker     if (err) {
196*e5436536SAndroid Build Coastguard Worker       /* clear config, if parsing error occured */
197*e5436536SAndroid Build Coastguard Worker       FDKmemclear(hLoudnessInfoSet, sizeof(LOUDNESS_INFO_SET));
198*e5436536SAndroid Build Coastguard Worker       hLoudnessInfoSet->diff = 1;
199*e5436536SAndroid Build Coastguard Worker     }
200*e5436536SAndroid Build Coastguard Worker   }
201*e5436536SAndroid Build Coastguard Worker 
202*e5436536SAndroid Build Coastguard Worker   err = drcDec_readUniDrcGain(hBs, hUniDrcConfig, frameSize, deltaTminDefault,
203*e5436536SAndroid Build Coastguard Worker                               hUniDrcGain);
204*e5436536SAndroid Build Coastguard Worker 
205*e5436536SAndroid Build Coastguard Worker   return err;
206*e5436536SAndroid Build Coastguard Worker }
207*e5436536SAndroid Build Coastguard Worker 
208*e5436536SAndroid Build Coastguard Worker /**************/
209*e5436536SAndroid Build Coastguard Worker /* uniDrcGain */
210*e5436536SAndroid Build Coastguard Worker /**************/
211*e5436536SAndroid Build Coastguard Worker 
_decodeGainInitial(HANDLE_FDK_BITSTREAM hBs,const GAIN_CODING_PROFILE gainCodingProfile)212*e5436536SAndroid Build Coastguard Worker static FIXP_SGL _decodeGainInitial(
213*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, const GAIN_CODING_PROFILE gainCodingProfile) {
214*e5436536SAndroid Build Coastguard Worker   int sign, magn;
215*e5436536SAndroid Build Coastguard Worker   FIXP_SGL gainInitial = (FIXP_SGL)0;
216*e5436536SAndroid Build Coastguard Worker   switch (gainCodingProfile) {
217*e5436536SAndroid Build Coastguard Worker     case GCP_REGULAR:
218*e5436536SAndroid Build Coastguard Worker       sign = FDKreadBits(hBs, 1);
219*e5436536SAndroid Build Coastguard Worker       magn = FDKreadBits(hBs, 8);
220*e5436536SAndroid Build Coastguard Worker 
221*e5436536SAndroid Build Coastguard Worker       gainInitial =
222*e5436536SAndroid Build Coastguard Worker           (FIXP_SGL)(magn << (FRACT_BITS - 1 - 3 - 7)); /* magn * 0.125; */
223*e5436536SAndroid Build Coastguard Worker       if (sign) gainInitial = -gainInitial;
224*e5436536SAndroid Build Coastguard Worker       break;
225*e5436536SAndroid Build Coastguard Worker     case GCP_FADING:
226*e5436536SAndroid Build Coastguard Worker       sign = FDKreadBits(hBs, 1);
227*e5436536SAndroid Build Coastguard Worker       if (sign == 0)
228*e5436536SAndroid Build Coastguard Worker         gainInitial = (FIXP_SGL)0;
229*e5436536SAndroid Build Coastguard Worker       else {
230*e5436536SAndroid Build Coastguard Worker         magn = FDKreadBits(hBs, 10);
231*e5436536SAndroid Build Coastguard Worker         gainInitial = -(FIXP_SGL)(
232*e5436536SAndroid Build Coastguard Worker             (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */
233*e5436536SAndroid Build Coastguard Worker       }
234*e5436536SAndroid Build Coastguard Worker       break;
235*e5436536SAndroid Build Coastguard Worker     case GCP_CLIPPING_DUCKING:
236*e5436536SAndroid Build Coastguard Worker       sign = FDKreadBits(hBs, 1);
237*e5436536SAndroid Build Coastguard Worker       if (sign == 0)
238*e5436536SAndroid Build Coastguard Worker         gainInitial = (FIXP_SGL)0;
239*e5436536SAndroid Build Coastguard Worker       else {
240*e5436536SAndroid Build Coastguard Worker         magn = FDKreadBits(hBs, 8);
241*e5436536SAndroid Build Coastguard Worker         gainInitial = -(FIXP_SGL)(
242*e5436536SAndroid Build Coastguard Worker             (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */
243*e5436536SAndroid Build Coastguard Worker       }
244*e5436536SAndroid Build Coastguard Worker       break;
245*e5436536SAndroid Build Coastguard Worker     case GCP_CONSTANT:
246*e5436536SAndroid Build Coastguard Worker       break;
247*e5436536SAndroid Build Coastguard Worker   }
248*e5436536SAndroid Build Coastguard Worker   return gainInitial;
249*e5436536SAndroid Build Coastguard Worker }
250*e5436536SAndroid Build Coastguard Worker 
_decodeNNodes(HANDLE_FDK_BITSTREAM hBs)251*e5436536SAndroid Build Coastguard Worker static int _decodeNNodes(HANDLE_FDK_BITSTREAM hBs) {
252*e5436536SAndroid Build Coastguard Worker   int nNodes = 0, endMarker = 0;
253*e5436536SAndroid Build Coastguard Worker 
254*e5436536SAndroid Build Coastguard Worker   /* decode number of nodes */
255*e5436536SAndroid Build Coastguard Worker   while (endMarker != 1) {
256*e5436536SAndroid Build Coastguard Worker     nNodes++;
257*e5436536SAndroid Build Coastguard Worker     if (nNodes >= 128) break;
258*e5436536SAndroid Build Coastguard Worker     endMarker = FDKreadBits(hBs, 1);
259*e5436536SAndroid Build Coastguard Worker   }
260*e5436536SAndroid Build Coastguard Worker   return nNodes;
261*e5436536SAndroid Build Coastguard Worker }
262*e5436536SAndroid Build Coastguard Worker 
_decodeGains(HANDLE_FDK_BITSTREAM hBs,const GAIN_CODING_PROFILE gainCodingProfile,const int nNodes,GAIN_NODE * pNodes)263*e5436536SAndroid Build Coastguard Worker static void _decodeGains(HANDLE_FDK_BITSTREAM hBs,
264*e5436536SAndroid Build Coastguard Worker                          const GAIN_CODING_PROFILE gainCodingProfile,
265*e5436536SAndroid Build Coastguard Worker                          const int nNodes, GAIN_NODE* pNodes) {
266*e5436536SAndroid Build Coastguard Worker   int k, deltaGain;
267*e5436536SAndroid Build Coastguard Worker   Huffman deltaGainCodebook;
268*e5436536SAndroid Build Coastguard Worker 
269*e5436536SAndroid Build Coastguard Worker   pNodes[0].gainDb = _decodeGainInitial(hBs, gainCodingProfile);
270*e5436536SAndroid Build Coastguard Worker 
271*e5436536SAndroid Build Coastguard Worker   if (gainCodingProfile == GCP_CLIPPING_DUCKING) {
272*e5436536SAndroid Build Coastguard Worker     deltaGainCodebook = (Huffman)&deltaGain_codingProfile_2_huffman;
273*e5436536SAndroid Build Coastguard Worker   } else {
274*e5436536SAndroid Build Coastguard Worker     deltaGainCodebook = (Huffman)&deltaGain_codingProfile_0_1_huffman;
275*e5436536SAndroid Build Coastguard Worker   }
276*e5436536SAndroid Build Coastguard Worker 
277*e5436536SAndroid Build Coastguard Worker   for (k = 1; k < nNodes; k++) {
278*e5436536SAndroid Build Coastguard Worker     deltaGain = _decodeHuffmanCW(deltaGainCodebook, hBs);
279*e5436536SAndroid Build Coastguard Worker     if (k >= 16) continue;
280*e5436536SAndroid Build Coastguard Worker     /* gain_dB_e = 7 */
281*e5436536SAndroid Build Coastguard Worker     pNodes[k].gainDb =
282*e5436536SAndroid Build Coastguard Worker         pNodes[k - 1].gainDb +
283*e5436536SAndroid Build Coastguard Worker         (FIXP_SGL)(deltaGain << (FRACT_BITS - 1 - 7 -
284*e5436536SAndroid Build Coastguard Worker                                  3)); /* pNodes[k-1].gainDb + 0.125*deltaGain */
285*e5436536SAndroid Build Coastguard Worker   }
286*e5436536SAndroid Build Coastguard Worker }
287*e5436536SAndroid Build Coastguard Worker 
_decodeSlopes(HANDLE_FDK_BITSTREAM hBs,const GAIN_INTERPOLATION_TYPE gainInterpolationType,const int nNodes,GAIN_NODE * pNodes)288*e5436536SAndroid Build Coastguard Worker static void _decodeSlopes(HANDLE_FDK_BITSTREAM hBs,
289*e5436536SAndroid Build Coastguard Worker                           const GAIN_INTERPOLATION_TYPE gainInterpolationType,
290*e5436536SAndroid Build Coastguard Worker                           const int nNodes, GAIN_NODE* pNodes) {
291*e5436536SAndroid Build Coastguard Worker   int k = 0;
292*e5436536SAndroid Build Coastguard Worker 
293*e5436536SAndroid Build Coastguard Worker   if (gainInterpolationType == GIT_SPLINE) {
294*e5436536SAndroid Build Coastguard Worker     /* decode slope steepness */
295*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < nNodes; k++) {
296*e5436536SAndroid Build Coastguard Worker       _decodeHuffmanCW((Huffman)&slopeSteepness_huffman, hBs);
297*e5436536SAndroid Build Coastguard Worker     }
298*e5436536SAndroid Build Coastguard Worker   }
299*e5436536SAndroid Build Coastguard Worker }
300*e5436536SAndroid Build Coastguard Worker 
_decodeTimeDelta(HANDLE_FDK_BITSTREAM hBs,const int Z)301*e5436536SAndroid Build Coastguard Worker static int _decodeTimeDelta(HANDLE_FDK_BITSTREAM hBs, const int Z) {
302*e5436536SAndroid Build Coastguard Worker   int prefix, mu;
303*e5436536SAndroid Build Coastguard Worker 
304*e5436536SAndroid Build Coastguard Worker   prefix = FDKreadBits(hBs, 2);
305*e5436536SAndroid Build Coastguard Worker   switch (prefix) {
306*e5436536SAndroid Build Coastguard Worker     case 0x0:
307*e5436536SAndroid Build Coastguard Worker       return 1;
308*e5436536SAndroid Build Coastguard Worker     case 0x1:
309*e5436536SAndroid Build Coastguard Worker       mu = FDKreadBits(hBs, 2);
310*e5436536SAndroid Build Coastguard Worker       return mu + 2;
311*e5436536SAndroid Build Coastguard Worker     case 0x2:
312*e5436536SAndroid Build Coastguard Worker       mu = FDKreadBits(hBs, 3);
313*e5436536SAndroid Build Coastguard Worker       return mu + 6;
314*e5436536SAndroid Build Coastguard Worker     case 0x3:
315*e5436536SAndroid Build Coastguard Worker       mu = FDKreadBits(hBs, Z);
316*e5436536SAndroid Build Coastguard Worker       return mu + 14;
317*e5436536SAndroid Build Coastguard Worker     default:
318*e5436536SAndroid Build Coastguard Worker       return 0;
319*e5436536SAndroid Build Coastguard Worker   }
320*e5436536SAndroid Build Coastguard Worker }
321*e5436536SAndroid Build Coastguard Worker 
_decodeTimes(HANDLE_FDK_BITSTREAM hBs,const int deltaTmin,const int frameSize,const int fullFrame,const int timeOffset,const int Z,const int nNodes,GAIN_NODE * pNodes)322*e5436536SAndroid Build Coastguard Worker static void _decodeTimes(HANDLE_FDK_BITSTREAM hBs, const int deltaTmin,
323*e5436536SAndroid Build Coastguard Worker                          const int frameSize, const int fullFrame,
324*e5436536SAndroid Build Coastguard Worker                          const int timeOffset, const int Z, const int nNodes,
325*e5436536SAndroid Build Coastguard Worker                          GAIN_NODE* pNodes) {
326*e5436536SAndroid Build Coastguard Worker   int timeDelta, k;
327*e5436536SAndroid Build Coastguard Worker   int timeOffs = timeOffset;
328*e5436536SAndroid Build Coastguard Worker   int frameEndFlag, nodeTimeTmp, nodeResFlag;
329*e5436536SAndroid Build Coastguard Worker 
330*e5436536SAndroid Build Coastguard Worker   if (fullFrame == 0) {
331*e5436536SAndroid Build Coastguard Worker     frameEndFlag = FDKreadBits(hBs, 1);
332*e5436536SAndroid Build Coastguard Worker   } else {
333*e5436536SAndroid Build Coastguard Worker     frameEndFlag = 1;
334*e5436536SAndroid Build Coastguard Worker   }
335*e5436536SAndroid Build Coastguard Worker 
336*e5436536SAndroid Build Coastguard Worker   if (frameEndFlag ==
337*e5436536SAndroid Build Coastguard Worker       1) { /* frameEndFlag == 1 signals that the last node is at the end of the
338*e5436536SAndroid Build Coastguard Worker               DRC frame */
339*e5436536SAndroid Build Coastguard Worker     nodeResFlag = 0;
340*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < nNodes - 1; k++) {
341*e5436536SAndroid Build Coastguard Worker       /* decode a delta time value */
342*e5436536SAndroid Build Coastguard Worker       timeDelta = _decodeTimeDelta(hBs, Z);
343*e5436536SAndroid Build Coastguard Worker       if (k >= (16 - 1)) continue;
344*e5436536SAndroid Build Coastguard Worker       /* frameEndFlag == 1 needs special handling for last node with node
345*e5436536SAndroid Build Coastguard Worker        * reservoir */
346*e5436536SAndroid Build Coastguard Worker       nodeTimeTmp = timeOffs + timeDelta * deltaTmin;
347*e5436536SAndroid Build Coastguard Worker       if (nodeTimeTmp > frameSize + timeOffset) {
348*e5436536SAndroid Build Coastguard Worker         if (nodeResFlag == 0) {
349*e5436536SAndroid Build Coastguard Worker           pNodes[k].time = frameSize + timeOffset;
350*e5436536SAndroid Build Coastguard Worker           nodeResFlag = 1;
351*e5436536SAndroid Build Coastguard Worker         }
352*e5436536SAndroid Build Coastguard Worker         pNodes[k + 1].time = nodeTimeTmp;
353*e5436536SAndroid Build Coastguard Worker       } else {
354*e5436536SAndroid Build Coastguard Worker         pNodes[k].time = nodeTimeTmp;
355*e5436536SAndroid Build Coastguard Worker       }
356*e5436536SAndroid Build Coastguard Worker       timeOffs = nodeTimeTmp;
357*e5436536SAndroid Build Coastguard Worker     }
358*e5436536SAndroid Build Coastguard Worker     if (nodeResFlag == 0) {
359*e5436536SAndroid Build Coastguard Worker       k = fMin(k, 16 - 1);
360*e5436536SAndroid Build Coastguard Worker       pNodes[k].time = frameSize + timeOffset;
361*e5436536SAndroid Build Coastguard Worker     }
362*e5436536SAndroid Build Coastguard Worker   } else {
363*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < nNodes; k++) {
364*e5436536SAndroid Build Coastguard Worker       /* decode a delta time value */
365*e5436536SAndroid Build Coastguard Worker       timeDelta = _decodeTimeDelta(hBs, Z);
366*e5436536SAndroid Build Coastguard Worker       if (k >= 16) continue;
367*e5436536SAndroid Build Coastguard Worker       pNodes[k].time = timeOffs + timeDelta * deltaTmin;
368*e5436536SAndroid Build Coastguard Worker       timeOffs = pNodes[k].time;
369*e5436536SAndroid Build Coastguard Worker     }
370*e5436536SAndroid Build Coastguard Worker   }
371*e5436536SAndroid Build Coastguard Worker }
372*e5436536SAndroid Build Coastguard Worker 
_readNodes(HANDLE_FDK_BITSTREAM hBs,GAIN_SET * gainSet,const int frameSize,const int timeDeltaMin,UCHAR * pNNodes,GAIN_NODE * pNodes)373*e5436536SAndroid Build Coastguard Worker static void _readNodes(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet,
374*e5436536SAndroid Build Coastguard Worker                        const int frameSize, const int timeDeltaMin,
375*e5436536SAndroid Build Coastguard Worker                        UCHAR* pNNodes, GAIN_NODE* pNodes) {
376*e5436536SAndroid Build Coastguard Worker   int timeOffset, drcGainCodingMode, nNodes;
377*e5436536SAndroid Build Coastguard Worker   int Z = _getZ(frameSize / timeDeltaMin);
378*e5436536SAndroid Build Coastguard Worker   if (gainSet->timeAlignment == 0) {
379*e5436536SAndroid Build Coastguard Worker     timeOffset = -1;
380*e5436536SAndroid Build Coastguard Worker   } else {
381*e5436536SAndroid Build Coastguard Worker     timeOffset = -timeDeltaMin +
382*e5436536SAndroid Build Coastguard Worker                  (timeDeltaMin - 1) /
383*e5436536SAndroid Build Coastguard Worker                      2; /* timeOffset = - deltaTmin + floor((deltaTmin-1)/2); */
384*e5436536SAndroid Build Coastguard Worker   }
385*e5436536SAndroid Build Coastguard Worker 
386*e5436536SAndroid Build Coastguard Worker   drcGainCodingMode = FDKreadBits(hBs, 1);
387*e5436536SAndroid Build Coastguard Worker   if (drcGainCodingMode == 0) {
388*e5436536SAndroid Build Coastguard Worker     /* "simple" mode: only one node at the end of the frame with slope = 0 */
389*e5436536SAndroid Build Coastguard Worker     nNodes = 1;
390*e5436536SAndroid Build Coastguard Worker     pNodes[0].gainDb = _decodeGainInitial(
391*e5436536SAndroid Build Coastguard Worker         hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile);
392*e5436536SAndroid Build Coastguard Worker     pNodes[0].time = frameSize + timeOffset;
393*e5436536SAndroid Build Coastguard Worker   } else {
394*e5436536SAndroid Build Coastguard Worker     nNodes = _decodeNNodes(hBs);
395*e5436536SAndroid Build Coastguard Worker 
396*e5436536SAndroid Build Coastguard Worker     _decodeSlopes(hBs, (GAIN_INTERPOLATION_TYPE)gainSet->gainInterpolationType,
397*e5436536SAndroid Build Coastguard Worker                   nNodes, pNodes);
398*e5436536SAndroid Build Coastguard Worker 
399*e5436536SAndroid Build Coastguard Worker     _decodeTimes(hBs, timeDeltaMin, frameSize, gainSet->fullFrame, timeOffset,
400*e5436536SAndroid Build Coastguard Worker                  Z, nNodes, pNodes);
401*e5436536SAndroid Build Coastguard Worker 
402*e5436536SAndroid Build Coastguard Worker     _decodeGains(hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile, nNodes,
403*e5436536SAndroid Build Coastguard Worker                  pNodes);
404*e5436536SAndroid Build Coastguard Worker   }
405*e5436536SAndroid Build Coastguard Worker   *pNNodes = (UCHAR)nNodes;
406*e5436536SAndroid Build Coastguard Worker }
407*e5436536SAndroid Build Coastguard Worker 
_readDrcGainSequence(HANDLE_FDK_BITSTREAM hBs,GAIN_SET * gainSet,const int frameSize,const int timeDeltaMin,UCHAR * pNNodes,GAIN_NODE pNodes[16])408*e5436536SAndroid Build Coastguard Worker static void _readDrcGainSequence(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet,
409*e5436536SAndroid Build Coastguard Worker                                  const int frameSize, const int timeDeltaMin,
410*e5436536SAndroid Build Coastguard Worker                                  UCHAR* pNNodes, GAIN_NODE pNodes[16]) {
411*e5436536SAndroid Build Coastguard Worker   SHORT timeBufPrevFrame[16], timeBufCurFrame[16];
412*e5436536SAndroid Build Coastguard Worker   int nNodesNodeRes, nNodesCur, k, m;
413*e5436536SAndroid Build Coastguard Worker 
414*e5436536SAndroid Build Coastguard Worker   if (gainSet->gainCodingProfile == GCP_CONSTANT) {
415*e5436536SAndroid Build Coastguard Worker     *pNNodes = 1;
416*e5436536SAndroid Build Coastguard Worker     pNodes[0].time = frameSize - 1;
417*e5436536SAndroid Build Coastguard Worker     pNodes[0].gainDb = (FIXP_SGL)0;
418*e5436536SAndroid Build Coastguard Worker   } else {
419*e5436536SAndroid Build Coastguard Worker     _readNodes(hBs, gainSet, frameSize, timeDeltaMin, pNNodes, pNodes);
420*e5436536SAndroid Build Coastguard Worker 
421*e5436536SAndroid Build Coastguard Worker     /* count number of nodes in node reservoir */
422*e5436536SAndroid Build Coastguard Worker     nNodesNodeRes = 0;
423*e5436536SAndroid Build Coastguard Worker     nNodesCur = 0;
424*e5436536SAndroid Build Coastguard Worker     /* count and buffer nodes from node reservoir */
425*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < *pNNodes; k++) {
426*e5436536SAndroid Build Coastguard Worker       if (k >= 16) continue;
427*e5436536SAndroid Build Coastguard Worker       if (pNodes[k].time >= frameSize) {
428*e5436536SAndroid Build Coastguard Worker         /* write node reservoir times into buffer */
429*e5436536SAndroid Build Coastguard Worker         timeBufPrevFrame[nNodesNodeRes] = pNodes[k].time;
430*e5436536SAndroid Build Coastguard Worker         nNodesNodeRes++;
431*e5436536SAndroid Build Coastguard Worker       } else { /* times from current frame */
432*e5436536SAndroid Build Coastguard Worker         timeBufCurFrame[nNodesCur] = pNodes[k].time;
433*e5436536SAndroid Build Coastguard Worker         nNodesCur++;
434*e5436536SAndroid Build Coastguard Worker       }
435*e5436536SAndroid Build Coastguard Worker     }
436*e5436536SAndroid Build Coastguard Worker     /* compose right time order (bit reservoir first) */
437*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < nNodesNodeRes; k++) {
438*e5436536SAndroid Build Coastguard Worker       /* subtract two time frameSize: one to remove node reservoir offset and
439*e5436536SAndroid Build Coastguard Worker        * one to get the negative index relative to the current frame
440*e5436536SAndroid Build Coastguard Worker        */
441*e5436536SAndroid Build Coastguard Worker       pNodes[k].time = timeBufPrevFrame[k] - 2 * frameSize;
442*e5436536SAndroid Build Coastguard Worker     }
443*e5436536SAndroid Build Coastguard Worker     /* ...and times from current frame */
444*e5436536SAndroid Build Coastguard Worker     for (m = 0; m < nNodesCur; m++, k++) {
445*e5436536SAndroid Build Coastguard Worker       pNodes[k].time = timeBufCurFrame[m];
446*e5436536SAndroid Build Coastguard Worker     }
447*e5436536SAndroid Build Coastguard Worker   }
448*e5436536SAndroid Build Coastguard Worker }
449*e5436536SAndroid Build Coastguard Worker 
_readUniDrcGainExtension(HANDLE_FDK_BITSTREAM hBs,UNI_DRC_GAIN_EXTENSION * pExt)450*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readUniDrcGainExtension(HANDLE_FDK_BITSTREAM hBs,
451*e5436536SAndroid Build Coastguard Worker                                           UNI_DRC_GAIN_EXTENSION* pExt) {
452*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
453*e5436536SAndroid Build Coastguard Worker   int k, bitSizeLen, extSizeBits, bitSize;
454*e5436536SAndroid Build Coastguard Worker 
455*e5436536SAndroid Build Coastguard Worker   k = 0;
456*e5436536SAndroid Build Coastguard Worker   pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4);
457*e5436536SAndroid Build Coastguard Worker   while (pExt->uniDrcGainExtType[k] != UNIDRCGAINEXT_TERM) {
458*e5436536SAndroid Build Coastguard Worker     if (k >= (8 - 1)) return DE_MEMORY_ERROR;
459*e5436536SAndroid Build Coastguard Worker     bitSizeLen = FDKreadBits(hBs, 3);
460*e5436536SAndroid Build Coastguard Worker     extSizeBits = bitSizeLen + 4;
461*e5436536SAndroid Build Coastguard Worker 
462*e5436536SAndroid Build Coastguard Worker     bitSize = FDKreadBits(hBs, extSizeBits);
463*e5436536SAndroid Build Coastguard Worker     pExt->extBitSize[k] = bitSize + 1;
464*e5436536SAndroid Build Coastguard Worker 
465*e5436536SAndroid Build Coastguard Worker     switch (pExt->uniDrcGainExtType[k]) {
466*e5436536SAndroid Build Coastguard Worker       /* add future extensions here */
467*e5436536SAndroid Build Coastguard Worker       default:
468*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, pExt->extBitSize[k]);
469*e5436536SAndroid Build Coastguard Worker         break;
470*e5436536SAndroid Build Coastguard Worker     }
471*e5436536SAndroid Build Coastguard Worker     k++;
472*e5436536SAndroid Build Coastguard Worker     pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4);
473*e5436536SAndroid Build Coastguard Worker   }
474*e5436536SAndroid Build Coastguard Worker 
475*e5436536SAndroid Build Coastguard Worker   return err;
476*e5436536SAndroid Build Coastguard Worker }
477*e5436536SAndroid Build Coastguard Worker 
478*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig,const int frameSize,const int deltaTminDefault,HANDLE_UNI_DRC_GAIN hUniDrcGain)479*e5436536SAndroid Build Coastguard Worker drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs,
480*e5436536SAndroid Build Coastguard Worker                       HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize,
481*e5436536SAndroid Build Coastguard Worker                       const int deltaTminDefault,
482*e5436536SAndroid Build Coastguard Worker                       HANDLE_UNI_DRC_GAIN hUniDrcGain) {
483*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
484*e5436536SAndroid Build Coastguard Worker   int seq, gainSequenceCount;
485*e5436536SAndroid Build Coastguard Worker   DRC_COEFFICIENTS_UNI_DRC* pCoef =
486*e5436536SAndroid Build Coastguard Worker       selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED);
487*e5436536SAndroid Build Coastguard Worker   if (hUniDrcGain == NULL) return DE_NOT_OK;
488*e5436536SAndroid Build Coastguard Worker   hUniDrcGain->status = 0;
489*e5436536SAndroid Build Coastguard Worker   if (pCoef) {
490*e5436536SAndroid Build Coastguard Worker     gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12);
491*e5436536SAndroid Build Coastguard Worker   } else {
492*e5436536SAndroid Build Coastguard Worker     gainSequenceCount = 0;
493*e5436536SAndroid Build Coastguard Worker   }
494*e5436536SAndroid Build Coastguard Worker 
495*e5436536SAndroid Build Coastguard Worker   for (seq = 0; seq < gainSequenceCount; seq++) {
496*e5436536SAndroid Build Coastguard Worker     UCHAR index = pCoef->gainSetIndexForGainSequence[seq];
497*e5436536SAndroid Build Coastguard Worker     GAIN_SET* gainSet;
498*e5436536SAndroid Build Coastguard Worker     int timeDeltaMin;
499*e5436536SAndroid Build Coastguard Worker     UCHAR tmpNNodes = 0;
500*e5436536SAndroid Build Coastguard Worker     GAIN_NODE tmpNodes[16];
501*e5436536SAndroid Build Coastguard Worker 
502*e5436536SAndroid Build Coastguard Worker     if ((index >= pCoef->gainSetCount) || (index >= 12)) return DE_NOT_OK;
503*e5436536SAndroid Build Coastguard Worker     gainSet = &(pCoef->gainSet[index]);
504*e5436536SAndroid Build Coastguard Worker 
505*e5436536SAndroid Build Coastguard Worker     timeDeltaMin = _getTimeDeltaMin(gainSet, deltaTminDefault);
506*e5436536SAndroid Build Coastguard Worker 
507*e5436536SAndroid Build Coastguard Worker     _readDrcGainSequence(hBs, gainSet, frameSize, timeDeltaMin, &tmpNNodes,
508*e5436536SAndroid Build Coastguard Worker                          tmpNodes);
509*e5436536SAndroid Build Coastguard Worker 
510*e5436536SAndroid Build Coastguard Worker     hUniDrcGain->nNodes[seq] = tmpNNodes;
511*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(hUniDrcGain->gainNode[seq], tmpNodes,
512*e5436536SAndroid Build Coastguard Worker               fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE));
513*e5436536SAndroid Build Coastguard Worker   }
514*e5436536SAndroid Build Coastguard Worker 
515*e5436536SAndroid Build Coastguard Worker   if (pCoef && (gainSequenceCount ==
516*e5436536SAndroid Build Coastguard Worker                 pCoef->gainSequenceCount)) { /* all sequences have been read */
517*e5436536SAndroid Build Coastguard Worker     hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
518*e5436536SAndroid Build Coastguard Worker     if (hUniDrcGain->uniDrcGainExtPresent == 1) {
519*e5436536SAndroid Build Coastguard Worker       err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
520*e5436536SAndroid Build Coastguard Worker       if (err) return err;
521*e5436536SAndroid Build Coastguard Worker     }
522*e5436536SAndroid Build Coastguard Worker   }
523*e5436536SAndroid Build Coastguard Worker 
524*e5436536SAndroid Build Coastguard Worker   if (err == DE_OK && gainSequenceCount > 0) {
525*e5436536SAndroid Build Coastguard Worker     hUniDrcGain->status = 1;
526*e5436536SAndroid Build Coastguard Worker   }
527*e5436536SAndroid Build Coastguard Worker   return err;
528*e5436536SAndroid Build Coastguard Worker }
529*e5436536SAndroid Build Coastguard Worker 
530*e5436536SAndroid Build Coastguard Worker /****************/
531*e5436536SAndroid Build Coastguard Worker /* uniDrcConfig */
532*e5436536SAndroid Build Coastguard Worker /****************/
533*e5436536SAndroid Build Coastguard Worker 
_decodeDuckingModification(HANDLE_FDK_BITSTREAM hBs,DUCKING_MODIFICATION * pDMod,int isBox)534*e5436536SAndroid Build Coastguard Worker static void _decodeDuckingModification(HANDLE_FDK_BITSTREAM hBs,
535*e5436536SAndroid Build Coastguard Worker                                        DUCKING_MODIFICATION* pDMod, int isBox) {
536*e5436536SAndroid Build Coastguard Worker   int bsDuckingScaling, sigma, mu;
537*e5436536SAndroid Build Coastguard Worker 
538*e5436536SAndroid Build Coastguard Worker   if (isBox) FDKpushFor(hBs, 7); /* reserved */
539*e5436536SAndroid Build Coastguard Worker   pDMod->duckingScalingPresent = FDKreadBits(hBs, 1);
540*e5436536SAndroid Build Coastguard Worker 
541*e5436536SAndroid Build Coastguard Worker   if (pDMod->duckingScalingPresent) {
542*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 4); /* reserved */
543*e5436536SAndroid Build Coastguard Worker     bsDuckingScaling = FDKreadBits(hBs, 4);
544*e5436536SAndroid Build Coastguard Worker     sigma = bsDuckingScaling >> 3;
545*e5436536SAndroid Build Coastguard Worker     mu = bsDuckingScaling & 0x7;
546*e5436536SAndroid Build Coastguard Worker 
547*e5436536SAndroid Build Coastguard Worker     if (sigma) {
548*e5436536SAndroid Build Coastguard Worker       pDMod->duckingScaling = (FIXP_SGL)(
549*e5436536SAndroid Build Coastguard Worker           (7 - mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 - 0.125 * (1 + mu); */
550*e5436536SAndroid Build Coastguard Worker     } else {
551*e5436536SAndroid Build Coastguard Worker       pDMod->duckingScaling = (FIXP_SGL)(
552*e5436536SAndroid Build Coastguard Worker           (9 + mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 + 0.125 * (1 + mu); */
553*e5436536SAndroid Build Coastguard Worker     }
554*e5436536SAndroid Build Coastguard Worker   } else {
555*e5436536SAndroid Build Coastguard Worker     pDMod->duckingScaling = (FIXP_SGL)(1 << (FRACT_BITS - 1 - 2)); /* 1.0 */
556*e5436536SAndroid Build Coastguard Worker   }
557*e5436536SAndroid Build Coastguard Worker }
558*e5436536SAndroid Build Coastguard Worker 
_decodeGainModification(HANDLE_FDK_BITSTREAM hBs,const int version,int bandCount,GAIN_MODIFICATION * pGMod,int isBox)559*e5436536SAndroid Build Coastguard Worker static void _decodeGainModification(HANDLE_FDK_BITSTREAM hBs, const int version,
560*e5436536SAndroid Build Coastguard Worker                                     int bandCount, GAIN_MODIFICATION* pGMod,
561*e5436536SAndroid Build Coastguard Worker                                     int isBox) {
562*e5436536SAndroid Build Coastguard Worker   int sign, bsGainOffset, bsAttenuationScaling, bsAmplificationScaling;
563*e5436536SAndroid Build Coastguard Worker 
564*e5436536SAndroid Build Coastguard Worker   if (version > 0) {
565*e5436536SAndroid Build Coastguard Worker     int b, shapeFilterPresent;
566*e5436536SAndroid Build Coastguard Worker 
567*e5436536SAndroid Build Coastguard Worker     if (isBox) {
568*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 4); /* reserved */
569*e5436536SAndroid Build Coastguard Worker       bandCount = FDKreadBits(hBs, 4);
570*e5436536SAndroid Build Coastguard Worker     }
571*e5436536SAndroid Build Coastguard Worker 
572*e5436536SAndroid Build Coastguard Worker     for (b = 0; b < bandCount; b++) {
573*e5436536SAndroid Build Coastguard Worker       if (isBox) {
574*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 4); /* reserved */
575*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1);
576*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1);
577*e5436536SAndroid Build Coastguard Worker         pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1);
578*e5436536SAndroid Build Coastguard Worker         pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1);
579*e5436536SAndroid Build Coastguard Worker       }
580*e5436536SAndroid Build Coastguard Worker 
581*e5436536SAndroid Build Coastguard Worker       if (!isBox)
582*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1);
583*e5436536SAndroid Build Coastguard Worker       if (pGMod[b].targetCharacteristicLeftPresent) {
584*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 4); /* reserved */
585*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicLeftIndex = FDKreadBits(hBs, 4);
586*e5436536SAndroid Build Coastguard Worker       }
587*e5436536SAndroid Build Coastguard Worker       if (!isBox)
588*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1);
589*e5436536SAndroid Build Coastguard Worker       if (pGMod[b].targetCharacteristicRightPresent) {
590*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 4); /* reserved */
591*e5436536SAndroid Build Coastguard Worker         pGMod[b].targetCharacteristicRightIndex = FDKreadBits(hBs, 4);
592*e5436536SAndroid Build Coastguard Worker       }
593*e5436536SAndroid Build Coastguard Worker       if (!isBox) pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1);
594*e5436536SAndroid Build Coastguard Worker       if (pGMod[b].gainScalingPresent) {
595*e5436536SAndroid Build Coastguard Worker         bsAttenuationScaling = FDKreadBits(hBs, 4);
596*e5436536SAndroid Build Coastguard Worker         pGMod[b].attenuationScaling = (FIXP_SGL)(
597*e5436536SAndroid Build Coastguard Worker             bsAttenuationScaling
598*e5436536SAndroid Build Coastguard Worker             << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */
599*e5436536SAndroid Build Coastguard Worker         bsAmplificationScaling = FDKreadBits(hBs, 4);
600*e5436536SAndroid Build Coastguard Worker         pGMod[b].amplificationScaling = (FIXP_SGL)(
601*e5436536SAndroid Build Coastguard Worker             bsAmplificationScaling
602*e5436536SAndroid Build Coastguard Worker             << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */
603*e5436536SAndroid Build Coastguard Worker       }
604*e5436536SAndroid Build Coastguard Worker       if (!isBox) pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1);
605*e5436536SAndroid Build Coastguard Worker       if (pGMod[b].gainOffsetPresent) {
606*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 2); /* reserved */
607*e5436536SAndroid Build Coastguard Worker         sign = FDKreadBits(hBs, 1);
608*e5436536SAndroid Build Coastguard Worker         bsGainOffset = FDKreadBits(hBs, 5);
609*e5436536SAndroid Build Coastguard Worker         pGMod[b].gainOffset = (FIXP_SGL)(
610*e5436536SAndroid Build Coastguard Worker             (1 + bsGainOffset)
611*e5436536SAndroid Build Coastguard Worker             << (FRACT_BITS - 1 - 2 - 4)); /* (1+bsGainOffset) * 0.25; */
612*e5436536SAndroid Build Coastguard Worker         if (sign) {
613*e5436536SAndroid Build Coastguard Worker           pGMod[b].gainOffset = -pGMod[b].gainOffset;
614*e5436536SAndroid Build Coastguard Worker         }
615*e5436536SAndroid Build Coastguard Worker       }
616*e5436536SAndroid Build Coastguard Worker     }
617*e5436536SAndroid Build Coastguard Worker     if (bandCount == 1) {
618*e5436536SAndroid Build Coastguard Worker       shapeFilterPresent = FDKreadBits(hBs, 1);
619*e5436536SAndroid Build Coastguard Worker       if (shapeFilterPresent) {
620*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 3); /* reserved */
621*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 4);            /* pGMod->shapeFilterIndex */
622*e5436536SAndroid Build Coastguard Worker       } else {
623*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 7); /* reserved */
624*e5436536SAndroid Build Coastguard Worker       }
625*e5436536SAndroid Build Coastguard Worker     }
626*e5436536SAndroid Build Coastguard Worker   } else {
627*e5436536SAndroid Build Coastguard Worker     int b, gainScalingPresent, gainOffsetPresent;
628*e5436536SAndroid Build Coastguard Worker     FIXP_SGL attenuationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)),
629*e5436536SAndroid Build Coastguard Worker              amplificationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)),
630*e5436536SAndroid Build Coastguard Worker              gainOffset = (FIXP_SGL)0;
631*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 7); /* reserved */
632*e5436536SAndroid Build Coastguard Worker     gainScalingPresent = FDKreadBits(hBs, 1);
633*e5436536SAndroid Build Coastguard Worker     if (gainScalingPresent) {
634*e5436536SAndroid Build Coastguard Worker       bsAttenuationScaling = FDKreadBits(hBs, 4);
635*e5436536SAndroid Build Coastguard Worker       attenuationScaling = (FIXP_SGL)(
636*e5436536SAndroid Build Coastguard Worker           bsAttenuationScaling
637*e5436536SAndroid Build Coastguard Worker           << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */
638*e5436536SAndroid Build Coastguard Worker       bsAmplificationScaling = FDKreadBits(hBs, 4);
639*e5436536SAndroid Build Coastguard Worker       amplificationScaling = (FIXP_SGL)(
640*e5436536SAndroid Build Coastguard Worker           bsAmplificationScaling
641*e5436536SAndroid Build Coastguard Worker           << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */
642*e5436536SAndroid Build Coastguard Worker     }
643*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 7); /* reserved */
644*e5436536SAndroid Build Coastguard Worker     gainOffsetPresent = FDKreadBits(hBs, 1);
645*e5436536SAndroid Build Coastguard Worker     if (gainOffsetPresent) {
646*e5436536SAndroid Build Coastguard Worker       if (isBox) FDKpushFor(hBs, 2); /* reserved */
647*e5436536SAndroid Build Coastguard Worker       sign = FDKreadBits(hBs, 1);
648*e5436536SAndroid Build Coastguard Worker       bsGainOffset = FDKreadBits(hBs, 5);
649*e5436536SAndroid Build Coastguard Worker       gainOffset =
650*e5436536SAndroid Build Coastguard Worker           (FIXP_SGL)((1 + bsGainOffset) << (FRACT_BITS - 1 - 2 -
651*e5436536SAndroid Build Coastguard Worker                                             4)); /* (1+bsGainOffset) * 0.25; */
652*e5436536SAndroid Build Coastguard Worker       if (sign) {
653*e5436536SAndroid Build Coastguard Worker         gainOffset = -gainOffset;
654*e5436536SAndroid Build Coastguard Worker       }
655*e5436536SAndroid Build Coastguard Worker     }
656*e5436536SAndroid Build Coastguard Worker     for (b = 0; b < 4; b++) {
657*e5436536SAndroid Build Coastguard Worker       pGMod[b].targetCharacteristicLeftPresent = 0;
658*e5436536SAndroid Build Coastguard Worker       pGMod[b].targetCharacteristicRightPresent = 0;
659*e5436536SAndroid Build Coastguard Worker       pGMod[b].gainScalingPresent = gainScalingPresent;
660*e5436536SAndroid Build Coastguard Worker       pGMod[b].attenuationScaling = attenuationScaling;
661*e5436536SAndroid Build Coastguard Worker       pGMod[b].amplificationScaling = amplificationScaling;
662*e5436536SAndroid Build Coastguard Worker       pGMod[b].gainOffsetPresent = gainOffsetPresent;
663*e5436536SAndroid Build Coastguard Worker       pGMod[b].gainOffset = gainOffset;
664*e5436536SAndroid Build Coastguard Worker     }
665*e5436536SAndroid Build Coastguard Worker   }
666*e5436536SAndroid Build Coastguard Worker }
667*e5436536SAndroid Build Coastguard Worker 
_readDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs,const int version,DRC_CHARACTERISTIC * pDChar,int isBox)668*e5436536SAndroid Build Coastguard Worker static void _readDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, const int version,
669*e5436536SAndroid Build Coastguard Worker                                    DRC_CHARACTERISTIC* pDChar, int isBox) {
670*e5436536SAndroid Build Coastguard Worker   if (version == 0) {
671*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 1); /* reserved */
672*e5436536SAndroid Build Coastguard Worker     pDChar->cicpIndex = FDKreadBits(hBs, 7);
673*e5436536SAndroid Build Coastguard Worker     if (pDChar->cicpIndex > 0) {
674*e5436536SAndroid Build Coastguard Worker       pDChar->present = 1;
675*e5436536SAndroid Build Coastguard Worker       pDChar->isCICP = 1;
676*e5436536SAndroid Build Coastguard Worker     } else {
677*e5436536SAndroid Build Coastguard Worker       pDChar->present = 0;
678*e5436536SAndroid Build Coastguard Worker     }
679*e5436536SAndroid Build Coastguard Worker   } else {
680*e5436536SAndroid Build Coastguard Worker     pDChar->present = FDKreadBits(hBs, 1);
681*e5436536SAndroid Build Coastguard Worker     if (isBox) pDChar->isCICP = FDKreadBits(hBs, 1);
682*e5436536SAndroid Build Coastguard Worker     if (pDChar->present) {
683*e5436536SAndroid Build Coastguard Worker       if (!isBox) pDChar->isCICP = FDKreadBits(hBs, 1);
684*e5436536SAndroid Build Coastguard Worker       if (pDChar->isCICP) {
685*e5436536SAndroid Build Coastguard Worker         if (isBox) FDKpushFor(hBs, 1); /* reserved */
686*e5436536SAndroid Build Coastguard Worker         pDChar->cicpIndex = FDKreadBits(hBs, 7);
687*e5436536SAndroid Build Coastguard Worker       } else {
688*e5436536SAndroid Build Coastguard Worker         pDChar->custom.left = FDKreadBits(hBs, 4);
689*e5436536SAndroid Build Coastguard Worker         pDChar->custom.right = FDKreadBits(hBs, 4);
690*e5436536SAndroid Build Coastguard Worker       }
691*e5436536SAndroid Build Coastguard Worker     }
692*e5436536SAndroid Build Coastguard Worker   }
693*e5436536SAndroid Build Coastguard Worker }
694*e5436536SAndroid Build Coastguard Worker 
_readBandBorder(HANDLE_FDK_BITSTREAM hBs,BAND_BORDER * pBBord,int drcBandType,int isBox)695*e5436536SAndroid Build Coastguard Worker static void _readBandBorder(HANDLE_FDK_BITSTREAM hBs, BAND_BORDER* pBBord,
696*e5436536SAndroid Build Coastguard Worker                             int drcBandType, int isBox) {
697*e5436536SAndroid Build Coastguard Worker   if (drcBandType) {
698*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 4); /* reserved */
699*e5436536SAndroid Build Coastguard Worker     pBBord->crossoverFreqIndex = FDKreadBits(hBs, 4);
700*e5436536SAndroid Build Coastguard Worker   } else {
701*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 6); /* reserved */
702*e5436536SAndroid Build Coastguard Worker     pBBord->startSubBandIndex = FDKreadBits(hBs, 10);
703*e5436536SAndroid Build Coastguard Worker   }
704*e5436536SAndroid Build Coastguard Worker }
705*e5436536SAndroid Build Coastguard Worker 
_readGainSet(HANDLE_FDK_BITSTREAM hBs,const int version,int * gainSequenceIndex,GAIN_SET * pGSet,int isBox)706*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readGainSet(HANDLE_FDK_BITSTREAM hBs, const int version,
707*e5436536SAndroid Build Coastguard Worker                               int* gainSequenceIndex, GAIN_SET* pGSet,
708*e5436536SAndroid Build Coastguard Worker                               int isBox) {
709*e5436536SAndroid Build Coastguard Worker   if (isBox) FDKpushFor(hBs, 2); /* reserved */
710*e5436536SAndroid Build Coastguard Worker   pGSet->gainCodingProfile = FDKreadBits(hBs, 2);
711*e5436536SAndroid Build Coastguard Worker   pGSet->gainInterpolationType = FDKreadBits(hBs, 1);
712*e5436536SAndroid Build Coastguard Worker   pGSet->fullFrame = FDKreadBits(hBs, 1);
713*e5436536SAndroid Build Coastguard Worker   pGSet->timeAlignment = FDKreadBits(hBs, 1);
714*e5436536SAndroid Build Coastguard Worker   pGSet->timeDeltaMinPresent = FDKreadBits(hBs, 1);
715*e5436536SAndroid Build Coastguard Worker 
716*e5436536SAndroid Build Coastguard Worker   if (pGSet->timeDeltaMinPresent) {
717*e5436536SAndroid Build Coastguard Worker     int bsTimeDeltaMin;
718*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 5); /* reserved */
719*e5436536SAndroid Build Coastguard Worker     bsTimeDeltaMin = FDKreadBits(hBs, 11);
720*e5436536SAndroid Build Coastguard Worker     pGSet->timeDeltaMin = bsTimeDeltaMin + 1;
721*e5436536SAndroid Build Coastguard Worker   }
722*e5436536SAndroid Build Coastguard Worker 
723*e5436536SAndroid Build Coastguard Worker   if (pGSet->gainCodingProfile != GCP_CONSTANT) {
724*e5436536SAndroid Build Coastguard Worker     int i;
725*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 3); /* reserved */
726*e5436536SAndroid Build Coastguard Worker     pGSet->bandCount = FDKreadBits(hBs, 4);
727*e5436536SAndroid Build Coastguard Worker     if (pGSet->bandCount > 4) return DE_MEMORY_ERROR;
728*e5436536SAndroid Build Coastguard Worker 
729*e5436536SAndroid Build Coastguard Worker     if ((pGSet->bandCount > 1) || isBox) {
730*e5436536SAndroid Build Coastguard Worker       pGSet->drcBandType = FDKreadBits(hBs, 1);
731*e5436536SAndroid Build Coastguard Worker     }
732*e5436536SAndroid Build Coastguard Worker 
733*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < pGSet->bandCount; i++) {
734*e5436536SAndroid Build Coastguard Worker       if (version == 0) {
735*e5436536SAndroid Build Coastguard Worker         *gainSequenceIndex = (*gainSequenceIndex) + 1;
736*e5436536SAndroid Build Coastguard Worker       } else {
737*e5436536SAndroid Build Coastguard Worker         int indexPresent;
738*e5436536SAndroid Build Coastguard Worker         indexPresent = (isBox) ? 1 : FDKreadBits(hBs, 1);
739*e5436536SAndroid Build Coastguard Worker         if (indexPresent) {
740*e5436536SAndroid Build Coastguard Worker           int bsIndex;
741*e5436536SAndroid Build Coastguard Worker           bsIndex = FDKreadBits(hBs, 6);
742*e5436536SAndroid Build Coastguard Worker           *gainSequenceIndex = bsIndex;
743*e5436536SAndroid Build Coastguard Worker         } else {
744*e5436536SAndroid Build Coastguard Worker           *gainSequenceIndex = (*gainSequenceIndex) + 1;
745*e5436536SAndroid Build Coastguard Worker         }
746*e5436536SAndroid Build Coastguard Worker       }
747*e5436536SAndroid Build Coastguard Worker       pGSet->gainSequenceIndex[i] = *gainSequenceIndex;
748*e5436536SAndroid Build Coastguard Worker       _readDrcCharacteristic(hBs, version, &(pGSet->drcCharacteristic[i]),
749*e5436536SAndroid Build Coastguard Worker                              isBox);
750*e5436536SAndroid Build Coastguard Worker     }
751*e5436536SAndroid Build Coastguard Worker     for (i = 1; i < pGSet->bandCount; i++) {
752*e5436536SAndroid Build Coastguard Worker       _readBandBorder(hBs, &(pGSet->bandBorder[i]), pGSet->drcBandType, isBox);
753*e5436536SAndroid Build Coastguard Worker     }
754*e5436536SAndroid Build Coastguard Worker   } else {
755*e5436536SAndroid Build Coastguard Worker     pGSet->bandCount = 1;
756*e5436536SAndroid Build Coastguard Worker     *gainSequenceIndex = (*gainSequenceIndex) + 1;
757*e5436536SAndroid Build Coastguard Worker     pGSet->gainSequenceIndex[0] = *gainSequenceIndex;
758*e5436536SAndroid Build Coastguard Worker   }
759*e5436536SAndroid Build Coastguard Worker 
760*e5436536SAndroid Build Coastguard Worker   return DE_OK;
761*e5436536SAndroid Build Coastguard Worker }
762*e5436536SAndroid Build Coastguard Worker 
_readCustomDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs,const CHARACTERISTIC_SIDE side,UCHAR * pCharacteristicFormat,CUSTOM_DRC_CHAR * pCChar,int isBox)763*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readCustomDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs,
764*e5436536SAndroid Build Coastguard Worker                                               const CHARACTERISTIC_SIDE side,
765*e5436536SAndroid Build Coastguard Worker                                               UCHAR* pCharacteristicFormat,
766*e5436536SAndroid Build Coastguard Worker                                               CUSTOM_DRC_CHAR* pCChar,
767*e5436536SAndroid Build Coastguard Worker                                               int isBox) {
768*e5436536SAndroid Build Coastguard Worker   if (isBox) FDKpushFor(hBs, 7); /* reserved */
769*e5436536SAndroid Build Coastguard Worker   *pCharacteristicFormat = FDKreadBits(hBs, 1);
770*e5436536SAndroid Build Coastguard Worker   if (*pCharacteristicFormat == CF_SIGMOID) {
771*e5436536SAndroid Build Coastguard Worker     int bsGain, bsIoRatio, bsExp;
772*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 1); /* reserved */
773*e5436536SAndroid Build Coastguard Worker     bsGain = FDKreadBits(hBs, 6);
774*e5436536SAndroid Build Coastguard Worker     if (side == CS_LEFT) {
775*e5436536SAndroid Build Coastguard Worker       pCChar->sigmoid.gain = (FIXP_SGL)(bsGain << (FRACT_BITS - 1 - 6));
776*e5436536SAndroid Build Coastguard Worker     } else {
777*e5436536SAndroid Build Coastguard Worker       pCChar->sigmoid.gain = (FIXP_SGL)(-bsGain << (FRACT_BITS - 1 - 6));
778*e5436536SAndroid Build Coastguard Worker     }
779*e5436536SAndroid Build Coastguard Worker     bsIoRatio = FDKreadBits(hBs, 4);
780*e5436536SAndroid Build Coastguard Worker     /* pCChar->sigmoid.ioRatio = 0.05 + 0.15 * bsIoRatio; */
781*e5436536SAndroid Build Coastguard Worker     pCChar->sigmoid.ioRatio =
782*e5436536SAndroid Build Coastguard Worker         FL2FXCONST_SGL(0.05f / (float)(1 << 2)) +
783*e5436536SAndroid Build Coastguard Worker         (FIXP_SGL)((((3 * bsIoRatio) << (FRACT_BITS - 1)) / 5) >> 4);
784*e5436536SAndroid Build Coastguard Worker     bsExp = FDKreadBits(hBs, 4);
785*e5436536SAndroid Build Coastguard Worker     if (bsExp < 15) {
786*e5436536SAndroid Build Coastguard Worker       pCChar->sigmoid.exp = (FIXP_SGL)((1 + 2 * bsExp) << (FRACT_BITS - 1 - 5));
787*e5436536SAndroid Build Coastguard Worker     } else {
788*e5436536SAndroid Build Coastguard Worker       pCChar->sigmoid.exp = (FIXP_SGL)MAXVAL_SGL; /* represents infinity */
789*e5436536SAndroid Build Coastguard Worker     }
790*e5436536SAndroid Build Coastguard Worker     pCChar->sigmoid.flipSign = FDKreadBits(hBs, 1);
791*e5436536SAndroid Build Coastguard Worker   } else { /* CF_NODES */
792*e5436536SAndroid Build Coastguard Worker     int i, bsCharacteristicNodeCount, bsNodeLevelDelta, bsNodeGain;
793*e5436536SAndroid Build Coastguard Worker     if (isBox) FDKpushFor(hBs, 6); /* reserved */
794*e5436536SAndroid Build Coastguard Worker     bsCharacteristicNodeCount = FDKreadBits(hBs, 2);
795*e5436536SAndroid Build Coastguard Worker     pCChar->nodes.characteristicNodeCount = bsCharacteristicNodeCount + 1;
796*e5436536SAndroid Build Coastguard Worker     if (pCChar->nodes.characteristicNodeCount > 4) return DE_MEMORY_ERROR;
797*e5436536SAndroid Build Coastguard Worker     pCChar->nodes.nodeLevel[0] = DRC_INPUT_LOUDNESS_TARGET_SGL;
798*e5436536SAndroid Build Coastguard Worker     pCChar->nodes.nodeGain[0] = (FIXP_SGL)0;
799*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < pCChar->nodes.characteristicNodeCount; i++) {
800*e5436536SAndroid Build Coastguard Worker       if (isBox) FDKpushFor(hBs, 3); /* reserved */
801*e5436536SAndroid Build Coastguard Worker       bsNodeLevelDelta = FDKreadBits(hBs, 5);
802*e5436536SAndroid Build Coastguard Worker       if (side == CS_LEFT) {
803*e5436536SAndroid Build Coastguard Worker         pCChar->nodes.nodeLevel[i + 1] =
804*e5436536SAndroid Build Coastguard Worker             pCChar->nodes.nodeLevel[i] -
805*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7));
806*e5436536SAndroid Build Coastguard Worker       } else {
807*e5436536SAndroid Build Coastguard Worker         pCChar->nodes.nodeLevel[i + 1] =
808*e5436536SAndroid Build Coastguard Worker             pCChar->nodes.nodeLevel[i] +
809*e5436536SAndroid Build Coastguard Worker             (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7));
810*e5436536SAndroid Build Coastguard Worker       }
811*e5436536SAndroid Build Coastguard Worker       bsNodeGain = FDKreadBits(hBs, 8);
812*e5436536SAndroid Build Coastguard Worker       pCChar->nodes.nodeGain[i + 1] = (FIXP_SGL)(
813*e5436536SAndroid Build Coastguard Worker           (bsNodeGain - 128)
814*e5436536SAndroid Build Coastguard Worker           << (FRACT_BITS - 1 - 1 - 7)); /* 0.5f * bsNodeGain - 64.0f; */
815*e5436536SAndroid Build Coastguard Worker     }
816*e5436536SAndroid Build Coastguard Worker   }
817*e5436536SAndroid Build Coastguard Worker   return DE_OK;
818*e5436536SAndroid Build Coastguard Worker }
819*e5436536SAndroid Build Coastguard Worker 
_skipLoudEqInstructions(HANDLE_FDK_BITSTREAM hBs)820*e5436536SAndroid Build Coastguard Worker static void _skipLoudEqInstructions(HANDLE_FDK_BITSTREAM hBs) {
821*e5436536SAndroid Build Coastguard Worker   int i;
822*e5436536SAndroid Build Coastguard Worker   int downmixIdPresent, additionalDownmixIdPresent,
823*e5436536SAndroid Build Coastguard Worker       additionalDownmixIdCount = 0;
824*e5436536SAndroid Build Coastguard Worker   int drcSetIdPresent, additionalDrcSetIdPresent, additionalDrcSetIdCount = 0;
825*e5436536SAndroid Build Coastguard Worker   int eqSetIdPresent, additionalEqSetIdPresent, additionalEqSetIdCount = 0;
826*e5436536SAndroid Build Coastguard Worker   int loudEqGainSequenceCount, drcCharacteristicFormatIsCICP;
827*e5436536SAndroid Build Coastguard Worker 
828*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4); /* loudEqSetId */
829*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4); /* drcLocation */
830*e5436536SAndroid Build Coastguard Worker   downmixIdPresent = FDKreadBits(hBs, 1);
831*e5436536SAndroid Build Coastguard Worker   if (downmixIdPresent) {
832*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 7); /* downmixId */
833*e5436536SAndroid Build Coastguard Worker     additionalDownmixIdPresent = FDKreadBits(hBs, 1);
834*e5436536SAndroid Build Coastguard Worker     if (additionalDownmixIdPresent) {
835*e5436536SAndroid Build Coastguard Worker       additionalDownmixIdCount = FDKreadBits(hBs, 7);
836*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < additionalDownmixIdCount; i++) {
837*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 7); /* additionalDownmixId */
838*e5436536SAndroid Build Coastguard Worker       }
839*e5436536SAndroid Build Coastguard Worker     }
840*e5436536SAndroid Build Coastguard Worker   }
841*e5436536SAndroid Build Coastguard Worker 
842*e5436536SAndroid Build Coastguard Worker   drcSetIdPresent = FDKreadBits(hBs, 1);
843*e5436536SAndroid Build Coastguard Worker   if (drcSetIdPresent) {
844*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* drcSetId */
845*e5436536SAndroid Build Coastguard Worker     additionalDrcSetIdPresent = FDKreadBits(hBs, 1);
846*e5436536SAndroid Build Coastguard Worker     if (additionalDrcSetIdPresent) {
847*e5436536SAndroid Build Coastguard Worker       additionalDrcSetIdCount = FDKreadBits(hBs, 6);
848*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < additionalDrcSetIdCount; i++) {
849*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 6); /* additionalDrcSetId; */
850*e5436536SAndroid Build Coastguard Worker       }
851*e5436536SAndroid Build Coastguard Worker     }
852*e5436536SAndroid Build Coastguard Worker   }
853*e5436536SAndroid Build Coastguard Worker 
854*e5436536SAndroid Build Coastguard Worker   eqSetIdPresent = FDKreadBits(hBs, 1);
855*e5436536SAndroid Build Coastguard Worker   if (eqSetIdPresent) {
856*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* eqSetId */
857*e5436536SAndroid Build Coastguard Worker     additionalEqSetIdPresent = FDKreadBits(hBs, 1);
858*e5436536SAndroid Build Coastguard Worker     if (additionalEqSetIdPresent) {
859*e5436536SAndroid Build Coastguard Worker       additionalEqSetIdCount = FDKreadBits(hBs, 6);
860*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < additionalEqSetIdCount; i++) {
861*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 6); /* additionalEqSetId; */
862*e5436536SAndroid Build Coastguard Worker       }
863*e5436536SAndroid Build Coastguard Worker     }
864*e5436536SAndroid Build Coastguard Worker   }
865*e5436536SAndroid Build Coastguard Worker 
866*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 1); /* loudnessAfterDrc */
867*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 1); /* loudnessAfterEq */
868*e5436536SAndroid Build Coastguard Worker   loudEqGainSequenceCount = FDKreadBits(hBs, 6);
869*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < loudEqGainSequenceCount; i++) {
870*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* gainSequenceIndex */
871*e5436536SAndroid Build Coastguard Worker     drcCharacteristicFormatIsCICP = FDKreadBits(hBs, 1);
872*e5436536SAndroid Build Coastguard Worker     if (drcCharacteristicFormatIsCICP) {
873*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 7); /* drcCharacteristic */
874*e5436536SAndroid Build Coastguard Worker     } else {
875*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 4); /* drcCharacteristicLeftIndex */
876*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 4); /* drcCharacteristicRightIndex */
877*e5436536SAndroid Build Coastguard Worker     }
878*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* frequencyRangeIndex */
879*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 3); /* bsLoudEqScaling */
880*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 5); /* bsLoudEqOffset */
881*e5436536SAndroid Build Coastguard Worker   }
882*e5436536SAndroid Build Coastguard Worker }
883*e5436536SAndroid Build Coastguard Worker 
_skipEqSubbandGainSpline(HANDLE_FDK_BITSTREAM hBs)884*e5436536SAndroid Build Coastguard Worker static void _skipEqSubbandGainSpline(HANDLE_FDK_BITSTREAM hBs) {
885*e5436536SAndroid Build Coastguard Worker   int nEqNodes, k, bits;
886*e5436536SAndroid Build Coastguard Worker   nEqNodes = FDKreadBits(hBs, 5);
887*e5436536SAndroid Build Coastguard Worker   nEqNodes += 2;
888*e5436536SAndroid Build Coastguard Worker   for (k = 0; k < nEqNodes; k++) {
889*e5436536SAndroid Build Coastguard Worker     bits = FDKreadBits(hBs, 1);
890*e5436536SAndroid Build Coastguard Worker     if (!bits) {
891*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 4);
892*e5436536SAndroid Build Coastguard Worker     }
893*e5436536SAndroid Build Coastguard Worker   }
894*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4 * (nEqNodes - 1));
895*e5436536SAndroid Build Coastguard Worker   bits = FDKreadBits(hBs, 2);
896*e5436536SAndroid Build Coastguard Worker   switch (bits) {
897*e5436536SAndroid Build Coastguard Worker     case 0:
898*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 5);
899*e5436536SAndroid Build Coastguard Worker       break;
900*e5436536SAndroid Build Coastguard Worker     case 1:
901*e5436536SAndroid Build Coastguard Worker     case 2:
902*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 4);
903*e5436536SAndroid Build Coastguard Worker       break;
904*e5436536SAndroid Build Coastguard Worker     case 3:
905*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 3);
906*e5436536SAndroid Build Coastguard Worker       break;
907*e5436536SAndroid Build Coastguard Worker   }
908*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 5 * (nEqNodes - 1));
909*e5436536SAndroid Build Coastguard Worker }
910*e5436536SAndroid Build Coastguard Worker 
_skipEqCoefficients(HANDLE_FDK_BITSTREAM hBs)911*e5436536SAndroid Build Coastguard Worker static void _skipEqCoefficients(HANDLE_FDK_BITSTREAM hBs) {
912*e5436536SAndroid Build Coastguard Worker   int j, k;
913*e5436536SAndroid Build Coastguard Worker   int eqDelayMaxPresent;
914*e5436536SAndroid Build Coastguard Worker   int uniqueFilterBlockCount, filterElementCount, filterElementGainPresent;
915*e5436536SAndroid Build Coastguard Worker   int uniqueTdFilterElementCount, eqFilterFormat, bsRealZeroRadiusOneCount,
916*e5436536SAndroid Build Coastguard Worker       realZeroCount, genericZeroCount, realPoleCount, complexPoleCount,
917*e5436536SAndroid Build Coastguard Worker       firFilterOrder;
918*e5436536SAndroid Build Coastguard Worker   int uniqueEqSubbandGainsCount, eqSubbandGainRepresentation,
919*e5436536SAndroid Build Coastguard Worker       eqSubbandGainCount;
920*e5436536SAndroid Build Coastguard Worker   int eqSubbandGainFormat;
921*e5436536SAndroid Build Coastguard Worker 
922*e5436536SAndroid Build Coastguard Worker   eqDelayMaxPresent = FDKreadBits(hBs, 1);
923*e5436536SAndroid Build Coastguard Worker   if (eqDelayMaxPresent) {
924*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 8); /* bsEqDelayMax */
925*e5436536SAndroid Build Coastguard Worker   }
926*e5436536SAndroid Build Coastguard Worker 
927*e5436536SAndroid Build Coastguard Worker   uniqueFilterBlockCount = FDKreadBits(hBs, 6);
928*e5436536SAndroid Build Coastguard Worker   for (j = 0; j < uniqueFilterBlockCount; j++) {
929*e5436536SAndroid Build Coastguard Worker     filterElementCount = FDKreadBits(hBs, 6);
930*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < filterElementCount; k++) {
931*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 6); /* filterElementIndex */
932*e5436536SAndroid Build Coastguard Worker       filterElementGainPresent = FDKreadBits(hBs, 1);
933*e5436536SAndroid Build Coastguard Worker       if (filterElementGainPresent) {
934*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, 10); /* bsFilterElementGain */
935*e5436536SAndroid Build Coastguard Worker       }
936*e5436536SAndroid Build Coastguard Worker     }
937*e5436536SAndroid Build Coastguard Worker   }
938*e5436536SAndroid Build Coastguard Worker   uniqueTdFilterElementCount = FDKreadBits(hBs, 6);
939*e5436536SAndroid Build Coastguard Worker   for (j = 0; j < uniqueTdFilterElementCount; j++) {
940*e5436536SAndroid Build Coastguard Worker     eqFilterFormat = FDKreadBits(hBs, 1);
941*e5436536SAndroid Build Coastguard Worker     if (eqFilterFormat == 0) { /* pole/zero */
942*e5436536SAndroid Build Coastguard Worker       bsRealZeroRadiusOneCount = FDKreadBits(hBs, 3);
943*e5436536SAndroid Build Coastguard Worker       realZeroCount = FDKreadBits(hBs, 6);
944*e5436536SAndroid Build Coastguard Worker       genericZeroCount = FDKreadBits(hBs, 6);
945*e5436536SAndroid Build Coastguard Worker       realPoleCount = FDKreadBits(hBs, 4);
946*e5436536SAndroid Build Coastguard Worker       complexPoleCount = FDKreadBits(hBs, 4);
947*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 2 * bsRealZeroRadiusOneCount * 1);
948*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, realZeroCount * 8);
949*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, genericZeroCount * 14);
950*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, realPoleCount * 8);
951*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, complexPoleCount * 14);
952*e5436536SAndroid Build Coastguard Worker     } else { /* FIR coefficients */
953*e5436536SAndroid Build Coastguard Worker       firFilterOrder = FDKreadBits(hBs, 7);
954*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 1);
955*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, (firFilterOrder / 2 + 1) * 11);
956*e5436536SAndroid Build Coastguard Worker     }
957*e5436536SAndroid Build Coastguard Worker   }
958*e5436536SAndroid Build Coastguard Worker   uniqueEqSubbandGainsCount = FDKreadBits(hBs, 6);
959*e5436536SAndroid Build Coastguard Worker   if (uniqueEqSubbandGainsCount > 0) {
960*e5436536SAndroid Build Coastguard Worker     eqSubbandGainRepresentation = FDKreadBits(hBs, 1);
961*e5436536SAndroid Build Coastguard Worker     eqSubbandGainFormat = FDKreadBits(hBs, 4);
962*e5436536SAndroid Build Coastguard Worker     switch (eqSubbandGainFormat) {
963*e5436536SAndroid Build Coastguard Worker       case GF_QMF32:
964*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 32;
965*e5436536SAndroid Build Coastguard Worker         break;
966*e5436536SAndroid Build Coastguard Worker       case GF_QMFHYBRID39:
967*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 39;
968*e5436536SAndroid Build Coastguard Worker         break;
969*e5436536SAndroid Build Coastguard Worker       case GF_QMF64:
970*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 64;
971*e5436536SAndroid Build Coastguard Worker         break;
972*e5436536SAndroid Build Coastguard Worker       case GF_QMFHYBRID71:
973*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 71;
974*e5436536SAndroid Build Coastguard Worker         break;
975*e5436536SAndroid Build Coastguard Worker       case GF_QMF128:
976*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 128;
977*e5436536SAndroid Build Coastguard Worker         break;
978*e5436536SAndroid Build Coastguard Worker       case GF_QMFHYBRID135:
979*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = 135;
980*e5436536SAndroid Build Coastguard Worker         break;
981*e5436536SAndroid Build Coastguard Worker       case GF_UNIFORM:
982*e5436536SAndroid Build Coastguard Worker       default:
983*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount = FDKreadBits(hBs, 8);
984*e5436536SAndroid Build Coastguard Worker         eqSubbandGainCount++;
985*e5436536SAndroid Build Coastguard Worker         break;
986*e5436536SAndroid Build Coastguard Worker     }
987*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < uniqueEqSubbandGainsCount; k++) {
988*e5436536SAndroid Build Coastguard Worker       if (eqSubbandGainRepresentation == 1) {
989*e5436536SAndroid Build Coastguard Worker         _skipEqSubbandGainSpline(hBs);
990*e5436536SAndroid Build Coastguard Worker       } else {
991*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, eqSubbandGainCount * 9);
992*e5436536SAndroid Build Coastguard Worker       }
993*e5436536SAndroid Build Coastguard Worker     }
994*e5436536SAndroid Build Coastguard Worker   }
995*e5436536SAndroid Build Coastguard Worker }
996*e5436536SAndroid Build Coastguard Worker 
_skipTdFilterCascade(HANDLE_FDK_BITSTREAM hBs,const int eqChannelGroupCount)997*e5436536SAndroid Build Coastguard Worker static void _skipTdFilterCascade(HANDLE_FDK_BITSTREAM hBs,
998*e5436536SAndroid Build Coastguard Worker                                  const int eqChannelGroupCount) {
999*e5436536SAndroid Build Coastguard Worker   int i, eqCascadeGainPresent, filterBlockCount, eqPhaseAlignmentPresent;
1000*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < eqChannelGroupCount; i++) {
1001*e5436536SAndroid Build Coastguard Worker     eqCascadeGainPresent = FDKreadBits(hBs, 1);
1002*e5436536SAndroid Build Coastguard Worker     if (eqCascadeGainPresent) {
1003*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 10); /* bsEqCascadeGain */
1004*e5436536SAndroid Build Coastguard Worker     }
1005*e5436536SAndroid Build Coastguard Worker     filterBlockCount = FDKreadBits(hBs, 4);
1006*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, filterBlockCount * 7); /* filterBlockIndex */
1007*e5436536SAndroid Build Coastguard Worker   }
1008*e5436536SAndroid Build Coastguard Worker   eqPhaseAlignmentPresent = FDKreadBits(hBs, 1);
1009*e5436536SAndroid Build Coastguard Worker   {
1010*e5436536SAndroid Build Coastguard Worker     if (eqPhaseAlignmentPresent) {
1011*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < eqChannelGroupCount; i++) {
1012*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, (eqChannelGroupCount - i - 1) * 1);
1013*e5436536SAndroid Build Coastguard Worker       }
1014*e5436536SAndroid Build Coastguard Worker     }
1015*e5436536SAndroid Build Coastguard Worker   }
1016*e5436536SAndroid Build Coastguard Worker }
1017*e5436536SAndroid Build Coastguard Worker 
_skipEqInstructions(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig)1018*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs,
1019*e5436536SAndroid Build Coastguard Worker                                      HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
1020*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1021*e5436536SAndroid Build Coastguard Worker   int c, i, k, channelCount;
1022*e5436536SAndroid Build Coastguard Worker   int downmixIdPresent, downmixId, eqApplyToDownmix, additionalDownmixIdPresent,
1023*e5436536SAndroid Build Coastguard Worker       additionalDownmixIdCount = 0;
1024*e5436536SAndroid Build Coastguard Worker   int additionalDrcSetIdPresent, additionalDrcSetIdCount;
1025*e5436536SAndroid Build Coastguard Worker   int dependsOnEqSetPresent, eqChannelGroupCount, tdFilterCascadePresent,
1026*e5436536SAndroid Build Coastguard Worker       subbandGainsPresent, eqTransitionDurationPresent;
1027*e5436536SAndroid Build Coastguard Worker   UCHAR eqChannelGroupForChannel[8];
1028*e5436536SAndroid Build Coastguard Worker 
1029*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 6); /* eqSetId */
1030*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4); /* eqSetComplexityLevel */
1031*e5436536SAndroid Build Coastguard Worker   downmixIdPresent = FDKreadBits(hBs, 1);
1032*e5436536SAndroid Build Coastguard Worker   if (downmixIdPresent) {
1033*e5436536SAndroid Build Coastguard Worker     downmixId = FDKreadBits(hBs, 7);
1034*e5436536SAndroid Build Coastguard Worker     eqApplyToDownmix = FDKreadBits(hBs, 1);
1035*e5436536SAndroid Build Coastguard Worker     additionalDownmixIdPresent = FDKreadBits(hBs, 1);
1036*e5436536SAndroid Build Coastguard Worker     if (additionalDownmixIdPresent) {
1037*e5436536SAndroid Build Coastguard Worker       additionalDownmixIdCount = FDKreadBits(hBs, 7);
1038*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, additionalDownmixIdCount * 7); /* additionalDownmixId */
1039*e5436536SAndroid Build Coastguard Worker     }
1040*e5436536SAndroid Build Coastguard Worker   } else {
1041*e5436536SAndroid Build Coastguard Worker     downmixId = 0;
1042*e5436536SAndroid Build Coastguard Worker     eqApplyToDownmix = 0;
1043*e5436536SAndroid Build Coastguard Worker   }
1044*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 6); /* drcSetId */
1045*e5436536SAndroid Build Coastguard Worker   additionalDrcSetIdPresent = FDKreadBits(hBs, 1);
1046*e5436536SAndroid Build Coastguard Worker   if (additionalDrcSetIdPresent) {
1047*e5436536SAndroid Build Coastguard Worker     additionalDrcSetIdCount = FDKreadBits(hBs, 6);
1048*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < additionalDrcSetIdCount; i++) {
1049*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 6); /* additionalDrcSetId */
1050*e5436536SAndroid Build Coastguard Worker     }
1051*e5436536SAndroid Build Coastguard Worker   }
1052*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 16); /* eqSetPurpose */
1053*e5436536SAndroid Build Coastguard Worker   dependsOnEqSetPresent = FDKreadBits(hBs, 1);
1054*e5436536SAndroid Build Coastguard Worker   if (dependsOnEqSetPresent) {
1055*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* dependsOnEqSet */
1056*e5436536SAndroid Build Coastguard Worker   } else {
1057*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 1); /* noIndependentEqUse */
1058*e5436536SAndroid Build Coastguard Worker   }
1059*e5436536SAndroid Build Coastguard Worker 
1060*e5436536SAndroid Build Coastguard Worker   channelCount = hUniDrcConfig->channelLayout.baseChannelCount;
1061*e5436536SAndroid Build Coastguard Worker   if ((downmixIdPresent == 1) && (eqApplyToDownmix == 1) && (downmixId != 0) &&
1062*e5436536SAndroid Build Coastguard Worker       (downmixId != DOWNMIX_ID_ANY_DOWNMIX) &&
1063*e5436536SAndroid Build Coastguard Worker       (additionalDownmixIdCount == 0)) {
1064*e5436536SAndroid Build Coastguard Worker     DOWNMIX_INSTRUCTIONS* pDown =
1065*e5436536SAndroid Build Coastguard Worker         selectDownmixInstructions(hUniDrcConfig, downmixId);
1066*e5436536SAndroid Build Coastguard Worker     if (pDown == NULL) return DE_NOT_OK;
1067*e5436536SAndroid Build Coastguard Worker 
1068*e5436536SAndroid Build Coastguard Worker     channelCount =
1069*e5436536SAndroid Build Coastguard Worker         pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/
1070*e5436536SAndroid Build Coastguard Worker   } else if ((downmixId == DOWNMIX_ID_ANY_DOWNMIX) ||
1071*e5436536SAndroid Build Coastguard Worker              (additionalDownmixIdCount > 1)) {
1072*e5436536SAndroid Build Coastguard Worker     channelCount = 1;
1073*e5436536SAndroid Build Coastguard Worker   }
1074*e5436536SAndroid Build Coastguard Worker 
1075*e5436536SAndroid Build Coastguard Worker   eqChannelGroupCount = 0;
1076*e5436536SAndroid Build Coastguard Worker   for (c = 0; c < channelCount; c++) {
1077*e5436536SAndroid Build Coastguard Worker     int newGroup = 1;
1078*e5436536SAndroid Build Coastguard Worker     if (c >= 8) return DE_MEMORY_ERROR;
1079*e5436536SAndroid Build Coastguard Worker     eqChannelGroupForChannel[c] = FDKreadBits(hBs, 7);
1080*e5436536SAndroid Build Coastguard Worker     for (k = 0; k < c; k++) {
1081*e5436536SAndroid Build Coastguard Worker       if (eqChannelGroupForChannel[c] == eqChannelGroupForChannel[k]) {
1082*e5436536SAndroid Build Coastguard Worker         newGroup = 0;
1083*e5436536SAndroid Build Coastguard Worker       }
1084*e5436536SAndroid Build Coastguard Worker     }
1085*e5436536SAndroid Build Coastguard Worker     if (newGroup == 1) {
1086*e5436536SAndroid Build Coastguard Worker       eqChannelGroupCount += 1;
1087*e5436536SAndroid Build Coastguard Worker     }
1088*e5436536SAndroid Build Coastguard Worker   }
1089*e5436536SAndroid Build Coastguard Worker   tdFilterCascadePresent = FDKreadBits(hBs, 1);
1090*e5436536SAndroid Build Coastguard Worker   if (tdFilterCascadePresent) {
1091*e5436536SAndroid Build Coastguard Worker     _skipTdFilterCascade(hBs, eqChannelGroupCount);
1092*e5436536SAndroid Build Coastguard Worker   }
1093*e5436536SAndroid Build Coastguard Worker   subbandGainsPresent = FDKreadBits(hBs, 1);
1094*e5436536SAndroid Build Coastguard Worker   if (subbandGainsPresent) {
1095*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, eqChannelGroupCount * 6); /* subbandGainsIndex */
1096*e5436536SAndroid Build Coastguard Worker   }
1097*e5436536SAndroid Build Coastguard Worker   eqTransitionDurationPresent = FDKreadBits(hBs, 1);
1098*e5436536SAndroid Build Coastguard Worker   if (eqTransitionDurationPresent) {
1099*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 5); /* bsEqTransitionDuration */
1100*e5436536SAndroid Build Coastguard Worker   }
1101*e5436536SAndroid Build Coastguard Worker   return err;
1102*e5436536SAndroid Build Coastguard Worker }
1103*e5436536SAndroid Build Coastguard Worker 
_skipDrcCoefficientsBasic(HANDLE_FDK_BITSTREAM hBs)1104*e5436536SAndroid Build Coastguard Worker static void _skipDrcCoefficientsBasic(HANDLE_FDK_BITSTREAM hBs) {
1105*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4); /* drcLocation */
1106*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 7); /* drcCharacteristic */
1107*e5436536SAndroid Build Coastguard Worker }
1108*e5436536SAndroid Build Coastguard Worker 
_readDrcCoefficientsUniDrc(HANDLE_FDK_BITSTREAM hBs,const int version,DRC_COEFFICIENTS_UNI_DRC * pCoef)1109*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readDrcCoefficientsUniDrc(HANDLE_FDK_BITSTREAM hBs,
1110*e5436536SAndroid Build Coastguard Worker                                             const int version,
1111*e5436536SAndroid Build Coastguard Worker                                             DRC_COEFFICIENTS_UNI_DRC* pCoef) {
1112*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1113*e5436536SAndroid Build Coastguard Worker   int i, bsDrcFrameSize;
1114*e5436536SAndroid Build Coastguard Worker   int gainSequenceIndex = -1;
1115*e5436536SAndroid Build Coastguard Worker 
1116*e5436536SAndroid Build Coastguard Worker   pCoef->drcLocation = FDKreadBits(hBs, 4);
1117*e5436536SAndroid Build Coastguard Worker   pCoef->drcFrameSizePresent = FDKreadBits(hBs, 1);
1118*e5436536SAndroid Build Coastguard Worker 
1119*e5436536SAndroid Build Coastguard Worker   if (pCoef->drcFrameSizePresent == 1) {
1120*e5436536SAndroid Build Coastguard Worker     bsDrcFrameSize = FDKreadBits(hBs, 15);
1121*e5436536SAndroid Build Coastguard Worker     pCoef->drcFrameSize = bsDrcFrameSize + 1;
1122*e5436536SAndroid Build Coastguard Worker   }
1123*e5436536SAndroid Build Coastguard Worker   if (version == 0) {
1124*e5436536SAndroid Build Coastguard Worker     int gainSequenceCount = 0, gainSetCount;
1125*e5436536SAndroid Build Coastguard Worker     pCoef->characteristicLeftCount = 0;
1126*e5436536SAndroid Build Coastguard Worker     pCoef->characteristicRightCount = 0;
1127*e5436536SAndroid Build Coastguard Worker     gainSetCount = FDKreadBits(hBs, 6);
1128*e5436536SAndroid Build Coastguard Worker     pCoef->gainSetCount = fMin(gainSetCount, 12);
1129*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < gainSetCount; i++) {
1130*e5436536SAndroid Build Coastguard Worker       GAIN_SET tmpGset;
1131*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&tmpGset, sizeof(GAIN_SET));
1132*e5436536SAndroid Build Coastguard Worker       err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0);
1133*e5436536SAndroid Build Coastguard Worker       if (err) return err;
1134*e5436536SAndroid Build Coastguard Worker       gainSequenceCount += tmpGset.bandCount;
1135*e5436536SAndroid Build Coastguard Worker 
1136*e5436536SAndroid Build Coastguard Worker       if (i >= 12) continue;
1137*e5436536SAndroid Build Coastguard Worker       pCoef->gainSet[i] = tmpGset;
1138*e5436536SAndroid Build Coastguard Worker     }
1139*e5436536SAndroid Build Coastguard Worker     pCoef->gainSequenceCount = gainSequenceCount;
1140*e5436536SAndroid Build Coastguard Worker   } else { /* (version == 1) */
1141*e5436536SAndroid Build Coastguard Worker     UCHAR drcCharacteristicLeftPresent, drcCharacteristicRightPresent;
1142*e5436536SAndroid Build Coastguard Worker     UCHAR shapeFiltersPresent, shapeFilterCount, tmpPresent;
1143*e5436536SAndroid Build Coastguard Worker     int gainSetCount;
1144*e5436536SAndroid Build Coastguard Worker     drcCharacteristicLeftPresent = FDKreadBits(hBs, 1);
1145*e5436536SAndroid Build Coastguard Worker     if (drcCharacteristicLeftPresent) {
1146*e5436536SAndroid Build Coastguard Worker       pCoef->characteristicLeftCount = FDKreadBits(hBs, 4);
1147*e5436536SAndroid Build Coastguard Worker       if ((pCoef->characteristicLeftCount + 1) > 16) return DE_MEMORY_ERROR;
1148*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < pCoef->characteristicLeftCount; i++) {
1149*e5436536SAndroid Build Coastguard Worker         err = _readCustomDrcCharacteristic(
1150*e5436536SAndroid Build Coastguard Worker             hBs, CS_LEFT, &(pCoef->characteristicLeftFormat[i + 1]),
1151*e5436536SAndroid Build Coastguard Worker             &(pCoef->customCharacteristicLeft[i + 1]), 0);
1152*e5436536SAndroid Build Coastguard Worker         if (err) return err;
1153*e5436536SAndroid Build Coastguard Worker       }
1154*e5436536SAndroid Build Coastguard Worker     }
1155*e5436536SAndroid Build Coastguard Worker     drcCharacteristicRightPresent = FDKreadBits(hBs, 1);
1156*e5436536SAndroid Build Coastguard Worker     if (drcCharacteristicRightPresent) {
1157*e5436536SAndroid Build Coastguard Worker       pCoef->characteristicRightCount = FDKreadBits(hBs, 4);
1158*e5436536SAndroid Build Coastguard Worker       if ((pCoef->characteristicRightCount + 1) > 16) return DE_MEMORY_ERROR;
1159*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < pCoef->characteristicRightCount; i++) {
1160*e5436536SAndroid Build Coastguard Worker         err = _readCustomDrcCharacteristic(
1161*e5436536SAndroid Build Coastguard Worker             hBs, CS_RIGHT, &(pCoef->characteristicRightFormat[i + 1]),
1162*e5436536SAndroid Build Coastguard Worker             &(pCoef->customCharacteristicRight[i + 1]), 0);
1163*e5436536SAndroid Build Coastguard Worker         if (err) return err;
1164*e5436536SAndroid Build Coastguard Worker       }
1165*e5436536SAndroid Build Coastguard Worker     }
1166*e5436536SAndroid Build Coastguard Worker     shapeFiltersPresent = FDKreadBits(hBs, 1);
1167*e5436536SAndroid Build Coastguard Worker     if (shapeFiltersPresent) {
1168*e5436536SAndroid Build Coastguard Worker       shapeFilterCount = FDKreadBits(hBs, 4);
1169*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < shapeFilterCount; i++) {
1170*e5436536SAndroid Build Coastguard Worker         tmpPresent = FDKreadBits(hBs, 1);
1171*e5436536SAndroid Build Coastguard Worker         if (tmpPresent) /* lfCutParams */
1172*e5436536SAndroid Build Coastguard Worker           FDKpushFor(hBs, 5);
1173*e5436536SAndroid Build Coastguard Worker 
1174*e5436536SAndroid Build Coastguard Worker         tmpPresent = FDKreadBits(hBs, 1);
1175*e5436536SAndroid Build Coastguard Worker         if (tmpPresent) /* lfBoostParams */
1176*e5436536SAndroid Build Coastguard Worker           FDKpushFor(hBs, 5);
1177*e5436536SAndroid Build Coastguard Worker 
1178*e5436536SAndroid Build Coastguard Worker         tmpPresent = FDKreadBits(hBs, 1);
1179*e5436536SAndroid Build Coastguard Worker         if (tmpPresent) /* hfCutParams */
1180*e5436536SAndroid Build Coastguard Worker           FDKpushFor(hBs, 5);
1181*e5436536SAndroid Build Coastguard Worker 
1182*e5436536SAndroid Build Coastguard Worker         tmpPresent = FDKreadBits(hBs, 1);
1183*e5436536SAndroid Build Coastguard Worker         if (tmpPresent) /* hfBoostParams */
1184*e5436536SAndroid Build Coastguard Worker           FDKpushFor(hBs, 5);
1185*e5436536SAndroid Build Coastguard Worker       }
1186*e5436536SAndroid Build Coastguard Worker     }
1187*e5436536SAndroid Build Coastguard Worker     pCoef->gainSequenceCount = FDKreadBits(hBs, 6);
1188*e5436536SAndroid Build Coastguard Worker     gainSetCount = FDKreadBits(hBs, 6);
1189*e5436536SAndroid Build Coastguard Worker     pCoef->gainSetCount = fMin(gainSetCount, 12);
1190*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < gainSetCount; i++) {
1191*e5436536SAndroid Build Coastguard Worker       GAIN_SET tmpGset;
1192*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&tmpGset, sizeof(GAIN_SET));
1193*e5436536SAndroid Build Coastguard Worker       err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0);
1194*e5436536SAndroid Build Coastguard Worker       if (err) return err;
1195*e5436536SAndroid Build Coastguard Worker 
1196*e5436536SAndroid Build Coastguard Worker       if (i >= 12) continue;
1197*e5436536SAndroid Build Coastguard Worker       pCoef->gainSet[i] = tmpGset;
1198*e5436536SAndroid Build Coastguard Worker     }
1199*e5436536SAndroid Build Coastguard Worker   }
1200*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < 12; i++) {
1201*e5436536SAndroid Build Coastguard Worker     pCoef->gainSetIndexForGainSequence[i] = 255;
1202*e5436536SAndroid Build Coastguard Worker   }
1203*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < pCoef->gainSetCount; i++) {
1204*e5436536SAndroid Build Coastguard Worker     int b;
1205*e5436536SAndroid Build Coastguard Worker     for (b = 0; b < pCoef->gainSet[i].bandCount; b++) {
1206*e5436536SAndroid Build Coastguard Worker       if (pCoef->gainSet[i].gainSequenceIndex[b] >= 12) continue;
1207*e5436536SAndroid Build Coastguard Worker       pCoef->gainSetIndexForGainSequence[pCoef->gainSet[i]
1208*e5436536SAndroid Build Coastguard Worker                                              .gainSequenceIndex[b]] = i;
1209*e5436536SAndroid Build Coastguard Worker     }
1210*e5436536SAndroid Build Coastguard Worker   }
1211*e5436536SAndroid Build Coastguard Worker 
1212*e5436536SAndroid Build Coastguard Worker   return err;
1213*e5436536SAndroid Build Coastguard Worker }
1214*e5436536SAndroid Build Coastguard Worker 
_skipDrcInstructionsBasic(HANDLE_FDK_BITSTREAM hBs)1215*e5436536SAndroid Build Coastguard Worker static void _skipDrcInstructionsBasic(HANDLE_FDK_BITSTREAM hBs) {
1216*e5436536SAndroid Build Coastguard Worker   int drcSetEffect;
1217*e5436536SAndroid Build Coastguard Worker   int additionalDownmixIdPresent, additionalDownmixIdCount,
1218*e5436536SAndroid Build Coastguard Worker       limiterPeakTargetPresent;
1219*e5436536SAndroid Build Coastguard Worker   int drcSetTargetLoudnessPresent, drcSetTargetLoudnessValueLowerPresent;
1220*e5436536SAndroid Build Coastguard Worker 
1221*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 6); /* drcSetId */
1222*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 4); /* drcLocation */
1223*e5436536SAndroid Build Coastguard Worker   FDKpushFor(hBs, 7); /* downmixId */
1224*e5436536SAndroid Build Coastguard Worker   additionalDownmixIdPresent = FDKreadBits(hBs, 1);
1225*e5436536SAndroid Build Coastguard Worker   if (additionalDownmixIdPresent) {
1226*e5436536SAndroid Build Coastguard Worker     additionalDownmixIdCount = FDKreadBits(hBs, 3);
1227*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 7 * additionalDownmixIdCount); /* additionalDownmixId */
1228*e5436536SAndroid Build Coastguard Worker   }
1229*e5436536SAndroid Build Coastguard Worker 
1230*e5436536SAndroid Build Coastguard Worker   drcSetEffect = FDKreadBits(hBs, 16);
1231*e5436536SAndroid Build Coastguard Worker   if (!(drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF))) {
1232*e5436536SAndroid Build Coastguard Worker     limiterPeakTargetPresent = FDKreadBits(hBs, 1);
1233*e5436536SAndroid Build Coastguard Worker     if (limiterPeakTargetPresent) {
1234*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 8); /* bsLimiterPeakTarget */
1235*e5436536SAndroid Build Coastguard Worker     }
1236*e5436536SAndroid Build Coastguard Worker   }
1237*e5436536SAndroid Build Coastguard Worker 
1238*e5436536SAndroid Build Coastguard Worker   drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1);
1239*e5436536SAndroid Build Coastguard Worker   if (drcSetTargetLoudnessPresent) {
1240*e5436536SAndroid Build Coastguard Worker     FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueUpper */
1241*e5436536SAndroid Build Coastguard Worker     drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1);
1242*e5436536SAndroid Build Coastguard Worker     if (drcSetTargetLoudnessValueLowerPresent) {
1243*e5436536SAndroid Build Coastguard Worker       FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueLower */
1244*e5436536SAndroid Build Coastguard Worker     }
1245*e5436536SAndroid Build Coastguard Worker   }
1246*e5436536SAndroid Build Coastguard Worker }
1247*e5436536SAndroid Build Coastguard Worker 
_readDrcInstructionsUniDrc(HANDLE_FDK_BITSTREAM hBs,const int version,HANDLE_UNI_DRC_CONFIG hUniDrcConfig,DRC_INSTRUCTIONS_UNI_DRC * pInst)1248*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readDrcInstructionsUniDrc(HANDLE_FDK_BITSTREAM hBs,
1249*e5436536SAndroid Build Coastguard Worker                                             const int version,
1250*e5436536SAndroid Build Coastguard Worker                                             HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
1251*e5436536SAndroid Build Coastguard Worker                                             DRC_INSTRUCTIONS_UNI_DRC* pInst) {
1252*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1253*e5436536SAndroid Build Coastguard Worker   int i, g, c;
1254*e5436536SAndroid Build Coastguard Worker   int downmixIdPresent, additionalDownmixIdPresent, additionalDownmixIdCount;
1255*e5436536SAndroid Build Coastguard Worker   int bsLimiterPeakTarget, channelCount;
1256*e5436536SAndroid Build Coastguard Worker   DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL;
1257*e5436536SAndroid Build Coastguard Worker   int repeatParameters, bsRepeatParametersCount;
1258*e5436536SAndroid Build Coastguard Worker   int repeatSequenceIndex, bsRepeatSequenceCount;
1259*e5436536SAndroid Build Coastguard Worker   SCHAR* gainSetIndex = pInst->gainSetIndex;
1260*e5436536SAndroid Build Coastguard Worker   SCHAR channelGroupForChannel[8];
1261*e5436536SAndroid Build Coastguard Worker   DUCKING_MODIFICATION duckingModificationForChannelGroup[8];
1262*e5436536SAndroid Build Coastguard Worker 
1263*e5436536SAndroid Build Coastguard Worker   pInst->drcSetId = FDKreadBits(hBs, 6);
1264*e5436536SAndroid Build Coastguard Worker   if (version == 0) {
1265*e5436536SAndroid Build Coastguard Worker     /* Assume all v0 DRC sets to be manageable in terms of complexity */
1266*e5436536SAndroid Build Coastguard Worker     pInst->drcSetComplexityLevel = 2;
1267*e5436536SAndroid Build Coastguard Worker   } else {
1268*e5436536SAndroid Build Coastguard Worker     pInst->drcSetComplexityLevel = FDKreadBits(hBs, 4);
1269*e5436536SAndroid Build Coastguard Worker   }
1270*e5436536SAndroid Build Coastguard Worker   pInst->drcLocation = FDKreadBits(hBs, 4);
1271*e5436536SAndroid Build Coastguard Worker   if (version == 0) {
1272*e5436536SAndroid Build Coastguard Worker     downmixIdPresent = 1;
1273*e5436536SAndroid Build Coastguard Worker   } else {
1274*e5436536SAndroid Build Coastguard Worker     downmixIdPresent = FDKreadBits(hBs, 1);
1275*e5436536SAndroid Build Coastguard Worker   }
1276*e5436536SAndroid Build Coastguard Worker   if (downmixIdPresent) {
1277*e5436536SAndroid Build Coastguard Worker     pInst->downmixId[0] = FDKreadBits(hBs, 7);
1278*e5436536SAndroid Build Coastguard Worker     if (version == 0) {
1279*e5436536SAndroid Build Coastguard Worker       if (pInst->downmixId[0] == 0)
1280*e5436536SAndroid Build Coastguard Worker         pInst->drcApplyToDownmix = 0;
1281*e5436536SAndroid Build Coastguard Worker       else
1282*e5436536SAndroid Build Coastguard Worker         pInst->drcApplyToDownmix = 1;
1283*e5436536SAndroid Build Coastguard Worker     } else {
1284*e5436536SAndroid Build Coastguard Worker       pInst->drcApplyToDownmix = FDKreadBits(hBs, 1);
1285*e5436536SAndroid Build Coastguard Worker     }
1286*e5436536SAndroid Build Coastguard Worker 
1287*e5436536SAndroid Build Coastguard Worker     additionalDownmixIdPresent = FDKreadBits(hBs, 1);
1288*e5436536SAndroid Build Coastguard Worker     if (additionalDownmixIdPresent) {
1289*e5436536SAndroid Build Coastguard Worker       additionalDownmixIdCount = FDKreadBits(hBs, 3);
1290*e5436536SAndroid Build Coastguard Worker       if ((1 + additionalDownmixIdCount) > 8) return DE_MEMORY_ERROR;
1291*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < additionalDownmixIdCount; i++) {
1292*e5436536SAndroid Build Coastguard Worker         pInst->downmixId[i + 1] = FDKreadBits(hBs, 7);
1293*e5436536SAndroid Build Coastguard Worker       }
1294*e5436536SAndroid Build Coastguard Worker       pInst->downmixIdCount = 1 + additionalDownmixIdCount;
1295*e5436536SAndroid Build Coastguard Worker     } else {
1296*e5436536SAndroid Build Coastguard Worker       pInst->downmixIdCount = 1;
1297*e5436536SAndroid Build Coastguard Worker     }
1298*e5436536SAndroid Build Coastguard Worker   } else {
1299*e5436536SAndroid Build Coastguard Worker     pInst->downmixId[0] = 0;
1300*e5436536SAndroid Build Coastguard Worker     pInst->downmixIdCount = 1;
1301*e5436536SAndroid Build Coastguard Worker   }
1302*e5436536SAndroid Build Coastguard Worker 
1303*e5436536SAndroid Build Coastguard Worker   pInst->drcSetEffect = FDKreadBits(hBs, 16);
1304*e5436536SAndroid Build Coastguard Worker 
1305*e5436536SAndroid Build Coastguard Worker   if ((pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) {
1306*e5436536SAndroid Build Coastguard Worker     pInst->limiterPeakTargetPresent = FDKreadBits(hBs, 1);
1307*e5436536SAndroid Build Coastguard Worker     if (pInst->limiterPeakTargetPresent) {
1308*e5436536SAndroid Build Coastguard Worker       bsLimiterPeakTarget = FDKreadBits(hBs, 8);
1309*e5436536SAndroid Build Coastguard Worker       pInst->limiterPeakTarget = -(FIXP_SGL)(
1310*e5436536SAndroid Build Coastguard Worker           bsLimiterPeakTarget
1311*e5436536SAndroid Build Coastguard Worker           << (FRACT_BITS - 1 - 3 - 5)); /* - bsLimiterPeakTarget * 0.125; */
1312*e5436536SAndroid Build Coastguard Worker     }
1313*e5436536SAndroid Build Coastguard Worker   }
1314*e5436536SAndroid Build Coastguard Worker 
1315*e5436536SAndroid Build Coastguard Worker   pInst->drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1);
1316*e5436536SAndroid Build Coastguard Worker 
1317*e5436536SAndroid Build Coastguard Worker   /* set default values */
1318*e5436536SAndroid Build Coastguard Worker   pInst->drcSetTargetLoudnessValueUpper = 0;
1319*e5436536SAndroid Build Coastguard Worker   pInst->drcSetTargetLoudnessValueLower = -63;
1320*e5436536SAndroid Build Coastguard Worker 
1321*e5436536SAndroid Build Coastguard Worker   if (pInst->drcSetTargetLoudnessPresent == 1) {
1322*e5436536SAndroid Build Coastguard Worker     int bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower;
1323*e5436536SAndroid Build Coastguard Worker     int drcSetTargetLoudnessValueLowerPresent;
1324*e5436536SAndroid Build Coastguard Worker     bsDrcSetTargetLoudnessValueUpper = FDKreadBits(hBs, 6);
1325*e5436536SAndroid Build Coastguard Worker     pInst->drcSetTargetLoudnessValueUpper =
1326*e5436536SAndroid Build Coastguard Worker         bsDrcSetTargetLoudnessValueUpper - 63;
1327*e5436536SAndroid Build Coastguard Worker     drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1);
1328*e5436536SAndroid Build Coastguard Worker     if (drcSetTargetLoudnessValueLowerPresent == 1) {
1329*e5436536SAndroid Build Coastguard Worker       bsDrcSetTargetLoudnessValueLower = FDKreadBits(hBs, 6);
1330*e5436536SAndroid Build Coastguard Worker       pInst->drcSetTargetLoudnessValueLower =
1331*e5436536SAndroid Build Coastguard Worker           bsDrcSetTargetLoudnessValueLower - 63;
1332*e5436536SAndroid Build Coastguard Worker     }
1333*e5436536SAndroid Build Coastguard Worker   }
1334*e5436536SAndroid Build Coastguard Worker 
1335*e5436536SAndroid Build Coastguard Worker   pInst->dependsOnDrcSetPresent = FDKreadBits(hBs, 1);
1336*e5436536SAndroid Build Coastguard Worker 
1337*e5436536SAndroid Build Coastguard Worker   pInst->noIndependentUse = 0;
1338*e5436536SAndroid Build Coastguard Worker   if (pInst->dependsOnDrcSetPresent) {
1339*e5436536SAndroid Build Coastguard Worker     pInst->dependsOnDrcSet = FDKreadBits(hBs, 6);
1340*e5436536SAndroid Build Coastguard Worker   } else {
1341*e5436536SAndroid Build Coastguard Worker     pInst->noIndependentUse = FDKreadBits(hBs, 1);
1342*e5436536SAndroid Build Coastguard Worker   }
1343*e5436536SAndroid Build Coastguard Worker 
1344*e5436536SAndroid Build Coastguard Worker   if (version == 0) {
1345*e5436536SAndroid Build Coastguard Worker     pInst->requiresEq = 0;
1346*e5436536SAndroid Build Coastguard Worker   } else {
1347*e5436536SAndroid Build Coastguard Worker     pInst->requiresEq = FDKreadBits(hBs, 1);
1348*e5436536SAndroid Build Coastguard Worker   }
1349*e5436536SAndroid Build Coastguard Worker 
1350*e5436536SAndroid Build Coastguard Worker   pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation);
1351*e5436536SAndroid Build Coastguard Worker 
1352*e5436536SAndroid Build Coastguard Worker   pInst->drcChannelCount = channelCount =
1353*e5436536SAndroid Build Coastguard Worker       hUniDrcConfig->channelLayout.baseChannelCount;
1354*e5436536SAndroid Build Coastguard Worker 
1355*e5436536SAndroid Build Coastguard Worker   if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) {
1356*e5436536SAndroid Build Coastguard Worker     DUCKING_MODIFICATION* pDModForChannel =
1357*e5436536SAndroid Build Coastguard Worker         pInst->duckingModificationForChannel;
1358*e5436536SAndroid Build Coastguard Worker     c = 0;
1359*e5436536SAndroid Build Coastguard Worker     while (c < channelCount) {
1360*e5436536SAndroid Build Coastguard Worker       int bsGainSetIndex;
1361*e5436536SAndroid Build Coastguard Worker       bsGainSetIndex = FDKreadBits(hBs, 6);
1362*e5436536SAndroid Build Coastguard Worker       if (c >= 8) return DE_MEMORY_ERROR;
1363*e5436536SAndroid Build Coastguard Worker       gainSetIndex[c] = bsGainSetIndex - 1;
1364*e5436536SAndroid Build Coastguard Worker       _decodeDuckingModification(hBs, &(pDModForChannel[c]), 0);
1365*e5436536SAndroid Build Coastguard Worker 
1366*e5436536SAndroid Build Coastguard Worker       c++;
1367*e5436536SAndroid Build Coastguard Worker       repeatParameters = FDKreadBits(hBs, 1);
1368*e5436536SAndroid Build Coastguard Worker       if (repeatParameters == 1) {
1369*e5436536SAndroid Build Coastguard Worker         bsRepeatParametersCount = FDKreadBits(hBs, 5);
1370*e5436536SAndroid Build Coastguard Worker         bsRepeatParametersCount += 1;
1371*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < bsRepeatParametersCount; i++) {
1372*e5436536SAndroid Build Coastguard Worker           if (c >= 8) return DE_MEMORY_ERROR;
1373*e5436536SAndroid Build Coastguard Worker           gainSetIndex[c] = gainSetIndex[c - 1];
1374*e5436536SAndroid Build Coastguard Worker           pDModForChannel[c] = pDModForChannel[c - 1];
1375*e5436536SAndroid Build Coastguard Worker           c++;
1376*e5436536SAndroid Build Coastguard Worker         }
1377*e5436536SAndroid Build Coastguard Worker       }
1378*e5436536SAndroid Build Coastguard Worker     }
1379*e5436536SAndroid Build Coastguard Worker     if (c > channelCount) {
1380*e5436536SAndroid Build Coastguard Worker       return DE_NOT_OK;
1381*e5436536SAndroid Build Coastguard Worker     }
1382*e5436536SAndroid Build Coastguard Worker 
1383*e5436536SAndroid Build Coastguard Worker     err = deriveDrcChannelGroups(
1384*e5436536SAndroid Build Coastguard Worker         pInst->drcSetEffect, pInst->drcChannelCount, gainSetIndex,
1385*e5436536SAndroid Build Coastguard Worker         pDModForChannel, &pInst->nDrcChannelGroups,
1386*e5436536SAndroid Build Coastguard Worker         pInst->gainSetIndexForChannelGroup, channelGroupForChannel,
1387*e5436536SAndroid Build Coastguard Worker         duckingModificationForChannelGroup);
1388*e5436536SAndroid Build Coastguard Worker     if (err) return (err);
1389*e5436536SAndroid Build Coastguard Worker   } else {
1390*e5436536SAndroid Build Coastguard Worker     int deriveChannelCount = 0;
1391*e5436536SAndroid Build Coastguard Worker     if (((version == 0) || (pInst->drcApplyToDownmix != 0)) &&
1392*e5436536SAndroid Build Coastguard Worker         (pInst->downmixId[0] != DOWNMIX_ID_BASE_LAYOUT) &&
1393*e5436536SAndroid Build Coastguard Worker         (pInst->downmixId[0] != DOWNMIX_ID_ANY_DOWNMIX) &&
1394*e5436536SAndroid Build Coastguard Worker         (pInst->downmixIdCount == 1)) {
1395*e5436536SAndroid Build Coastguard Worker       if (hUniDrcConfig->downmixInstructionsCount != 0) {
1396*e5436536SAndroid Build Coastguard Worker         DOWNMIX_INSTRUCTIONS* pDown =
1397*e5436536SAndroid Build Coastguard Worker             selectDownmixInstructions(hUniDrcConfig, pInst->downmixId[0]);
1398*e5436536SAndroid Build Coastguard Worker         if (pDown == NULL) return DE_NOT_OK;
1399*e5436536SAndroid Build Coastguard Worker         pInst->drcChannelCount = channelCount =
1400*e5436536SAndroid Build Coastguard Worker             pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/
1401*e5436536SAndroid Build Coastguard Worker       } else {
1402*e5436536SAndroid Build Coastguard Worker         deriveChannelCount = 1;
1403*e5436536SAndroid Build Coastguard Worker         channelCount = 1;
1404*e5436536SAndroid Build Coastguard Worker       }
1405*e5436536SAndroid Build Coastguard Worker     } else if (((version == 0) || (pInst->drcApplyToDownmix != 0)) &&
1406*e5436536SAndroid Build Coastguard Worker                ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) ||
1407*e5436536SAndroid Build Coastguard Worker                 (pInst->downmixIdCount > 1))) {
1408*e5436536SAndroid Build Coastguard Worker       /* Set maximum channel count as upper border. The effective channel count
1409*e5436536SAndroid Build Coastguard Worker        * is set at the process function. */
1410*e5436536SAndroid Build Coastguard Worker       pInst->drcChannelCount = 8;
1411*e5436536SAndroid Build Coastguard Worker       channelCount = 1;
1412*e5436536SAndroid Build Coastguard Worker     }
1413*e5436536SAndroid Build Coastguard Worker 
1414*e5436536SAndroid Build Coastguard Worker     c = 0;
1415*e5436536SAndroid Build Coastguard Worker     while (c < channelCount) {
1416*e5436536SAndroid Build Coastguard Worker       int bsGainSetIndex;
1417*e5436536SAndroid Build Coastguard Worker       bsGainSetIndex = FDKreadBits(hBs, 6);
1418*e5436536SAndroid Build Coastguard Worker       if (c >= 8) return DE_MEMORY_ERROR;
1419*e5436536SAndroid Build Coastguard Worker       gainSetIndex[c] = bsGainSetIndex - 1;
1420*e5436536SAndroid Build Coastguard Worker       c++;
1421*e5436536SAndroid Build Coastguard Worker       repeatSequenceIndex = FDKreadBits(hBs, 1);
1422*e5436536SAndroid Build Coastguard Worker 
1423*e5436536SAndroid Build Coastguard Worker       if (repeatSequenceIndex == 1) {
1424*e5436536SAndroid Build Coastguard Worker         bsRepeatSequenceCount = FDKreadBits(hBs, 5);
1425*e5436536SAndroid Build Coastguard Worker         bsRepeatSequenceCount += 1;
1426*e5436536SAndroid Build Coastguard Worker         if (deriveChannelCount) {
1427*e5436536SAndroid Build Coastguard Worker           channelCount = 1 + bsRepeatSequenceCount;
1428*e5436536SAndroid Build Coastguard Worker         }
1429*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < bsRepeatSequenceCount; i++) {
1430*e5436536SAndroid Build Coastguard Worker           if (c >= 8) return DE_MEMORY_ERROR;
1431*e5436536SAndroid Build Coastguard Worker           gainSetIndex[c] = bsGainSetIndex - 1;
1432*e5436536SAndroid Build Coastguard Worker           c++;
1433*e5436536SAndroid Build Coastguard Worker         }
1434*e5436536SAndroid Build Coastguard Worker       }
1435*e5436536SAndroid Build Coastguard Worker     }
1436*e5436536SAndroid Build Coastguard Worker     if (c > channelCount) {
1437*e5436536SAndroid Build Coastguard Worker       return DE_NOT_OK;
1438*e5436536SAndroid Build Coastguard Worker     }
1439*e5436536SAndroid Build Coastguard Worker     if (deriveChannelCount) {
1440*e5436536SAndroid Build Coastguard Worker       pInst->drcChannelCount = channelCount;
1441*e5436536SAndroid Build Coastguard Worker     }
1442*e5436536SAndroid Build Coastguard Worker 
1443*e5436536SAndroid Build Coastguard Worker     /* DOWNMIX_ID_ANY_DOWNMIX: channelCount is 1. Distribute gainSetIndex to all
1444*e5436536SAndroid Build Coastguard Worker      * channels. */
1445*e5436536SAndroid Build Coastguard Worker     if ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) ||
1446*e5436536SAndroid Build Coastguard Worker         (pInst->downmixIdCount > 1)) {
1447*e5436536SAndroid Build Coastguard Worker       for (c = 1; c < pInst->drcChannelCount; c++) {
1448*e5436536SAndroid Build Coastguard Worker         gainSetIndex[c] = gainSetIndex[0];
1449*e5436536SAndroid Build Coastguard Worker       }
1450*e5436536SAndroid Build Coastguard Worker     }
1451*e5436536SAndroid Build Coastguard Worker 
1452*e5436536SAndroid Build Coastguard Worker     err = deriveDrcChannelGroups(pInst->drcSetEffect, pInst->drcChannelCount,
1453*e5436536SAndroid Build Coastguard Worker                                  gainSetIndex, NULL, &pInst->nDrcChannelGroups,
1454*e5436536SAndroid Build Coastguard Worker                                  pInst->gainSetIndexForChannelGroup,
1455*e5436536SAndroid Build Coastguard Worker                                  channelGroupForChannel, NULL);
1456*e5436536SAndroid Build Coastguard Worker     if (err) return (err);
1457*e5436536SAndroid Build Coastguard Worker 
1458*e5436536SAndroid Build Coastguard Worker     for (g = 0; g < pInst->nDrcChannelGroups; g++) {
1459*e5436536SAndroid Build Coastguard Worker       int set, bandCount;
1460*e5436536SAndroid Build Coastguard Worker       set = pInst->gainSetIndexForChannelGroup[g];
1461*e5436536SAndroid Build Coastguard Worker 
1462*e5436536SAndroid Build Coastguard Worker       /* get bandCount */
1463*e5436536SAndroid Build Coastguard Worker       if (pCoef != NULL && set < pCoef->gainSetCount) {
1464*e5436536SAndroid Build Coastguard Worker         bandCount = pCoef->gainSet[set].bandCount;
1465*e5436536SAndroid Build Coastguard Worker       } else {
1466*e5436536SAndroid Build Coastguard Worker         bandCount = 1;
1467*e5436536SAndroid Build Coastguard Worker       }
1468*e5436536SAndroid Build Coastguard Worker 
1469*e5436536SAndroid Build Coastguard Worker       _decodeGainModification(hBs, version, bandCount,
1470*e5436536SAndroid Build Coastguard Worker                               pInst->gainModificationForChannelGroup[g], 0);
1471*e5436536SAndroid Build Coastguard Worker     }
1472*e5436536SAndroid Build Coastguard Worker   }
1473*e5436536SAndroid Build Coastguard Worker 
1474*e5436536SAndroid Build Coastguard Worker   return err;
1475*e5436536SAndroid Build Coastguard Worker }
1476*e5436536SAndroid Build Coastguard Worker 
_readChannelLayout(HANDLE_FDK_BITSTREAM hBs,CHANNEL_LAYOUT * pChan)1477*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readChannelLayout(HANDLE_FDK_BITSTREAM hBs,
1478*e5436536SAndroid Build Coastguard Worker                                     CHANNEL_LAYOUT* pChan) {
1479*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1480*e5436536SAndroid Build Coastguard Worker 
1481*e5436536SAndroid Build Coastguard Worker   pChan->baseChannelCount = FDKreadBits(hBs, 7);
1482*e5436536SAndroid Build Coastguard Worker 
1483*e5436536SAndroid Build Coastguard Worker   if (pChan->baseChannelCount > 8) return DE_NOT_OK;
1484*e5436536SAndroid Build Coastguard Worker 
1485*e5436536SAndroid Build Coastguard Worker   pChan->layoutSignalingPresent = FDKreadBits(hBs, 1);
1486*e5436536SAndroid Build Coastguard Worker 
1487*e5436536SAndroid Build Coastguard Worker   if (pChan->layoutSignalingPresent) {
1488*e5436536SAndroid Build Coastguard Worker     pChan->definedLayout = FDKreadBits(hBs, 8);
1489*e5436536SAndroid Build Coastguard Worker 
1490*e5436536SAndroid Build Coastguard Worker     if (pChan->definedLayout == 0) {
1491*e5436536SAndroid Build Coastguard Worker       int i;
1492*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < pChan->baseChannelCount; i++) {
1493*e5436536SAndroid Build Coastguard Worker         if (i < 8) {
1494*e5436536SAndroid Build Coastguard Worker           pChan->speakerPosition[i] = FDKreadBits(hBs, 7);
1495*e5436536SAndroid Build Coastguard Worker         } else {
1496*e5436536SAndroid Build Coastguard Worker           FDKpushFor(hBs, 7);
1497*e5436536SAndroid Build Coastguard Worker         }
1498*e5436536SAndroid Build Coastguard Worker       }
1499*e5436536SAndroid Build Coastguard Worker     }
1500*e5436536SAndroid Build Coastguard Worker   }
1501*e5436536SAndroid Build Coastguard Worker   return err;
1502*e5436536SAndroid Build Coastguard Worker }
1503*e5436536SAndroid Build Coastguard Worker 
_readDownmixInstructions(HANDLE_FDK_BITSTREAM hBs,const int version,CHANNEL_LAYOUT * pChan,DOWNMIX_INSTRUCTIONS * pDown)1504*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readDownmixInstructions(HANDLE_FDK_BITSTREAM hBs,
1505*e5436536SAndroid Build Coastguard Worker                                           const int version,
1506*e5436536SAndroid Build Coastguard Worker                                           CHANNEL_LAYOUT* pChan,
1507*e5436536SAndroid Build Coastguard Worker                                           DOWNMIX_INSTRUCTIONS* pDown) {
1508*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1509*e5436536SAndroid Build Coastguard Worker 
1510*e5436536SAndroid Build Coastguard Worker   pDown->downmixId = FDKreadBits(hBs, 7);
1511*e5436536SAndroid Build Coastguard Worker   pDown->targetChannelCount = FDKreadBits(hBs, 7);
1512*e5436536SAndroid Build Coastguard Worker   pDown->targetLayout = FDKreadBits(hBs, 8);
1513*e5436536SAndroid Build Coastguard Worker   pDown->downmixCoefficientsPresent = FDKreadBits(hBs, 1);
1514*e5436536SAndroid Build Coastguard Worker 
1515*e5436536SAndroid Build Coastguard Worker   if (pDown->downmixCoefficientsPresent) {
1516*e5436536SAndroid Build Coastguard Worker     int nDownmixCoeffs = pDown->targetChannelCount * pChan->baseChannelCount;
1517*e5436536SAndroid Build Coastguard Worker     int i;
1518*e5436536SAndroid Build Coastguard Worker     if (nDownmixCoeffs > 8 * 8) return DE_NOT_OK;
1519*e5436536SAndroid Build Coastguard Worker     if (version == 0) {
1520*e5436536SAndroid Build Coastguard Worker       pDown->bsDownmixOffset = 0;
1521*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < nDownmixCoeffs; i++) {
1522*e5436536SAndroid Build Coastguard Worker         /* LFE downmix coefficients are not supported. */
1523*e5436536SAndroid Build Coastguard Worker         pDown->downmixCoefficient[i] = downmixCoeff[FDKreadBits(hBs, 4)];
1524*e5436536SAndroid Build Coastguard Worker       }
1525*e5436536SAndroid Build Coastguard Worker     } else {
1526*e5436536SAndroid Build Coastguard Worker       pDown->bsDownmixOffset = FDKreadBits(hBs, 4);
1527*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < nDownmixCoeffs; i++) {
1528*e5436536SAndroid Build Coastguard Worker         pDown->downmixCoefficient[i] = downmixCoeffV1[FDKreadBits(hBs, 5)];
1529*e5436536SAndroid Build Coastguard Worker       }
1530*e5436536SAndroid Build Coastguard Worker     }
1531*e5436536SAndroid Build Coastguard Worker   }
1532*e5436536SAndroid Build Coastguard Worker   return err;
1533*e5436536SAndroid Build Coastguard Worker }
1534*e5436536SAndroid Build Coastguard Worker 
_readDrcExtensionV1(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig)1535*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readDrcExtensionV1(HANDLE_FDK_BITSTREAM hBs,
1536*e5436536SAndroid Build Coastguard Worker                                      HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
1537*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1538*e5436536SAndroid Build Coastguard Worker   int downmixInstructionsV1Present;
1539*e5436536SAndroid Build Coastguard Worker   int drcCoeffsAndInstructionsUniDrcV1Present;
1540*e5436536SAndroid Build Coastguard Worker   int loudEqInstructionsPresent, loudEqInstructionsCount;
1541*e5436536SAndroid Build Coastguard Worker   int eqPresent, eqInstructionsCount;
1542*e5436536SAndroid Build Coastguard Worker   int i, offset;
1543*e5436536SAndroid Build Coastguard Worker   int diff = hUniDrcConfig->diff;
1544*e5436536SAndroid Build Coastguard Worker 
1545*e5436536SAndroid Build Coastguard Worker   downmixInstructionsV1Present = FDKreadBits(hBs, 1);
1546*e5436536SAndroid Build Coastguard Worker   if (downmixInstructionsV1Present == 1) {
1547*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1,
1548*e5436536SAndroid Build Coastguard Worker                         FDKreadBits(hBs, 7));
1549*e5436536SAndroid Build Coastguard Worker     offset = hUniDrcConfig->downmixInstructionsCountV0;
1550*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->downmixInstructionsCount = fMin(
1551*e5436536SAndroid Build Coastguard Worker         (UCHAR)(offset + hUniDrcConfig->downmixInstructionsCountV1), (UCHAR)6);
1552*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV1; i++) {
1553*e5436536SAndroid Build Coastguard Worker       DOWNMIX_INSTRUCTIONS tmpDown;
1554*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS));
1555*e5436536SAndroid Build Coastguard Worker       err = _readDownmixInstructions(hBs, 1, &hUniDrcConfig->channelLayout,
1556*e5436536SAndroid Build Coastguard Worker                                      &tmpDown);
1557*e5436536SAndroid Build Coastguard Worker       if (err) return err;
1558*e5436536SAndroid Build Coastguard Worker       if ((offset + i) >= 6) continue;
1559*e5436536SAndroid Build Coastguard Worker       if (!diff)
1560*e5436536SAndroid Build Coastguard Worker         diff |= (FDKmemcmp(&tmpDown,
1561*e5436536SAndroid Build Coastguard Worker                            &(hUniDrcConfig->downmixInstructions[offset + i]),
1562*e5436536SAndroid Build Coastguard Worker                            sizeof(DOWNMIX_INSTRUCTIONS)) != 0);
1563*e5436536SAndroid Build Coastguard Worker       hUniDrcConfig->downmixInstructions[offset + i] = tmpDown;
1564*e5436536SAndroid Build Coastguard Worker     }
1565*e5436536SAndroid Build Coastguard Worker   } else {
1566*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, 0);
1567*e5436536SAndroid Build Coastguard Worker   }
1568*e5436536SAndroid Build Coastguard Worker 
1569*e5436536SAndroid Build Coastguard Worker   drcCoeffsAndInstructionsUniDrcV1Present = FDKreadBits(hBs, 1);
1570*e5436536SAndroid Build Coastguard Worker   if (drcCoeffsAndInstructionsUniDrcV1Present == 1) {
1571*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1,
1572*e5436536SAndroid Build Coastguard Worker                         FDKreadBits(hBs, 3));
1573*e5436536SAndroid Build Coastguard Worker     offset = hUniDrcConfig->drcCoefficientsUniDrcCountV0;
1574*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->drcCoefficientsUniDrcCount =
1575*e5436536SAndroid Build Coastguard Worker         fMin((UCHAR)(offset + hUniDrcConfig->drcCoefficientsUniDrcCountV1),
1576*e5436536SAndroid Build Coastguard Worker              (UCHAR)2);
1577*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV1; i++) {
1578*e5436536SAndroid Build Coastguard Worker       DRC_COEFFICIENTS_UNI_DRC tmpCoef;
1579*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC));
1580*e5436536SAndroid Build Coastguard Worker       err = _readDrcCoefficientsUniDrc(hBs, 1, &tmpCoef);
1581*e5436536SAndroid Build Coastguard Worker       if (err) return err;
1582*e5436536SAndroid Build Coastguard Worker       if ((offset + i) >= 2) continue;
1583*e5436536SAndroid Build Coastguard Worker       if (!diff)
1584*e5436536SAndroid Build Coastguard Worker         diff |= (FDKmemcmp(&tmpCoef,
1585*e5436536SAndroid Build Coastguard Worker                            &(hUniDrcConfig->drcCoefficientsUniDrc[offset + i]),
1586*e5436536SAndroid Build Coastguard Worker                            sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0);
1587*e5436536SAndroid Build Coastguard Worker       hUniDrcConfig->drcCoefficientsUniDrc[offset + i] = tmpCoef;
1588*e5436536SAndroid Build Coastguard Worker     }
1589*e5436536SAndroid Build Coastguard Worker 
1590*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1,
1591*e5436536SAndroid Build Coastguard Worker                         FDKreadBits(hBs, 6));
1592*e5436536SAndroid Build Coastguard Worker     offset = hUniDrcConfig->drcInstructionsUniDrcCount;
1593*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->drcInstructionsUniDrcCount =
1594*e5436536SAndroid Build Coastguard Worker         fMin((UCHAR)(offset + hUniDrcConfig->drcInstructionsUniDrcCountV1),
1595*e5436536SAndroid Build Coastguard Worker              (UCHAR)12);
1596*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) {
1597*e5436536SAndroid Build Coastguard Worker       DRC_INSTRUCTIONS_UNI_DRC tmpInst;
1598*e5436536SAndroid Build Coastguard Worker       FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC));
1599*e5436536SAndroid Build Coastguard Worker       err = _readDrcInstructionsUniDrc(hBs, 1, hUniDrcConfig, &tmpInst);
1600*e5436536SAndroid Build Coastguard Worker       if (err) return err;
1601*e5436536SAndroid Build Coastguard Worker       if ((offset + i) >= 12) continue;
1602*e5436536SAndroid Build Coastguard Worker       if (!diff)
1603*e5436536SAndroid Build Coastguard Worker         diff |= (FDKmemcmp(&tmpInst,
1604*e5436536SAndroid Build Coastguard Worker                            &(hUniDrcConfig->drcInstructionsUniDrc[offset + i]),
1605*e5436536SAndroid Build Coastguard Worker                            sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0);
1606*e5436536SAndroid Build Coastguard Worker       hUniDrcConfig->drcInstructionsUniDrc[offset + i] = tmpInst;
1607*e5436536SAndroid Build Coastguard Worker     }
1608*e5436536SAndroid Build Coastguard Worker   } else {
1609*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, 0);
1610*e5436536SAndroid Build Coastguard Worker     diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, 0);
1611*e5436536SAndroid Build Coastguard Worker   }
1612*e5436536SAndroid Build Coastguard Worker 
1613*e5436536SAndroid Build Coastguard Worker   loudEqInstructionsPresent = FDKreadBits(hBs, 1);
1614*e5436536SAndroid Build Coastguard Worker   if (loudEqInstructionsPresent == 1) {
1615*e5436536SAndroid Build Coastguard Worker     loudEqInstructionsCount = FDKreadBits(hBs, 4);
1616*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < loudEqInstructionsCount; i++) {
1617*e5436536SAndroid Build Coastguard Worker       _skipLoudEqInstructions(hBs);
1618*e5436536SAndroid Build Coastguard Worker     }
1619*e5436536SAndroid Build Coastguard Worker   }
1620*e5436536SAndroid Build Coastguard Worker 
1621*e5436536SAndroid Build Coastguard Worker   eqPresent = FDKreadBits(hBs, 1);
1622*e5436536SAndroid Build Coastguard Worker   if (eqPresent == 1) {
1623*e5436536SAndroid Build Coastguard Worker     _skipEqCoefficients(hBs);
1624*e5436536SAndroid Build Coastguard Worker     eqInstructionsCount = FDKreadBits(hBs, 4);
1625*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < eqInstructionsCount; i++) {
1626*e5436536SAndroid Build Coastguard Worker       _skipEqInstructions(hBs, hUniDrcConfig);
1627*e5436536SAndroid Build Coastguard Worker     }
1628*e5436536SAndroid Build Coastguard Worker   }
1629*e5436536SAndroid Build Coastguard Worker 
1630*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->diff = diff;
1631*e5436536SAndroid Build Coastguard Worker 
1632*e5436536SAndroid Build Coastguard Worker   return err;
1633*e5436536SAndroid Build Coastguard Worker }
1634*e5436536SAndroid Build Coastguard Worker 
_readUniDrcConfigExtension(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig)1635*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readUniDrcConfigExtension(
1636*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
1637*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1638*e5436536SAndroid Build Coastguard Worker   int k, bitSizeLen, extSizeBits, bitSize;
1639*e5436536SAndroid Build Coastguard Worker   INT nBitsRemaining;
1640*e5436536SAndroid Build Coastguard Worker   UNI_DRC_CONFIG_EXTENSION* pExt = &(hUniDrcConfig->uniDrcConfigExt);
1641*e5436536SAndroid Build Coastguard Worker 
1642*e5436536SAndroid Build Coastguard Worker   k = 0;
1643*e5436536SAndroid Build Coastguard Worker   pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4);
1644*e5436536SAndroid Build Coastguard Worker   while (pExt->uniDrcConfigExtType[k] != UNIDRCCONFEXT_TERM) {
1645*e5436536SAndroid Build Coastguard Worker     if (k >= (8 - 1)) return DE_MEMORY_ERROR;
1646*e5436536SAndroid Build Coastguard Worker     bitSizeLen = FDKreadBits(hBs, 4);
1647*e5436536SAndroid Build Coastguard Worker     extSizeBits = bitSizeLen + 4;
1648*e5436536SAndroid Build Coastguard Worker 
1649*e5436536SAndroid Build Coastguard Worker     bitSize = FDKreadBits(hBs, extSizeBits);
1650*e5436536SAndroid Build Coastguard Worker     pExt->extBitSize[k] = bitSize + 1;
1651*e5436536SAndroid Build Coastguard Worker     nBitsRemaining = (INT)FDKgetValidBits(hBs);
1652*e5436536SAndroid Build Coastguard Worker 
1653*e5436536SAndroid Build Coastguard Worker     switch (pExt->uniDrcConfigExtType[k]) {
1654*e5436536SAndroid Build Coastguard Worker       case UNIDRCCONFEXT_V1:
1655*e5436536SAndroid Build Coastguard Worker         err = _readDrcExtensionV1(hBs, hUniDrcConfig);
1656*e5436536SAndroid Build Coastguard Worker         if (err) return err;
1657*e5436536SAndroid Build Coastguard Worker         if (nBitsRemaining !=
1658*e5436536SAndroid Build Coastguard Worker             ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs)))
1659*e5436536SAndroid Build Coastguard Worker           return DE_NOT_OK;
1660*e5436536SAndroid Build Coastguard Worker         break;
1661*e5436536SAndroid Build Coastguard Worker       case UNIDRCCONFEXT_PARAM_DRC:
1662*e5436536SAndroid Build Coastguard Worker       /* add future extensions here */
1663*e5436536SAndroid Build Coastguard Worker       default:
1664*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, pExt->extBitSize[k]);
1665*e5436536SAndroid Build Coastguard Worker         break;
1666*e5436536SAndroid Build Coastguard Worker     }
1667*e5436536SAndroid Build Coastguard Worker     k++;
1668*e5436536SAndroid Build Coastguard Worker     pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4);
1669*e5436536SAndroid Build Coastguard Worker   }
1670*e5436536SAndroid Build Coastguard Worker 
1671*e5436536SAndroid Build Coastguard Worker   return err;
1672*e5436536SAndroid Build Coastguard Worker }
1673*e5436536SAndroid Build Coastguard Worker 
1674*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs,HANDLE_UNI_DRC_CONFIG hUniDrcConfig)1675*e5436536SAndroid Build Coastguard Worker drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs,
1676*e5436536SAndroid Build Coastguard Worker                         HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
1677*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1678*e5436536SAndroid Build Coastguard Worker   int i, diff = 0;
1679*e5436536SAndroid Build Coastguard Worker   int drcDescriptionBasicPresent, drcCoefficientsBasicCount,
1680*e5436536SAndroid Build Coastguard Worker       drcInstructionsBasicCount;
1681*e5436536SAndroid Build Coastguard Worker   CHANNEL_LAYOUT tmpChan;
1682*e5436536SAndroid Build Coastguard Worker   FDKmemclear(&tmpChan, sizeof(CHANNEL_LAYOUT));
1683*e5436536SAndroid Build Coastguard Worker   if (hUniDrcConfig == NULL) return DE_NOT_OK;
1684*e5436536SAndroid Build Coastguard Worker 
1685*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hUniDrcConfig->sampleRatePresent, FDKreadBits(hBs, 1));
1686*e5436536SAndroid Build Coastguard Worker 
1687*e5436536SAndroid Build Coastguard Worker   if (hUniDrcConfig->sampleRatePresent == 1) {
1688*e5436536SAndroid Build Coastguard Worker     diff |=
1689*e5436536SAndroid Build Coastguard Worker         _compAssign(&hUniDrcConfig->sampleRate, FDKreadBits(hBs, 18) + 1000);
1690*e5436536SAndroid Build Coastguard Worker   }
1691*e5436536SAndroid Build Coastguard Worker 
1692*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV0,
1693*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 7));
1694*e5436536SAndroid Build Coastguard Worker 
1695*e5436536SAndroid Build Coastguard Worker   drcDescriptionBasicPresent = FDKreadBits(hBs, 1);
1696*e5436536SAndroid Build Coastguard Worker   if (drcDescriptionBasicPresent == 1) {
1697*e5436536SAndroid Build Coastguard Worker     drcCoefficientsBasicCount = FDKreadBits(hBs, 3);
1698*e5436536SAndroid Build Coastguard Worker     drcInstructionsBasicCount = FDKreadBits(hBs, 4);
1699*e5436536SAndroid Build Coastguard Worker   } else {
1700*e5436536SAndroid Build Coastguard Worker     drcCoefficientsBasicCount = 0;
1701*e5436536SAndroid Build Coastguard Worker     drcInstructionsBasicCount = 0;
1702*e5436536SAndroid Build Coastguard Worker   }
1703*e5436536SAndroid Build Coastguard Worker 
1704*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV0,
1705*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 3));
1706*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV0,
1707*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 6));
1708*e5436536SAndroid Build Coastguard Worker 
1709*e5436536SAndroid Build Coastguard Worker   err = _readChannelLayout(hBs, &tmpChan);
1710*e5436536SAndroid Build Coastguard Worker   if (err) return err;
1711*e5436536SAndroid Build Coastguard Worker 
1712*e5436536SAndroid Build Coastguard Worker   if (!diff)
1713*e5436536SAndroid Build Coastguard Worker     diff |= (FDKmemcmp(&tmpChan, &hUniDrcConfig->channelLayout,
1714*e5436536SAndroid Build Coastguard Worker                        sizeof(CHANNEL_LAYOUT)) != 0);
1715*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->channelLayout = tmpChan;
1716*e5436536SAndroid Build Coastguard Worker 
1717*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->downmixInstructionsCount =
1718*e5436536SAndroid Build Coastguard Worker       fMin(hUniDrcConfig->downmixInstructionsCountV0, (UCHAR)6);
1719*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV0; i++) {
1720*e5436536SAndroid Build Coastguard Worker     DOWNMIX_INSTRUCTIONS tmpDown;
1721*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS));
1722*e5436536SAndroid Build Coastguard Worker     err = _readDownmixInstructions(hBs, 0, &hUniDrcConfig->channelLayout,
1723*e5436536SAndroid Build Coastguard Worker                                    &tmpDown);
1724*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1725*e5436536SAndroid Build Coastguard Worker     if (i >= 6) continue;
1726*e5436536SAndroid Build Coastguard Worker     if (!diff)
1727*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpDown, &(hUniDrcConfig->downmixInstructions[i]),
1728*e5436536SAndroid Build Coastguard Worker                          sizeof(DOWNMIX_INSTRUCTIONS)) != 0);
1729*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->downmixInstructions[i] = tmpDown;
1730*e5436536SAndroid Build Coastguard Worker   }
1731*e5436536SAndroid Build Coastguard Worker 
1732*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < drcCoefficientsBasicCount; i++) {
1733*e5436536SAndroid Build Coastguard Worker     _skipDrcCoefficientsBasic(hBs);
1734*e5436536SAndroid Build Coastguard Worker   }
1735*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < drcInstructionsBasicCount; i++) {
1736*e5436536SAndroid Build Coastguard Worker     _skipDrcInstructionsBasic(hBs);
1737*e5436536SAndroid Build Coastguard Worker   }
1738*e5436536SAndroid Build Coastguard Worker 
1739*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->drcCoefficientsUniDrcCount =
1740*e5436536SAndroid Build Coastguard Worker       fMin(hUniDrcConfig->drcCoefficientsUniDrcCountV0, (UCHAR)2);
1741*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV0; i++) {
1742*e5436536SAndroid Build Coastguard Worker     DRC_COEFFICIENTS_UNI_DRC tmpCoef;
1743*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC));
1744*e5436536SAndroid Build Coastguard Worker     err = _readDrcCoefficientsUniDrc(hBs, 0, &tmpCoef);
1745*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1746*e5436536SAndroid Build Coastguard Worker     if (i >= 2) continue;
1747*e5436536SAndroid Build Coastguard Worker     if (!diff)
1748*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpCoef, &(hUniDrcConfig->drcCoefficientsUniDrc[i]),
1749*e5436536SAndroid Build Coastguard Worker                          sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0);
1750*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->drcCoefficientsUniDrc[i] = tmpCoef;
1751*e5436536SAndroid Build Coastguard Worker   }
1752*e5436536SAndroid Build Coastguard Worker 
1753*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->drcInstructionsUniDrcCount =
1754*e5436536SAndroid Build Coastguard Worker       fMin(hUniDrcConfig->drcInstructionsUniDrcCountV0, (UCHAR)12);
1755*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCountV0; i++) {
1756*e5436536SAndroid Build Coastguard Worker     DRC_INSTRUCTIONS_UNI_DRC tmpInst;
1757*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC));
1758*e5436536SAndroid Build Coastguard Worker     err = _readDrcInstructionsUniDrc(hBs, 0, hUniDrcConfig, &tmpInst);
1759*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1760*e5436536SAndroid Build Coastguard Worker     if (i >= 12) continue;
1761*e5436536SAndroid Build Coastguard Worker     if (!diff)
1762*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpInst, &(hUniDrcConfig->drcInstructionsUniDrc[i]),
1763*e5436536SAndroid Build Coastguard Worker                          sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0);
1764*e5436536SAndroid Build Coastguard Worker     hUniDrcConfig->drcInstructionsUniDrc[i] = tmpInst;
1765*e5436536SAndroid Build Coastguard Worker   }
1766*e5436536SAndroid Build Coastguard Worker 
1767*e5436536SAndroid Build Coastguard Worker   diff |=
1768*e5436536SAndroid Build Coastguard Worker       _compAssign(&hUniDrcConfig->uniDrcConfigExtPresent, FDKreadBits(hBs, 1));
1769*e5436536SAndroid Build Coastguard Worker   hUniDrcConfig->diff = diff;
1770*e5436536SAndroid Build Coastguard Worker 
1771*e5436536SAndroid Build Coastguard Worker   if (hUniDrcConfig->uniDrcConfigExtPresent == 1) {
1772*e5436536SAndroid Build Coastguard Worker     err = _readUniDrcConfigExtension(hBs, hUniDrcConfig);
1773*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1774*e5436536SAndroid Build Coastguard Worker   }
1775*e5436536SAndroid Build Coastguard Worker 
1776*e5436536SAndroid Build Coastguard Worker   return err;
1777*e5436536SAndroid Build Coastguard Worker }
1778*e5436536SAndroid Build Coastguard Worker 
1779*e5436536SAndroid Build Coastguard Worker /*******************/
1780*e5436536SAndroid Build Coastguard Worker /* loudnessInfoSet */
1781*e5436536SAndroid Build Coastguard Worker /*******************/
1782*e5436536SAndroid Build Coastguard Worker 
_decodeMethodValue(HANDLE_FDK_BITSTREAM hBs,const UCHAR methodDefinition,FIXP_DBL * methodValue,INT isBox)1783*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _decodeMethodValue(HANDLE_FDK_BITSTREAM hBs,
1784*e5436536SAndroid Build Coastguard Worker                                     const UCHAR methodDefinition,
1785*e5436536SAndroid Build Coastguard Worker                                     FIXP_DBL* methodValue, INT isBox) {
1786*e5436536SAndroid Build Coastguard Worker   int tmp;
1787*e5436536SAndroid Build Coastguard Worker   FIXP_DBL val;
1788*e5436536SAndroid Build Coastguard Worker   switch (methodDefinition) {
1789*e5436536SAndroid Build Coastguard Worker     case MD_UNKNOWN_OTHER:
1790*e5436536SAndroid Build Coastguard Worker     case MD_PROGRAM_LOUDNESS:
1791*e5436536SAndroid Build Coastguard Worker     case MD_ANCHOR_LOUDNESS:
1792*e5436536SAndroid Build Coastguard Worker     case MD_MAX_OF_LOUDNESS_RANGE:
1793*e5436536SAndroid Build Coastguard Worker     case MD_MOMENTARY_LOUDNESS_MAX:
1794*e5436536SAndroid Build Coastguard Worker     case MD_SHORT_TERM_LOUDNESS_MAX:
1795*e5436536SAndroid Build Coastguard Worker       tmp = FDKreadBits(hBs, 8);
1796*e5436536SAndroid Build Coastguard Worker       val = FL2FXCONST_DBL(-57.75f / (float)(1 << 7)) +
1797*e5436536SAndroid Build Coastguard Worker             (FIXP_DBL)(
1798*e5436536SAndroid Build Coastguard Worker                 tmp << (DFRACT_BITS - 1 - 2 - 7)); /* -57.75 + tmp * 0.25; */
1799*e5436536SAndroid Build Coastguard Worker       break;
1800*e5436536SAndroid Build Coastguard Worker     case MD_LOUDNESS_RANGE:
1801*e5436536SAndroid Build Coastguard Worker       tmp = FDKreadBits(hBs, 8);
1802*e5436536SAndroid Build Coastguard Worker       if (tmp == 0)
1803*e5436536SAndroid Build Coastguard Worker         val = (FIXP_DBL)0;
1804*e5436536SAndroid Build Coastguard Worker       else if (tmp <= 128)
1805*e5436536SAndroid Build Coastguard Worker         val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 2 - 7)); /* tmp * 0.25; */
1806*e5436536SAndroid Build Coastguard Worker       else if (tmp <= 204) {
1807*e5436536SAndroid Build Coastguard Worker         val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 1 - 7)) -
1808*e5436536SAndroid Build Coastguard Worker               FL2FXCONST_DBL(32.0f / (float)(1 << 7)); /* 0.5 * tmp - 32.0f; */
1809*e5436536SAndroid Build Coastguard Worker       } else {
1810*e5436536SAndroid Build Coastguard Worker         /* downscale by 1 more bit to prevent overflow at intermediate result */
1811*e5436536SAndroid Build Coastguard Worker         val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 8)) -
1812*e5436536SAndroid Build Coastguard Worker               FL2FXCONST_DBL(134.0f / (float)(1 << 8)); /* tmp - 134.0; */
1813*e5436536SAndroid Build Coastguard Worker         val <<= 1;
1814*e5436536SAndroid Build Coastguard Worker       }
1815*e5436536SAndroid Build Coastguard Worker       break;
1816*e5436536SAndroid Build Coastguard Worker     case MD_MIXING_LEVEL:
1817*e5436536SAndroid Build Coastguard Worker       tmp = FDKreadBits(hBs, isBox ? 8 : 5);
1818*e5436536SAndroid Build Coastguard Worker       val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)) +
1819*e5436536SAndroid Build Coastguard Worker             FL2FXCONST_DBL(80.0f / (float)(1 << 7)); /* tmp + 80.0; */
1820*e5436536SAndroid Build Coastguard Worker       break;
1821*e5436536SAndroid Build Coastguard Worker     case MD_ROOM_TYPE:
1822*e5436536SAndroid Build Coastguard Worker       tmp = FDKreadBits(hBs, isBox ? 8 : 2);
1823*e5436536SAndroid Build Coastguard Worker       val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)); /* tmp; */
1824*e5436536SAndroid Build Coastguard Worker       break;
1825*e5436536SAndroid Build Coastguard Worker     case MD_SHORT_TERM_LOUDNESS:
1826*e5436536SAndroid Build Coastguard Worker       tmp = FDKreadBits(hBs, 8);
1827*e5436536SAndroid Build Coastguard Worker       val = FL2FXCONST_DBL(-116.0f / (float)(1 << 7)) +
1828*e5436536SAndroid Build Coastguard Worker             (FIXP_DBL)(
1829*e5436536SAndroid Build Coastguard Worker                 tmp << (DFRACT_BITS - 1 - 1 - 7)); /* -116.0 + tmp * 0.5; */
1830*e5436536SAndroid Build Coastguard Worker       break;
1831*e5436536SAndroid Build Coastguard Worker     default:
1832*e5436536SAndroid Build Coastguard Worker       return DE_NOT_OK; /* invalid methodDefinition value */
1833*e5436536SAndroid Build Coastguard Worker   }
1834*e5436536SAndroid Build Coastguard Worker   *methodValue = val;
1835*e5436536SAndroid Build Coastguard Worker   return DE_OK;
1836*e5436536SAndroid Build Coastguard Worker }
1837*e5436536SAndroid Build Coastguard Worker 
_readLoudnessMeasurement(HANDLE_FDK_BITSTREAM hBs,LOUDNESS_MEASUREMENT * pMeas)1838*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readLoudnessMeasurement(HANDLE_FDK_BITSTREAM hBs,
1839*e5436536SAndroid Build Coastguard Worker                                           LOUDNESS_MEASUREMENT* pMeas) {
1840*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1841*e5436536SAndroid Build Coastguard Worker 
1842*e5436536SAndroid Build Coastguard Worker   pMeas->methodDefinition = FDKreadBits(hBs, 4);
1843*e5436536SAndroid Build Coastguard Worker   err =
1844*e5436536SAndroid Build Coastguard Worker       _decodeMethodValue(hBs, pMeas->methodDefinition, &pMeas->methodValue, 0);
1845*e5436536SAndroid Build Coastguard Worker   if (err) return err;
1846*e5436536SAndroid Build Coastguard Worker   pMeas->measurementSystem = FDKreadBits(hBs, 4);
1847*e5436536SAndroid Build Coastguard Worker   pMeas->reliability = FDKreadBits(hBs, 2);
1848*e5436536SAndroid Build Coastguard Worker 
1849*e5436536SAndroid Build Coastguard Worker   return err;
1850*e5436536SAndroid Build Coastguard Worker }
1851*e5436536SAndroid Build Coastguard Worker 
_readLoudnessInfo(HANDLE_FDK_BITSTREAM hBs,const int version,LOUDNESS_INFO * loudnessInfo)1852*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readLoudnessInfo(HANDLE_FDK_BITSTREAM hBs, const int version,
1853*e5436536SAndroid Build Coastguard Worker                                    LOUDNESS_INFO* loudnessInfo) {
1854*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1855*e5436536SAndroid Build Coastguard Worker   int bsSamplePeakLevel, bsTruePeakLevel, i;
1856*e5436536SAndroid Build Coastguard Worker   int measurementCount;
1857*e5436536SAndroid Build Coastguard Worker 
1858*e5436536SAndroid Build Coastguard Worker   loudnessInfo->drcSetId = FDKreadBits(hBs, 6);
1859*e5436536SAndroid Build Coastguard Worker   if (version >= 1) {
1860*e5436536SAndroid Build Coastguard Worker     loudnessInfo->eqSetId = FDKreadBits(hBs, 6);
1861*e5436536SAndroid Build Coastguard Worker   } else {
1862*e5436536SAndroid Build Coastguard Worker     loudnessInfo->eqSetId = 0;
1863*e5436536SAndroid Build Coastguard Worker   }
1864*e5436536SAndroid Build Coastguard Worker   loudnessInfo->downmixId = FDKreadBits(hBs, 7);
1865*e5436536SAndroid Build Coastguard Worker 
1866*e5436536SAndroid Build Coastguard Worker   loudnessInfo->samplePeakLevelPresent = FDKreadBits(hBs, 1);
1867*e5436536SAndroid Build Coastguard Worker   if (loudnessInfo->samplePeakLevelPresent) {
1868*e5436536SAndroid Build Coastguard Worker     bsSamplePeakLevel = FDKreadBits(hBs, 12);
1869*e5436536SAndroid Build Coastguard Worker     if (bsSamplePeakLevel == 0) {
1870*e5436536SAndroid Build Coastguard Worker       loudnessInfo->samplePeakLevelPresent = 0;
1871*e5436536SAndroid Build Coastguard Worker       loudnessInfo->samplePeakLevel = (FIXP_DBL)0;
1872*e5436536SAndroid Build Coastguard Worker     } else { /* 20.0 - bsSamplePeakLevel * 0.03125; */
1873*e5436536SAndroid Build Coastguard Worker       loudnessInfo->samplePeakLevel =
1874*e5436536SAndroid Build Coastguard Worker           FL2FXCONST_DBL(20.0f / (float)(1 << 7)) -
1875*e5436536SAndroid Build Coastguard Worker           (FIXP_DBL)(bsSamplePeakLevel << (DFRACT_BITS - 1 - 5 - 7));
1876*e5436536SAndroid Build Coastguard Worker     }
1877*e5436536SAndroid Build Coastguard Worker   }
1878*e5436536SAndroid Build Coastguard Worker 
1879*e5436536SAndroid Build Coastguard Worker   loudnessInfo->truePeakLevelPresent = FDKreadBits(hBs, 1);
1880*e5436536SAndroid Build Coastguard Worker   if (loudnessInfo->truePeakLevelPresent) {
1881*e5436536SAndroid Build Coastguard Worker     bsTruePeakLevel = FDKreadBits(hBs, 12);
1882*e5436536SAndroid Build Coastguard Worker     if (bsTruePeakLevel == 0) {
1883*e5436536SAndroid Build Coastguard Worker       loudnessInfo->truePeakLevelPresent = 0;
1884*e5436536SAndroid Build Coastguard Worker       loudnessInfo->truePeakLevel = (FIXP_DBL)0;
1885*e5436536SAndroid Build Coastguard Worker     } else {
1886*e5436536SAndroid Build Coastguard Worker       loudnessInfo->truePeakLevel =
1887*e5436536SAndroid Build Coastguard Worker           FL2FXCONST_DBL(20.0f / (float)(1 << 7)) -
1888*e5436536SAndroid Build Coastguard Worker           (FIXP_DBL)(bsTruePeakLevel << (DFRACT_BITS - 1 - 5 - 7));
1889*e5436536SAndroid Build Coastguard Worker     }
1890*e5436536SAndroid Build Coastguard Worker     loudnessInfo->truePeakLevelMeasurementSystem = FDKreadBits(hBs, 4);
1891*e5436536SAndroid Build Coastguard Worker     loudnessInfo->truePeakLevelReliability = FDKreadBits(hBs, 2);
1892*e5436536SAndroid Build Coastguard Worker   }
1893*e5436536SAndroid Build Coastguard Worker 
1894*e5436536SAndroid Build Coastguard Worker   measurementCount = FDKreadBits(hBs, 4);
1895*e5436536SAndroid Build Coastguard Worker   loudnessInfo->measurementCount = fMin(measurementCount, 8);
1896*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < measurementCount; i++) {
1897*e5436536SAndroid Build Coastguard Worker     LOUDNESS_MEASUREMENT tmpMeas;
1898*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpMeas, sizeof(LOUDNESS_MEASUREMENT));
1899*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessMeasurement(hBs, &tmpMeas);
1900*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1901*e5436536SAndroid Build Coastguard Worker     if (i >= 8) continue;
1902*e5436536SAndroid Build Coastguard Worker     loudnessInfo->loudnessMeasurement[i] = tmpMeas;
1903*e5436536SAndroid Build Coastguard Worker   }
1904*e5436536SAndroid Build Coastguard Worker 
1905*e5436536SAndroid Build Coastguard Worker   return err;
1906*e5436536SAndroid Build Coastguard Worker }
1907*e5436536SAndroid Build Coastguard Worker 
_readLoudnessInfoSetExtEq(HANDLE_FDK_BITSTREAM hBs,HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet)1908*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readLoudnessInfoSetExtEq(
1909*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
1910*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1911*e5436536SAndroid Build Coastguard Worker   int i, offset;
1912*e5436536SAndroid Build Coastguard Worker   int diff = hLoudnessInfoSet->diff;
1913*e5436536SAndroid Build Coastguard Worker 
1914*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV1,
1915*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 6));
1916*e5436536SAndroid Build Coastguard Worker   diff |=
1917*e5436536SAndroid Build Coastguard Worker       _compAssign(&hLoudnessInfoSet->loudnessInfoCountV1, FDKreadBits(hBs, 6));
1918*e5436536SAndroid Build Coastguard Worker 
1919*e5436536SAndroid Build Coastguard Worker   offset = hLoudnessInfoSet->loudnessInfoAlbumCountV0;
1920*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->loudnessInfoAlbumCount = fMin(
1921*e5436536SAndroid Build Coastguard Worker       (UCHAR)(offset + hLoudnessInfoSet->loudnessInfoAlbumCountV1), (UCHAR)12);
1922*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV1; i++) {
1923*e5436536SAndroid Build Coastguard Worker     LOUDNESS_INFO tmpLoud;
1924*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
1925*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessInfo(hBs, 1, &tmpLoud);
1926*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1927*e5436536SAndroid Build Coastguard Worker     if ((offset + i) >= 12) continue;
1928*e5436536SAndroid Build Coastguard Worker     if (!diff)
1929*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpLoud,
1930*e5436536SAndroid Build Coastguard Worker                          &(hLoudnessInfoSet->loudnessInfoAlbum[offset + i]),
1931*e5436536SAndroid Build Coastguard Worker                          sizeof(LOUDNESS_INFO)) != 0);
1932*e5436536SAndroid Build Coastguard Worker     hLoudnessInfoSet->loudnessInfoAlbum[offset + i] = tmpLoud;
1933*e5436536SAndroid Build Coastguard Worker   }
1934*e5436536SAndroid Build Coastguard Worker 
1935*e5436536SAndroid Build Coastguard Worker   offset = hLoudnessInfoSet->loudnessInfoCountV0;
1936*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->loudnessInfoCount =
1937*e5436536SAndroid Build Coastguard Worker       fMin((UCHAR)(offset + hLoudnessInfoSet->loudnessInfoCountV1), (UCHAR)12);
1938*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV1; i++) {
1939*e5436536SAndroid Build Coastguard Worker     LOUDNESS_INFO tmpLoud;
1940*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
1941*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessInfo(hBs, 1, &tmpLoud);
1942*e5436536SAndroid Build Coastguard Worker     if (err) return err;
1943*e5436536SAndroid Build Coastguard Worker     if ((offset + i) >= 12) continue;
1944*e5436536SAndroid Build Coastguard Worker     if (!diff)
1945*e5436536SAndroid Build Coastguard Worker       diff |=
1946*e5436536SAndroid Build Coastguard Worker           (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[offset + i]),
1947*e5436536SAndroid Build Coastguard Worker                      sizeof(LOUDNESS_INFO)) != 0);
1948*e5436536SAndroid Build Coastguard Worker     hLoudnessInfoSet->loudnessInfo[offset + i] = tmpLoud;
1949*e5436536SAndroid Build Coastguard Worker   }
1950*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->diff = diff;
1951*e5436536SAndroid Build Coastguard Worker   return err;
1952*e5436536SAndroid Build Coastguard Worker }
1953*e5436536SAndroid Build Coastguard Worker 
_readLoudnessInfoSetExtension(HANDLE_FDK_BITSTREAM hBs,HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet)1954*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _readLoudnessInfoSetExtension(
1955*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
1956*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1957*e5436536SAndroid Build Coastguard Worker   int k, bitSizeLen, extSizeBits, bitSize;
1958*e5436536SAndroid Build Coastguard Worker   INT nBitsRemaining;
1959*e5436536SAndroid Build Coastguard Worker   LOUDNESS_INFO_SET_EXTENSION* pExt = &(hLoudnessInfoSet->loudnessInfoSetExt);
1960*e5436536SAndroid Build Coastguard Worker 
1961*e5436536SAndroid Build Coastguard Worker   k = 0;
1962*e5436536SAndroid Build Coastguard Worker   pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4);
1963*e5436536SAndroid Build Coastguard Worker   while (pExt->loudnessInfoSetExtType[k] != UNIDRCLOUDEXT_TERM) {
1964*e5436536SAndroid Build Coastguard Worker     if (k >= (8 - 1)) return DE_MEMORY_ERROR;
1965*e5436536SAndroid Build Coastguard Worker     bitSizeLen = FDKreadBits(hBs, 4);
1966*e5436536SAndroid Build Coastguard Worker     extSizeBits = bitSizeLen + 4;
1967*e5436536SAndroid Build Coastguard Worker 
1968*e5436536SAndroid Build Coastguard Worker     bitSize = FDKreadBits(hBs, extSizeBits);
1969*e5436536SAndroid Build Coastguard Worker     pExt->extBitSize[k] = bitSize + 1;
1970*e5436536SAndroid Build Coastguard Worker     nBitsRemaining = (INT)FDKgetValidBits(hBs);
1971*e5436536SAndroid Build Coastguard Worker 
1972*e5436536SAndroid Build Coastguard Worker     switch (pExt->loudnessInfoSetExtType[k]) {
1973*e5436536SAndroid Build Coastguard Worker       case UNIDRCLOUDEXT_EQ:
1974*e5436536SAndroid Build Coastguard Worker         err = _readLoudnessInfoSetExtEq(hBs, hLoudnessInfoSet);
1975*e5436536SAndroid Build Coastguard Worker         if (err) return err;
1976*e5436536SAndroid Build Coastguard Worker         if (nBitsRemaining !=
1977*e5436536SAndroid Build Coastguard Worker             ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs)))
1978*e5436536SAndroid Build Coastguard Worker           return DE_NOT_OK;
1979*e5436536SAndroid Build Coastguard Worker         break;
1980*e5436536SAndroid Build Coastguard Worker       /* add future extensions here */
1981*e5436536SAndroid Build Coastguard Worker       default:
1982*e5436536SAndroid Build Coastguard Worker         FDKpushFor(hBs, pExt->extBitSize[k]);
1983*e5436536SAndroid Build Coastguard Worker         break;
1984*e5436536SAndroid Build Coastguard Worker     }
1985*e5436536SAndroid Build Coastguard Worker     k++;
1986*e5436536SAndroid Build Coastguard Worker     pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4);
1987*e5436536SAndroid Build Coastguard Worker   }
1988*e5436536SAndroid Build Coastguard Worker 
1989*e5436536SAndroid Build Coastguard Worker   return err;
1990*e5436536SAndroid Build Coastguard Worker }
1991*e5436536SAndroid Build Coastguard Worker 
1992*e5436536SAndroid Build Coastguard Worker /* Parser for loundessInfoSet() */
1993*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs,HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet)1994*e5436536SAndroid Build Coastguard Worker drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs,
1995*e5436536SAndroid Build Coastguard Worker                            HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
1996*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
1997*e5436536SAndroid Build Coastguard Worker   int i, diff = 0;
1998*e5436536SAndroid Build Coastguard Worker   if (hLoudnessInfoSet == NULL) return DE_NOT_OK;
1999*e5436536SAndroid Build Coastguard Worker 
2000*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV0,
2001*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 6));
2002*e5436536SAndroid Build Coastguard Worker   diff |=
2003*e5436536SAndroid Build Coastguard Worker       _compAssign(&hLoudnessInfoSet->loudnessInfoCountV0, FDKreadBits(hBs, 6));
2004*e5436536SAndroid Build Coastguard Worker 
2005*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->loudnessInfoAlbumCount =
2006*e5436536SAndroid Build Coastguard Worker       fMin(hLoudnessInfoSet->loudnessInfoAlbumCountV0, (UCHAR)12);
2007*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV0; i++) {
2008*e5436536SAndroid Build Coastguard Worker     LOUDNESS_INFO tmpLoud;
2009*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
2010*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessInfo(hBs, 0, &tmpLoud);
2011*e5436536SAndroid Build Coastguard Worker     if (err) return err;
2012*e5436536SAndroid Build Coastguard Worker     if (i >= 12) continue;
2013*e5436536SAndroid Build Coastguard Worker     if (!diff)
2014*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfoAlbum[i]),
2015*e5436536SAndroid Build Coastguard Worker                          sizeof(LOUDNESS_INFO)) != 0);
2016*e5436536SAndroid Build Coastguard Worker     hLoudnessInfoSet->loudnessInfoAlbum[i] = tmpLoud;
2017*e5436536SAndroid Build Coastguard Worker   }
2018*e5436536SAndroid Build Coastguard Worker 
2019*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->loudnessInfoCount =
2020*e5436536SAndroid Build Coastguard Worker       fMin(hLoudnessInfoSet->loudnessInfoCountV0, (UCHAR)12);
2021*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV0; i++) {
2022*e5436536SAndroid Build Coastguard Worker     LOUDNESS_INFO tmpLoud;
2023*e5436536SAndroid Build Coastguard Worker     FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
2024*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessInfo(hBs, 0, &tmpLoud);
2025*e5436536SAndroid Build Coastguard Worker     if (err) return err;
2026*e5436536SAndroid Build Coastguard Worker     if (i >= 12) continue;
2027*e5436536SAndroid Build Coastguard Worker     if (!diff)
2028*e5436536SAndroid Build Coastguard Worker       diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[i]),
2029*e5436536SAndroid Build Coastguard Worker                          sizeof(LOUDNESS_INFO)) != 0);
2030*e5436536SAndroid Build Coastguard Worker     hLoudnessInfoSet->loudnessInfo[i] = tmpLoud;
2031*e5436536SAndroid Build Coastguard Worker   }
2032*e5436536SAndroid Build Coastguard Worker 
2033*e5436536SAndroid Build Coastguard Worker   diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoSetExtPresent,
2034*e5436536SAndroid Build Coastguard Worker                       FDKreadBits(hBs, 1));
2035*e5436536SAndroid Build Coastguard Worker   hLoudnessInfoSet->diff = diff;
2036*e5436536SAndroid Build Coastguard Worker 
2037*e5436536SAndroid Build Coastguard Worker   if (hLoudnessInfoSet->loudnessInfoSetExtPresent) {
2038*e5436536SAndroid Build Coastguard Worker     err = _readLoudnessInfoSetExtension(hBs, hLoudnessInfoSet);
2039*e5436536SAndroid Build Coastguard Worker     if (err) return err;
2040*e5436536SAndroid Build Coastguard Worker   }
2041*e5436536SAndroid Build Coastguard Worker 
2042*e5436536SAndroid Build Coastguard Worker   return err;
2043*e5436536SAndroid Build Coastguard Worker }
2044