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 - 2023 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 /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Christian Griebel
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: Dynamic range control (DRC) decoder tool for AAC
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "aacdec_drc.h"
104*e5436536SAndroid Build Coastguard Worker
105*e5436536SAndroid Build Coastguard Worker #include "channelinfo.h"
106*e5436536SAndroid Build Coastguard Worker #include "aac_rom.h"
107*e5436536SAndroid Build Coastguard Worker
108*e5436536SAndroid Build Coastguard Worker #include "sbrdecoder.h"
109*e5436536SAndroid Build Coastguard Worker
110*e5436536SAndroid Build Coastguard Worker /*
111*e5436536SAndroid Build Coastguard Worker * Dynamic Range Control
112*e5436536SAndroid Build Coastguard Worker */
113*e5436536SAndroid Build Coastguard Worker
114*e5436536SAndroid Build Coastguard Worker /* For parameter conversion */
115*e5436536SAndroid Build Coastguard Worker #define DRC_PARAMETER_BITS (7)
116*e5436536SAndroid Build Coastguard Worker #define DRC_MAX_QUANT_STEPS (1 << DRC_PARAMETER_BITS)
117*e5436536SAndroid Build Coastguard Worker #define DRC_MAX_QUANT_FACTOR (DRC_MAX_QUANT_STEPS - 1)
118*e5436536SAndroid Build Coastguard Worker #define DRC_PARAM_QUANT_STEP \
119*e5436536SAndroid Build Coastguard Worker (FL2FXCONST_DBL(1.0f / (float)DRC_MAX_QUANT_FACTOR))
120*e5436536SAndroid Build Coastguard Worker #define DRC_PARAM_SCALE (1)
121*e5436536SAndroid Build Coastguard Worker #define DRC_SCALING_MAX \
122*e5436536SAndroid Build Coastguard Worker ((FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)127))
123*e5436536SAndroid Build Coastguard Worker
124*e5436536SAndroid Build Coastguard Worker #define DRC_BLOCK_LEN (1024)
125*e5436536SAndroid Build Coastguard Worker #define DRC_BAND_MULT (4)
126*e5436536SAndroid Build Coastguard Worker #define DRC_BLOCK_LEN_DIV_BAND_MULT (DRC_BLOCK_LEN / DRC_BAND_MULT)
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker #define MAX_REFERENCE_LEVEL (127)
129*e5436536SAndroid Build Coastguard Worker
130*e5436536SAndroid Build Coastguard Worker #define DRC_HEAVY_THRESHOLD_DB (10)
131*e5436536SAndroid Build Coastguard Worker
132*e5436536SAndroid Build Coastguard Worker #define DVB_ANC_DATA_SYNC_BYTE (0xBC) /* DVB ancillary data sync byte. */
133*e5436536SAndroid Build Coastguard Worker
134*e5436536SAndroid Build Coastguard Worker #define OFF 0
135*e5436536SAndroid Build Coastguard Worker #define ON 1
136*e5436536SAndroid Build Coastguard Worker
convert_drcParam(FIXP_DBL param_dbl)137*e5436536SAndroid Build Coastguard Worker static INT convert_drcParam(FIXP_DBL param_dbl) {
138*e5436536SAndroid Build Coastguard Worker /* converts an internal DRC boost/cut scaling factor in FIXP_DBL
139*e5436536SAndroid Build Coastguard Worker (which is downscaled by DRC_PARAM_SCALE)
140*e5436536SAndroid Build Coastguard Worker back to an integer value between 0 and 127. */
141*e5436536SAndroid Build Coastguard Worker LONG param_long;
142*e5436536SAndroid Build Coastguard Worker
143*e5436536SAndroid Build Coastguard Worker param_long = (LONG)param_dbl >> 7;
144*e5436536SAndroid Build Coastguard Worker param_long = param_long * (INT)DRC_MAX_QUANT_FACTOR;
145*e5436536SAndroid Build Coastguard Worker param_long >>= 31 - 7 - DRC_PARAM_SCALE - 1;
146*e5436536SAndroid Build Coastguard Worker param_long += 1; /* for rounding */
147*e5436536SAndroid Build Coastguard Worker param_long >>= 1;
148*e5436536SAndroid Build Coastguard Worker
149*e5436536SAndroid Build Coastguard Worker return (INT)param_long;
150*e5436536SAndroid Build Coastguard Worker }
151*e5436536SAndroid Build Coastguard Worker
152*e5436536SAndroid Build Coastguard Worker /*!
153*e5436536SAndroid Build Coastguard Worker \brief Disable DRC
154*e5436536SAndroid Build Coastguard Worker
155*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info
156*e5436536SAndroid Build Coastguard Worker
157*e5436536SAndroid Build Coastguard Worker \return none
158*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcDisable(HANDLE_AAC_DRC self)159*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcDisable(HANDLE_AAC_DRC self) {
160*e5436536SAndroid Build Coastguard Worker self->enable = 0;
161*e5436536SAndroid Build Coastguard Worker self->applyExtGain = 0;
162*e5436536SAndroid Build Coastguard Worker self->progRefLevelPresent = 0;
163*e5436536SAndroid Build Coastguard Worker }
164*e5436536SAndroid Build Coastguard Worker
165*e5436536SAndroid Build Coastguard Worker /*!
166*e5436536SAndroid Build Coastguard Worker \brief Reset DRC information
167*e5436536SAndroid Build Coastguard Worker
168*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info
169*e5436536SAndroid Build Coastguard Worker
170*e5436536SAndroid Build Coastguard Worker \return none
171*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcReset(HANDLE_AAC_DRC self)172*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcReset(HANDLE_AAC_DRC self) {
173*e5436536SAndroid Build Coastguard Worker self->applyExtGain = 0;
174*e5436536SAndroid Build Coastguard Worker self->additionalGainPrev = AACDEC_DRC_GAIN_INIT_VALUE;
175*e5436536SAndroid Build Coastguard Worker self->additionalGainFilterState = AACDEC_DRC_GAIN_INIT_VALUE;
176*e5436536SAndroid Build Coastguard Worker self->additionalGainFilterState1 = AACDEC_DRC_GAIN_INIT_VALUE;
177*e5436536SAndroid Build Coastguard Worker }
178*e5436536SAndroid Build Coastguard Worker
179*e5436536SAndroid Build Coastguard Worker /*!
180*e5436536SAndroid Build Coastguard Worker \brief Initialize DRC information
181*e5436536SAndroid Build Coastguard Worker
182*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info
183*e5436536SAndroid Build Coastguard Worker
184*e5436536SAndroid Build Coastguard Worker \return none
185*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcInit(HANDLE_AAC_DRC self)186*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcInit(HANDLE_AAC_DRC self) {
187*e5436536SAndroid Build Coastguard Worker CDrcParams *pParams;
188*e5436536SAndroid Build Coastguard Worker
189*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
190*e5436536SAndroid Build Coastguard Worker return;
191*e5436536SAndroid Build Coastguard Worker }
192*e5436536SAndroid Build Coastguard Worker
193*e5436536SAndroid Build Coastguard Worker /* init control fields */
194*e5436536SAndroid Build Coastguard Worker self->enable = OFF;
195*e5436536SAndroid Build Coastguard Worker self->numThreads = 0;
196*e5436536SAndroid Build Coastguard Worker
197*e5436536SAndroid Build Coastguard Worker /* init params */
198*e5436536SAndroid Build Coastguard Worker pParams = &self->params;
199*e5436536SAndroid Build Coastguard Worker pParams->bsDelayEnable = 0;
200*e5436536SAndroid Build Coastguard Worker pParams->cut = FL2FXCONST_DBL(0.0f);
201*e5436536SAndroid Build Coastguard Worker pParams->usrCut = FL2FXCONST_DBL(0.0f);
202*e5436536SAndroid Build Coastguard Worker pParams->boost = FL2FXCONST_DBL(0.0f);
203*e5436536SAndroid Build Coastguard Worker pParams->usrBoost = FL2FXCONST_DBL(0.0f);
204*e5436536SAndroid Build Coastguard Worker pParams->targetRefLevel = 96;
205*e5436536SAndroid Build Coastguard Worker pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
206*e5436536SAndroid Build Coastguard Worker pParams->applyHeavyCompression = OFF;
207*e5436536SAndroid Build Coastguard Worker pParams->usrApplyHeavyCompression = OFF;
208*e5436536SAndroid Build Coastguard Worker
209*e5436536SAndroid Build Coastguard Worker pParams->defaultPresentationMode = DISABLED_PARAMETER_HANDLING;
210*e5436536SAndroid Build Coastguard Worker pParams->encoderTargetLevel = MAX_REFERENCE_LEVEL; /* worst case assumption */
211*e5436536SAndroid Build Coastguard Worker
212*e5436536SAndroid Build Coastguard Worker self->update = 1;
213*e5436536SAndroid Build Coastguard Worker self->numOutChannels = 0;
214*e5436536SAndroid Build Coastguard Worker self->prevAacNumChannels = 0;
215*e5436536SAndroid Build Coastguard Worker
216*e5436536SAndroid Build Coastguard Worker /* initial program ref level = target ref level */
217*e5436536SAndroid Build Coastguard Worker self->progRefLevel = pParams->targetRefLevel;
218*e5436536SAndroid Build Coastguard Worker self->progRefLevelPresent = 0;
219*e5436536SAndroid Build Coastguard Worker self->presMode = -1;
220*e5436536SAndroid Build Coastguard Worker
221*e5436536SAndroid Build Coastguard Worker aacDecoder_drcReset(self);
222*e5436536SAndroid Build Coastguard Worker }
223*e5436536SAndroid Build Coastguard Worker
224*e5436536SAndroid Build Coastguard Worker /*!
225*e5436536SAndroid Build Coastguard Worker \brief Initialize DRC control data for one channel
226*e5436536SAndroid Build Coastguard Worker
227*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info
228*e5436536SAndroid Build Coastguard Worker
229*e5436536SAndroid Build Coastguard Worker \return none
230*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcInitChannelData(CDrcChannelData * pDrcChData)231*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChData) {
232*e5436536SAndroid Build Coastguard Worker if (pDrcChData != NULL) {
233*e5436536SAndroid Build Coastguard Worker pDrcChData->expiryCount = 0;
234*e5436536SAndroid Build Coastguard Worker pDrcChData->numBands = 1;
235*e5436536SAndroid Build Coastguard Worker pDrcChData->bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT - 1;
236*e5436536SAndroid Build Coastguard Worker pDrcChData->drcValue[0] = 0;
237*e5436536SAndroid Build Coastguard Worker pDrcChData->drcInterpolationScheme = 0;
238*e5436536SAndroid Build Coastguard Worker pDrcChData->drcDataType = UNKNOWN_PAYLOAD;
239*e5436536SAndroid Build Coastguard Worker }
240*e5436536SAndroid Build Coastguard Worker }
241*e5436536SAndroid Build Coastguard Worker
242*e5436536SAndroid Build Coastguard Worker /*!
243*e5436536SAndroid Build Coastguard Worker \brief Set one single DRC parameter
244*e5436536SAndroid Build Coastguard Worker
245*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info.
246*e5436536SAndroid Build Coastguard Worker \param Parameter to be set.
247*e5436536SAndroid Build Coastguard Worker \value Value to be set.
248*e5436536SAndroid Build Coastguard Worker
249*e5436536SAndroid Build Coastguard Worker \return an error code.
250*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcSetParam(HANDLE_AAC_DRC self,AACDEC_DRC_PARAM param,INT value)251*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self,
252*e5436536SAndroid Build Coastguard Worker AACDEC_DRC_PARAM param, INT value) {
253*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
254*e5436536SAndroid Build Coastguard Worker
255*e5436536SAndroid Build Coastguard Worker switch (param) {
256*e5436536SAndroid Build Coastguard Worker case DRC_CUT_SCALE:
257*e5436536SAndroid Build Coastguard Worker /* set attenuation scale factor */
258*e5436536SAndroid Build Coastguard Worker if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) {
259*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
260*e5436536SAndroid Build Coastguard Worker }
261*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
262*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
263*e5436536SAndroid Build Coastguard Worker }
264*e5436536SAndroid Build Coastguard Worker self->params.usrCut = (FIXP_DBL)(
265*e5436536SAndroid Build Coastguard Worker (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value);
266*e5436536SAndroid Build Coastguard Worker self->update = 1;
267*e5436536SAndroid Build Coastguard Worker break;
268*e5436536SAndroid Build Coastguard Worker case DRC_BOOST_SCALE:
269*e5436536SAndroid Build Coastguard Worker /* set boost factor */
270*e5436536SAndroid Build Coastguard Worker if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) {
271*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
272*e5436536SAndroid Build Coastguard Worker }
273*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
274*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
275*e5436536SAndroid Build Coastguard Worker }
276*e5436536SAndroid Build Coastguard Worker self->params.usrBoost = (FIXP_DBL)(
277*e5436536SAndroid Build Coastguard Worker (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value);
278*e5436536SAndroid Build Coastguard Worker self->update = 1;
279*e5436536SAndroid Build Coastguard Worker break;
280*e5436536SAndroid Build Coastguard Worker case TARGET_REF_LEVEL:
281*e5436536SAndroid Build Coastguard Worker if (value > MAX_REFERENCE_LEVEL || value < -MAX_REFERENCE_LEVEL) {
282*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
283*e5436536SAndroid Build Coastguard Worker }
284*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
285*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
286*e5436536SAndroid Build Coastguard Worker }
287*e5436536SAndroid Build Coastguard Worker if (value < 0) {
288*e5436536SAndroid Build Coastguard Worker self->params.targetRefLevel = -1;
289*e5436536SAndroid Build Coastguard Worker } else {
290*e5436536SAndroid Build Coastguard Worker if (self->params.targetRefLevel != (SCHAR)value) {
291*e5436536SAndroid Build Coastguard Worker self->params.targetRefLevel = (SCHAR)value;
292*e5436536SAndroid Build Coastguard Worker self->progRefLevel = (SCHAR)value; /* Always set the program reference
293*e5436536SAndroid Build Coastguard Worker level equal to the target level
294*e5436536SAndroid Build Coastguard Worker according to 4.5.2.7.3 of
295*e5436536SAndroid Build Coastguard Worker ISO/IEC 14496-3. */
296*e5436536SAndroid Build Coastguard Worker }
297*e5436536SAndroid Build Coastguard Worker self->update = 1;
298*e5436536SAndroid Build Coastguard Worker }
299*e5436536SAndroid Build Coastguard Worker break;
300*e5436536SAndroid Build Coastguard Worker case APPLY_HEAVY_COMPRESSION:
301*e5436536SAndroid Build Coastguard Worker if ((value != OFF) && (value != ON)) {
302*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
303*e5436536SAndroid Build Coastguard Worker }
304*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
305*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
306*e5436536SAndroid Build Coastguard Worker }
307*e5436536SAndroid Build Coastguard Worker /* Store new parameter value */
308*e5436536SAndroid Build Coastguard Worker self->params.usrApplyHeavyCompression = (UCHAR)value;
309*e5436536SAndroid Build Coastguard Worker self->update = 1;
310*e5436536SAndroid Build Coastguard Worker break;
311*e5436536SAndroid Build Coastguard Worker case DEFAULT_PRESENTATION_MODE:
312*e5436536SAndroid Build Coastguard Worker if (value < AAC_DRC_PARAMETER_HANDLING_DISABLED ||
313*e5436536SAndroid Build Coastguard Worker value > AAC_DRC_PRESENTATION_MODE_2_DEFAULT) {
314*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
315*e5436536SAndroid Build Coastguard Worker }
316*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
317*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
318*e5436536SAndroid Build Coastguard Worker }
319*e5436536SAndroid Build Coastguard Worker self->params.defaultPresentationMode =
320*e5436536SAndroid Build Coastguard Worker (AACDEC_DRC_PARAMETER_HANDLING)value;
321*e5436536SAndroid Build Coastguard Worker self->update = 1;
322*e5436536SAndroid Build Coastguard Worker break;
323*e5436536SAndroid Build Coastguard Worker case ENCODER_TARGET_LEVEL:
324*e5436536SAndroid Build Coastguard Worker if (value > MAX_REFERENCE_LEVEL || value < 0) {
325*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
326*e5436536SAndroid Build Coastguard Worker }
327*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
328*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
329*e5436536SAndroid Build Coastguard Worker }
330*e5436536SAndroid Build Coastguard Worker self->params.encoderTargetLevel = (UCHAR)value;
331*e5436536SAndroid Build Coastguard Worker self->update = 1;
332*e5436536SAndroid Build Coastguard Worker break;
333*e5436536SAndroid Build Coastguard Worker case DRC_BS_DELAY:
334*e5436536SAndroid Build Coastguard Worker if (value < 0 || value > 1) {
335*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
336*e5436536SAndroid Build Coastguard Worker }
337*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
338*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
339*e5436536SAndroid Build Coastguard Worker }
340*e5436536SAndroid Build Coastguard Worker self->params.bsDelayEnable = value;
341*e5436536SAndroid Build Coastguard Worker break;
342*e5436536SAndroid Build Coastguard Worker case DRC_DATA_EXPIRY_FRAME:
343*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
344*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
345*e5436536SAndroid Build Coastguard Worker }
346*e5436536SAndroid Build Coastguard Worker self->params.expiryFrame = (value > 0) ? (UINT)value : 0;
347*e5436536SAndroid Build Coastguard Worker break;
348*e5436536SAndroid Build Coastguard Worker case MAX_OUTPUT_CHANNELS:
349*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
350*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
351*e5436536SAndroid Build Coastguard Worker }
352*e5436536SAndroid Build Coastguard Worker self->numOutChannels = (INT)value;
353*e5436536SAndroid Build Coastguard Worker self->update = 1;
354*e5436536SAndroid Build Coastguard Worker break;
355*e5436536SAndroid Build Coastguard Worker default:
356*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
357*e5436536SAndroid Build Coastguard Worker } /* switch(param) */
358*e5436536SAndroid Build Coastguard Worker
359*e5436536SAndroid Build Coastguard Worker return ErrorStatus;
360*e5436536SAndroid Build Coastguard Worker }
361*e5436536SAndroid Build Coastguard Worker
parseExcludedChannels(UINT * excludedChnsMask,HANDLE_FDK_BITSTREAM bs)362*e5436536SAndroid Build Coastguard Worker static int parseExcludedChannels(UINT *excludedChnsMask,
363*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM bs) {
364*e5436536SAndroid Build Coastguard Worker UINT excludeMask = 0;
365*e5436536SAndroid Build Coastguard Worker UINT i, j;
366*e5436536SAndroid Build Coastguard Worker int bitCnt = 9;
367*e5436536SAndroid Build Coastguard Worker
368*e5436536SAndroid Build Coastguard Worker for (i = 0, j = 1; i < 7; i++, j <<= 1) {
369*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) {
370*e5436536SAndroid Build Coastguard Worker excludeMask |= j;
371*e5436536SAndroid Build Coastguard Worker }
372*e5436536SAndroid Build Coastguard Worker }
373*e5436536SAndroid Build Coastguard Worker
374*e5436536SAndroid Build Coastguard Worker /* additional_excluded_chns */
375*e5436536SAndroid Build Coastguard Worker while (FDKreadBits(bs, 1)) {
376*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 7; i++, j <<= 1) {
377*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) {
378*e5436536SAndroid Build Coastguard Worker excludeMask |= j;
379*e5436536SAndroid Build Coastguard Worker }
380*e5436536SAndroid Build Coastguard Worker }
381*e5436536SAndroid Build Coastguard Worker bitCnt += 9;
382*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(j < (UINT)-1);
383*e5436536SAndroid Build Coastguard Worker }
384*e5436536SAndroid Build Coastguard Worker
385*e5436536SAndroid Build Coastguard Worker *excludedChnsMask = excludeMask;
386*e5436536SAndroid Build Coastguard Worker
387*e5436536SAndroid Build Coastguard Worker return (bitCnt);
388*e5436536SAndroid Build Coastguard Worker }
389*e5436536SAndroid Build Coastguard Worker
390*e5436536SAndroid Build Coastguard Worker /*!
391*e5436536SAndroid Build Coastguard Worker \brief Save DRC payload bitstream position
392*e5436536SAndroid Build Coastguard Worker
393*e5436536SAndroid Build Coastguard Worker \self Handle of DRC info
394*e5436536SAndroid Build Coastguard Worker \bs Handle of FDK bitstream
395*e5436536SAndroid Build Coastguard Worker
396*e5436536SAndroid Build Coastguard Worker \return The number of DRC payload bits
397*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self,HANDLE_FDK_BITSTREAM bs,AACDEC_DRC_PAYLOAD_TYPE type)398*e5436536SAndroid Build Coastguard Worker int aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM bs,
399*e5436536SAndroid Build Coastguard Worker AACDEC_DRC_PAYLOAD_TYPE type) {
400*e5436536SAndroid Build Coastguard Worker UINT bsStartPos;
401*e5436536SAndroid Build Coastguard Worker int i, numBands = 1, bitCnt = 0;
402*e5436536SAndroid Build Coastguard Worker
403*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
404*e5436536SAndroid Build Coastguard Worker return 0;
405*e5436536SAndroid Build Coastguard Worker }
406*e5436536SAndroid Build Coastguard Worker
407*e5436536SAndroid Build Coastguard Worker bsStartPos = FDKgetValidBits(bs);
408*e5436536SAndroid Build Coastguard Worker
409*e5436536SAndroid Build Coastguard Worker switch (type) {
410*e5436536SAndroid Build Coastguard Worker case MPEG_DRC_EXT_DATA: {
411*e5436536SAndroid Build Coastguard Worker bitCnt = 4;
412*e5436536SAndroid Build Coastguard Worker
413*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) { /* pce_tag_present */
414*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* pce_instance_tag + drc_tag_reserved_bits */
415*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
416*e5436536SAndroid Build Coastguard Worker }
417*e5436536SAndroid Build Coastguard Worker
418*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) { /* excluded_chns_present */
419*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 7); /* exclude mask [0..7] */
420*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
421*e5436536SAndroid Build Coastguard Worker while (FDKreadBits(bs, 1)) { /* additional_excluded_chns */
422*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 7); /* exclude mask [x..y] */
423*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
424*e5436536SAndroid Build Coastguard Worker }
425*e5436536SAndroid Build Coastguard Worker }
426*e5436536SAndroid Build Coastguard Worker
427*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) { /* drc_bands_present */
428*e5436536SAndroid Build Coastguard Worker numBands += FDKreadBits(bs, 4); /* drc_band_incr */
429*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 4); /* reserved */
430*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
431*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numBands; i++) {
432*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* drc_band_top[i] */
433*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
434*e5436536SAndroid Build Coastguard Worker }
435*e5436536SAndroid Build Coastguard Worker }
436*e5436536SAndroid Build Coastguard Worker
437*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) { /* prog_ref_level_present */
438*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* prog_ref_level + prog_ref_level_reserved_bits */
439*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
440*e5436536SAndroid Build Coastguard Worker }
441*e5436536SAndroid Build Coastguard Worker
442*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numBands; i++) {
443*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */
444*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
445*e5436536SAndroid Build Coastguard Worker }
446*e5436536SAndroid Build Coastguard Worker
447*e5436536SAndroid Build Coastguard Worker if ((self->numPayloads < MAX_DRC_THREADS) &&
448*e5436536SAndroid Build Coastguard Worker ((INT)FDKgetValidBits(bs) >= 0)) {
449*e5436536SAndroid Build Coastguard Worker self->drcPayloadPosition[self->numPayloads++] = bsStartPos;
450*e5436536SAndroid Build Coastguard Worker }
451*e5436536SAndroid Build Coastguard Worker } break;
452*e5436536SAndroid Build Coastguard Worker
453*e5436536SAndroid Build Coastguard Worker case DVB_DRC_ANC_DATA:
454*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
455*e5436536SAndroid Build Coastguard Worker /* check sync word */
456*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE) {
457*e5436536SAndroid Build Coastguard Worker int dmxLevelsPresent, compressionPresent;
458*e5436536SAndroid Build Coastguard Worker int coarseGrainTcPresent, fineGrainTcPresent;
459*e5436536SAndroid Build Coastguard Worker
460*e5436536SAndroid Build Coastguard Worker /* bs_info field */
461*e5436536SAndroid Build Coastguard Worker FDKreadBits(
462*e5436536SAndroid Build Coastguard Worker bs,
463*e5436536SAndroid Build Coastguard Worker 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
464*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
465*e5436536SAndroid Build Coastguard Worker
466*e5436536SAndroid Build Coastguard Worker /* Evaluate ancillary_data_status */
467*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 3); /* reserved, set to 0 */
468*e5436536SAndroid Build Coastguard Worker dmxLevelsPresent =
469*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
470*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* reserved, set to 0 */
471*e5436536SAndroid Build Coastguard Worker compressionPresent =
472*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
473*e5436536SAndroid Build Coastguard Worker coarseGrainTcPresent =
474*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
475*e5436536SAndroid Build Coastguard Worker fineGrainTcPresent =
476*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* fine_grain_timecode_status */
477*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
478*e5436536SAndroid Build Coastguard Worker
479*e5436536SAndroid Build Coastguard Worker /* MPEG4 downmixing levels */
480*e5436536SAndroid Build Coastguard Worker if (dmxLevelsPresent) {
481*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
482*e5436536SAndroid Build Coastguard Worker bitCnt += 8;
483*e5436536SAndroid Build Coastguard Worker }
484*e5436536SAndroid Build Coastguard Worker /* audio coding mode and compression status */
485*e5436536SAndroid Build Coastguard Worker if (compressionPresent) {
486*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */
487*e5436536SAndroid Build Coastguard Worker bitCnt += 16;
488*e5436536SAndroid Build Coastguard Worker }
489*e5436536SAndroid Build Coastguard Worker /* coarse grain timecode */
490*e5436536SAndroid Build Coastguard Worker if (coarseGrainTcPresent) {
491*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 16); /* coarse_grain_timecode */
492*e5436536SAndroid Build Coastguard Worker bitCnt += 16;
493*e5436536SAndroid Build Coastguard Worker }
494*e5436536SAndroid Build Coastguard Worker /* fine grain timecode */
495*e5436536SAndroid Build Coastguard Worker if (fineGrainTcPresent) {
496*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 16); /* fine_grain_timecode */
497*e5436536SAndroid Build Coastguard Worker bitCnt += 16;
498*e5436536SAndroid Build Coastguard Worker }
499*e5436536SAndroid Build Coastguard Worker if (!self->dvbAncDataAvailable && ((INT)FDKgetValidBits(bs) >= 0)) {
500*e5436536SAndroid Build Coastguard Worker self->dvbAncDataPosition = bsStartPos;
501*e5436536SAndroid Build Coastguard Worker self->dvbAncDataAvailable = 1;
502*e5436536SAndroid Build Coastguard Worker }
503*e5436536SAndroid Build Coastguard Worker }
504*e5436536SAndroid Build Coastguard Worker break;
505*e5436536SAndroid Build Coastguard Worker
506*e5436536SAndroid Build Coastguard Worker default:
507*e5436536SAndroid Build Coastguard Worker break;
508*e5436536SAndroid Build Coastguard Worker }
509*e5436536SAndroid Build Coastguard Worker
510*e5436536SAndroid Build Coastguard Worker return (bitCnt);
511*e5436536SAndroid Build Coastguard Worker }
512*e5436536SAndroid Build Coastguard Worker
513*e5436536SAndroid Build Coastguard Worker /*!
514*e5436536SAndroid Build Coastguard Worker \brief Parse DRC parameters from bitstream
515*e5436536SAndroid Build Coastguard Worker
516*e5436536SAndroid Build Coastguard Worker \bs Handle of FDK bitstream (in)
517*e5436536SAndroid Build Coastguard Worker \pDrcBs Pointer to DRC payload data container (out)
518*e5436536SAndroid Build Coastguard Worker \payloadPosition Bitstream position of MPEG DRC data chunk (in)
519*e5436536SAndroid Build Coastguard Worker
520*e5436536SAndroid Build Coastguard Worker \return Flag telling whether new DRC data has been found or not.
521*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcParse(HANDLE_FDK_BITSTREAM bs,CDrcPayload * pDrcBs,UINT payloadPosition)522*e5436536SAndroid Build Coastguard Worker static int aacDecoder_drcParse(HANDLE_FDK_BITSTREAM bs, CDrcPayload *pDrcBs,
523*e5436536SAndroid Build Coastguard Worker UINT payloadPosition) {
524*e5436536SAndroid Build Coastguard Worker int i, numBands;
525*e5436536SAndroid Build Coastguard Worker
526*e5436536SAndroid Build Coastguard Worker /* Move to the beginning of the DRC payload field */
527*e5436536SAndroid Build Coastguard Worker FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition);
528*e5436536SAndroid Build Coastguard Worker
529*e5436536SAndroid Build Coastguard Worker /* pce_tag_present */
530*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) {
531*e5436536SAndroid Build Coastguard Worker pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */
532*e5436536SAndroid Build Coastguard Worker /* only one program supported */
533*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 4); /* drc_tag_reserved_bits */
534*e5436536SAndroid Build Coastguard Worker } else {
535*e5436536SAndroid Build Coastguard Worker pDrcBs->pceInstanceTag = -1; /* not present */
536*e5436536SAndroid Build Coastguard Worker }
537*e5436536SAndroid Build Coastguard Worker
538*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) { /* excluded_chns_present */
539*e5436536SAndroid Build Coastguard Worker /* get excluded_chn_mask */
540*e5436536SAndroid Build Coastguard Worker parseExcludedChannels(&pDrcBs->excludedChnsMask, bs);
541*e5436536SAndroid Build Coastguard Worker } else {
542*e5436536SAndroid Build Coastguard Worker pDrcBs->excludedChnsMask = 0;
543*e5436536SAndroid Build Coastguard Worker }
544*e5436536SAndroid Build Coastguard Worker
545*e5436536SAndroid Build Coastguard Worker numBands = 1;
546*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) /* drc_bands_present */
547*e5436536SAndroid Build Coastguard Worker {
548*e5436536SAndroid Build Coastguard Worker /* get band_incr */
549*e5436536SAndroid Build Coastguard Worker numBands += FDKreadBits(bs, 4); /* drc_band_incr */
550*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcInterpolationScheme =
551*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 4); /* drc_interpolation_scheme */
552*e5436536SAndroid Build Coastguard Worker /* band_top */
553*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numBands; i++) {
554*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */
555*e5436536SAndroid Build Coastguard Worker }
556*e5436536SAndroid Build Coastguard Worker } else {
557*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT -
558*e5436536SAndroid Build Coastguard Worker 1; /* ... comprising the whole spectrum. */
559*e5436536SAndroid Build Coastguard Worker ;
560*e5436536SAndroid Build Coastguard Worker }
561*e5436536SAndroid Build Coastguard Worker
562*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.numBands = numBands;
563*e5436536SAndroid Build Coastguard Worker
564*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1)) /* prog_ref_level_present */
565*e5436536SAndroid Build Coastguard Worker {
566*e5436536SAndroid Build Coastguard Worker pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */
567*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */
568*e5436536SAndroid Build Coastguard Worker } else {
569*e5436536SAndroid Build Coastguard Worker pDrcBs->progRefLevel = -1;
570*e5436536SAndroid Build Coastguard Worker }
571*e5436536SAndroid Build Coastguard Worker
572*e5436536SAndroid Build Coastguard Worker for (i = 0; i < numBands; i++) {
573*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1)
574*e5436536SAndroid Build Coastguard Worker << 7; /* dyn_rng_sgn[i] */
575*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcValue[i] |=
576*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */
577*e5436536SAndroid Build Coastguard Worker }
578*e5436536SAndroid Build Coastguard Worker
579*e5436536SAndroid Build Coastguard Worker /* Set DRC payload type */
580*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA;
581*e5436536SAndroid Build Coastguard Worker
582*e5436536SAndroid Build Coastguard Worker return (1);
583*e5436536SAndroid Build Coastguard Worker }
584*e5436536SAndroid Build Coastguard Worker
585*e5436536SAndroid Build Coastguard Worker /*!
586*e5436536SAndroid Build Coastguard Worker \brief Parse heavy compression value transported in DSEs of DVB streams with
587*e5436536SAndroid Build Coastguard Worker MPEG-4 content.
588*e5436536SAndroid Build Coastguard Worker
589*e5436536SAndroid Build Coastguard Worker \bs Handle of FDK bitstream (in)
590*e5436536SAndroid Build Coastguard Worker \pDrcBs Pointer to DRC payload data container (out)
591*e5436536SAndroid Build Coastguard Worker \payloadPosition Bitstream position of DVB ancillary data chunk
592*e5436536SAndroid Build Coastguard Worker
593*e5436536SAndroid Build Coastguard Worker \return Flag telling whether new DRC data has been found or not.
594*e5436536SAndroid Build Coastguard Worker */
595*e5436536SAndroid Build Coastguard Worker #define DVB_COMPRESSION_SCALE (8) /* 48,164 dB */
596*e5436536SAndroid Build Coastguard Worker
aacDecoder_drcReadCompression(HANDLE_FDK_BITSTREAM bs,CDrcPayload * pDrcBs,UINT payloadPosition)597*e5436536SAndroid Build Coastguard Worker static int aacDecoder_drcReadCompression(HANDLE_FDK_BITSTREAM bs,
598*e5436536SAndroid Build Coastguard Worker CDrcPayload *pDrcBs,
599*e5436536SAndroid Build Coastguard Worker UINT payloadPosition) {
600*e5436536SAndroid Build Coastguard Worker int foundDrcData = 0;
601*e5436536SAndroid Build Coastguard Worker int dmxLevelsPresent, compressionPresent;
602*e5436536SAndroid Build Coastguard Worker
603*e5436536SAndroid Build Coastguard Worker /* Move to the beginning of the DRC payload field */
604*e5436536SAndroid Build Coastguard Worker FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition);
605*e5436536SAndroid Build Coastguard Worker
606*e5436536SAndroid Build Coastguard Worker /* Sanity checks */
607*e5436536SAndroid Build Coastguard Worker if (FDKgetValidBits(bs) < 24) {
608*e5436536SAndroid Build Coastguard Worker return 0;
609*e5436536SAndroid Build Coastguard Worker }
610*e5436536SAndroid Build Coastguard Worker
611*e5436536SAndroid Build Coastguard Worker /* Check sync word */
612*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) {
613*e5436536SAndroid Build Coastguard Worker return 0;
614*e5436536SAndroid Build Coastguard Worker }
615*e5436536SAndroid Build Coastguard Worker
616*e5436536SAndroid Build Coastguard Worker /* Evaluate bs_info field */
617*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */
618*e5436536SAndroid Build Coastguard Worker /* No MPEG-4 audio data */
619*e5436536SAndroid Build Coastguard Worker return 0;
620*e5436536SAndroid Build Coastguard Worker }
621*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 2); /* dolby_surround_mode */
622*e5436536SAndroid Build Coastguard Worker pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */
623*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* stereo_downmix_mode */
624*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
625*e5436536SAndroid Build Coastguard Worker return 0;
626*e5436536SAndroid Build Coastguard Worker }
627*e5436536SAndroid Build Coastguard Worker
628*e5436536SAndroid Build Coastguard Worker /* Evaluate ancillary_data_status */
629*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */
630*e5436536SAndroid Build Coastguard Worker return 0;
631*e5436536SAndroid Build Coastguard Worker }
632*e5436536SAndroid Build Coastguard Worker dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
633*e5436536SAndroid Build Coastguard Worker /*extensionPresent =*/FDKreadBits(bs,
634*e5436536SAndroid Build Coastguard Worker 1); /* ancillary_data_extension_status; */
635*e5436536SAndroid Build Coastguard Worker compressionPresent =
636*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
637*e5436536SAndroid Build Coastguard Worker /*coarseGrainTcPresent =*/FDKreadBits(bs,
638*e5436536SAndroid Build Coastguard Worker 1); /* coarse_grain_timecode_status */
639*e5436536SAndroid Build Coastguard Worker /*fineGrainTcPresent =*/FDKreadBits(bs, 1); /* fine_grain_timecode_status */
640*e5436536SAndroid Build Coastguard Worker
641*e5436536SAndroid Build Coastguard Worker if (dmxLevelsPresent) {
642*e5436536SAndroid Build Coastguard Worker FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
643*e5436536SAndroid Build Coastguard Worker }
644*e5436536SAndroid Build Coastguard Worker
645*e5436536SAndroid Build Coastguard Worker /* audio_coding_mode_and_compression_status */
646*e5436536SAndroid Build Coastguard Worker if (compressionPresent) {
647*e5436536SAndroid Build Coastguard Worker UCHAR compressionOn, compressionValue;
648*e5436536SAndroid Build Coastguard Worker
649*e5436536SAndroid Build Coastguard Worker /* audio_coding_mode */
650*e5436536SAndroid Build Coastguard Worker if (FDKreadBits(bs, 7) != 0) { /* The reserved bits shall be set to "0". */
651*e5436536SAndroid Build Coastguard Worker return 0;
652*e5436536SAndroid Build Coastguard Worker }
653*e5436536SAndroid Build Coastguard Worker compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */
654*e5436536SAndroid Build Coastguard Worker compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */
655*e5436536SAndroid Build Coastguard Worker
656*e5436536SAndroid Build Coastguard Worker if (compressionOn) {
657*e5436536SAndroid Build Coastguard Worker /* A compression value is available so store the data just like MPEG DRC
658*e5436536SAndroid Build Coastguard Worker * data */
659*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.numBands = 1; /* One band ... */
660*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcValue[0] =
661*e5436536SAndroid Build Coastguard Worker compressionValue; /* ... with one value ... */
662*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.bandTop[0] =
663*e5436536SAndroid Build Coastguard Worker DRC_BLOCK_LEN_DIV_BAND_MULT -
664*e5436536SAndroid Build Coastguard Worker 1; /* ... comprising the whole spectrum. */
665*e5436536SAndroid Build Coastguard Worker ;
666*e5436536SAndroid Build Coastguard Worker pDrcBs->pceInstanceTag = -1; /* Not present */
667*e5436536SAndroid Build Coastguard Worker pDrcBs->progRefLevel = -1; /* Not present */
668*e5436536SAndroid Build Coastguard Worker pDrcBs->channelData.drcDataType =
669*e5436536SAndroid Build Coastguard Worker DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */
670*e5436536SAndroid Build Coastguard Worker foundDrcData = 1;
671*e5436536SAndroid Build Coastguard Worker }
672*e5436536SAndroid Build Coastguard Worker }
673*e5436536SAndroid Build Coastguard Worker
674*e5436536SAndroid Build Coastguard Worker return (foundDrcData);
675*e5436536SAndroid Build Coastguard Worker }
676*e5436536SAndroid Build Coastguard Worker
677*e5436536SAndroid Build Coastguard Worker /*
678*e5436536SAndroid Build Coastguard Worker * Extract DRC payload from bitstream and map it to channels.
679*e5436536SAndroid Build Coastguard Worker * Valid return values are:
680*e5436536SAndroid Build Coastguard Worker * -1 : An unexpected error occured.
681*e5436536SAndroid Build Coastguard Worker * 0 : No error and no valid DRC data available.
682*e5436536SAndroid Build Coastguard Worker * 1 : No error and valid DRC data has been mapped.
683*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcExtractAndMap(HANDLE_AAC_DRC self,HANDLE_FDK_BITSTREAM hBs,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo[],UCHAR pceInstanceTag,UCHAR channelMapping[],int validChannels)684*e5436536SAndroid Build Coastguard Worker static int aacDecoder_drcExtractAndMap(
685*e5436536SAndroid Build Coastguard Worker HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs,
686*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
687*e5436536SAndroid Build Coastguard Worker UCHAR pceInstanceTag,
688*e5436536SAndroid Build Coastguard Worker UCHAR channelMapping[], /* Channel mapping translating drcChannel index to
689*e5436536SAndroid Build Coastguard Worker canonical channel index */
690*e5436536SAndroid Build Coastguard Worker int validChannels) {
691*e5436536SAndroid Build Coastguard Worker CDrcPayload threadBs[MAX_DRC_THREADS];
692*e5436536SAndroid Build Coastguard Worker CDrcPayload *validThreadBs[MAX_DRC_THREADS];
693*e5436536SAndroid Build Coastguard Worker CDrcParams *pParams;
694*e5436536SAndroid Build Coastguard Worker UINT backupBsPosition;
695*e5436536SAndroid Build Coastguard Worker int result = 0;
696*e5436536SAndroid Build Coastguard Worker int i, thread, validThreads = 0;
697*e5436536SAndroid Build Coastguard Worker
698*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(self != NULL);
699*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(hBs != NULL);
700*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL);
701*e5436536SAndroid Build Coastguard Worker
702*e5436536SAndroid Build Coastguard Worker pParams = &self->params;
703*e5436536SAndroid Build Coastguard Worker
704*e5436536SAndroid Build Coastguard Worker self->numThreads = 0;
705*e5436536SAndroid Build Coastguard Worker backupBsPosition = FDKgetValidBits(hBs);
706*e5436536SAndroid Build Coastguard Worker
707*e5436536SAndroid Build Coastguard Worker for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS;
708*e5436536SAndroid Build Coastguard Worker i++) {
709*e5436536SAndroid Build Coastguard Worker /* Init payload data chunk. The memclear is very important because it
710*e5436536SAndroid Build Coastguard Worker initializes the most values. Without it the module wouldn't work properly
711*e5436536SAndroid Build Coastguard Worker or crash. */
712*e5436536SAndroid Build Coastguard Worker FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
713*e5436536SAndroid Build Coastguard Worker threadBs[self->numThreads].channelData.bandTop[0] =
714*e5436536SAndroid Build Coastguard Worker DRC_BLOCK_LEN_DIV_BAND_MULT - 1;
715*e5436536SAndroid Build Coastguard Worker
716*e5436536SAndroid Build Coastguard Worker /* Extract payload */
717*e5436536SAndroid Build Coastguard Worker self->numThreads += aacDecoder_drcParse(hBs, &threadBs[self->numThreads],
718*e5436536SAndroid Build Coastguard Worker self->drcPayloadPosition[i]);
719*e5436536SAndroid Build Coastguard Worker }
720*e5436536SAndroid Build Coastguard Worker self->numPayloads = 0;
721*e5436536SAndroid Build Coastguard Worker
722*e5436536SAndroid Build Coastguard Worker if (self->dvbAncDataAvailable &&
723*e5436536SAndroid Build Coastguard Worker self->numThreads < MAX_DRC_THREADS) { /* Append a DVB heavy compression
724*e5436536SAndroid Build Coastguard Worker payload thread if available. */
725*e5436536SAndroid Build Coastguard Worker
726*e5436536SAndroid Build Coastguard Worker /* Init payload data chunk. The memclear is very important because it
727*e5436536SAndroid Build Coastguard Worker initializes the most values. Without it the module wouldn't work properly
728*e5436536SAndroid Build Coastguard Worker or crash. */
729*e5436536SAndroid Build Coastguard Worker FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
730*e5436536SAndroid Build Coastguard Worker threadBs[self->numThreads].channelData.bandTop[0] =
731*e5436536SAndroid Build Coastguard Worker DRC_BLOCK_LEN_DIV_BAND_MULT - 1;
732*e5436536SAndroid Build Coastguard Worker
733*e5436536SAndroid Build Coastguard Worker /* Extract payload */
734*e5436536SAndroid Build Coastguard Worker self->numThreads += aacDecoder_drcReadCompression(
735*e5436536SAndroid Build Coastguard Worker hBs, &threadBs[self->numThreads], self->dvbAncDataPosition);
736*e5436536SAndroid Build Coastguard Worker }
737*e5436536SAndroid Build Coastguard Worker self->dvbAncDataAvailable = 0;
738*e5436536SAndroid Build Coastguard Worker
739*e5436536SAndroid Build Coastguard Worker /* Reset the bitbufffer */
740*e5436536SAndroid Build Coastguard Worker FDKpushBiDirectional(hBs, (INT)FDKgetValidBits(hBs) - (INT)backupBsPosition);
741*e5436536SAndroid Build Coastguard Worker
742*e5436536SAndroid Build Coastguard Worker /* calculate number of valid bits in excl_chn_mask */
743*e5436536SAndroid Build Coastguard Worker
744*e5436536SAndroid Build Coastguard Worker /* coupling channels not supported */
745*e5436536SAndroid Build Coastguard Worker
746*e5436536SAndroid Build Coastguard Worker /* check for valid threads */
747*e5436536SAndroid Build Coastguard Worker for (thread = 0; thread < self->numThreads; thread++) {
748*e5436536SAndroid Build Coastguard Worker CDrcPayload *pThreadBs = &threadBs[thread];
749*e5436536SAndroid Build Coastguard Worker int numExclChns = 0;
750*e5436536SAndroid Build Coastguard Worker
751*e5436536SAndroid Build Coastguard Worker switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
752*e5436536SAndroid Build Coastguard Worker default:
753*e5436536SAndroid Build Coastguard Worker continue;
754*e5436536SAndroid Build Coastguard Worker case MPEG_DRC_EXT_DATA:
755*e5436536SAndroid Build Coastguard Worker case DVB_DRC_ANC_DATA:
756*e5436536SAndroid Build Coastguard Worker break;
757*e5436536SAndroid Build Coastguard Worker }
758*e5436536SAndroid Build Coastguard Worker
759*e5436536SAndroid Build Coastguard Worker if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
760*e5436536SAndroid Build Coastguard Worker if (pThreadBs->pceInstanceTag != pceInstanceTag) {
761*e5436536SAndroid Build Coastguard Worker continue; /* don't accept */
762*e5436536SAndroid Build Coastguard Worker }
763*e5436536SAndroid Build Coastguard Worker }
764*e5436536SAndroid Build Coastguard Worker
765*e5436536SAndroid Build Coastguard Worker /* calculate number of excluded channels */
766*e5436536SAndroid Build Coastguard Worker if (pThreadBs->excludedChnsMask > 0) {
767*e5436536SAndroid Build Coastguard Worker INT exclMask = pThreadBs->excludedChnsMask;
768*e5436536SAndroid Build Coastguard Worker int ch;
769*e5436536SAndroid Build Coastguard Worker for (ch = 0; ch < validChannels; ch++) {
770*e5436536SAndroid Build Coastguard Worker numExclChns += exclMask & 0x1;
771*e5436536SAndroid Build Coastguard Worker exclMask >>= 1;
772*e5436536SAndroid Build Coastguard Worker }
773*e5436536SAndroid Build Coastguard Worker }
774*e5436536SAndroid Build Coastguard Worker if (numExclChns < validChannels) {
775*e5436536SAndroid Build Coastguard Worker validThreadBs[validThreads] = pThreadBs;
776*e5436536SAndroid Build Coastguard Worker validThreads++;
777*e5436536SAndroid Build Coastguard Worker }
778*e5436536SAndroid Build Coastguard Worker }
779*e5436536SAndroid Build Coastguard Worker
780*e5436536SAndroid Build Coastguard Worker /* map DRC bitstream information onto DRC channel information */
781*e5436536SAndroid Build Coastguard Worker for (thread = 0; thread < validThreads; thread++) {
782*e5436536SAndroid Build Coastguard Worker CDrcPayload *pThreadBs = validThreadBs[thread];
783*e5436536SAndroid Build Coastguard Worker INT exclMask = pThreadBs->excludedChnsMask;
784*e5436536SAndroid Build Coastguard Worker AACDEC_DRC_PAYLOAD_TYPE drcPayloadType =
785*e5436536SAndroid Build Coastguard Worker (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
786*e5436536SAndroid Build Coastguard Worker int ch;
787*e5436536SAndroid Build Coastguard Worker
788*e5436536SAndroid Build Coastguard Worker /* last progRefLevel transmitted is the one that is used
789*e5436536SAndroid Build Coastguard Worker * (but it should really only be transmitted once per block!)
790*e5436536SAndroid Build Coastguard Worker */
791*e5436536SAndroid Build Coastguard Worker if (pThreadBs->progRefLevel >= 0) {
792*e5436536SAndroid Build Coastguard Worker self->progRefLevel = pThreadBs->progRefLevel;
793*e5436536SAndroid Build Coastguard Worker self->progRefLevelPresent = 1;
794*e5436536SAndroid Build Coastguard Worker self->prlExpiryCount = 0; /* Got a new value -> Reset counter */
795*e5436536SAndroid Build Coastguard Worker }
796*e5436536SAndroid Build Coastguard Worker
797*e5436536SAndroid Build Coastguard Worker if (drcPayloadType == DVB_DRC_ANC_DATA) {
798*e5436536SAndroid Build Coastguard Worker /* Announce the presentation mode of this valid thread. */
799*e5436536SAndroid Build Coastguard Worker self->presMode = pThreadBs->presMode;
800*e5436536SAndroid Build Coastguard Worker }
801*e5436536SAndroid Build Coastguard Worker
802*e5436536SAndroid Build Coastguard Worker /* SCE, CPE and LFE */
803*e5436536SAndroid Build Coastguard Worker for (ch = 0; ch < validChannels; ch++) {
804*e5436536SAndroid Build Coastguard Worker AACDEC_DRC_PAYLOAD_TYPE prvPayloadType = UNKNOWN_PAYLOAD;
805*e5436536SAndroid Build Coastguard Worker int mapedChannel = channelMapping[ch];
806*e5436536SAndroid Build Coastguard Worker
807*e5436536SAndroid Build Coastguard Worker if ((mapedChannel >= validChannels) ||
808*e5436536SAndroid Build Coastguard Worker ((exclMask & (1 << mapedChannel)) != 0))
809*e5436536SAndroid Build Coastguard Worker continue;
810*e5436536SAndroid Build Coastguard Worker
811*e5436536SAndroid Build Coastguard Worker if ((pParams->expiryFrame <= 0) ||
812*e5436536SAndroid Build Coastguard Worker (pAacDecoderStaticChannelInfo[ch]->drcData.expiryCount <
813*e5436536SAndroid Build Coastguard Worker pParams->expiryFrame)) {
814*e5436536SAndroid Build Coastguard Worker prvPayloadType =
815*e5436536SAndroid Build Coastguard Worker (AACDEC_DRC_PAYLOAD_TYPE)pAacDecoderStaticChannelInfo[ch]
816*e5436536SAndroid Build Coastguard Worker ->drcData.drcDataType;
817*e5436536SAndroid Build Coastguard Worker }
818*e5436536SAndroid Build Coastguard Worker if (((drcPayloadType == MPEG_DRC_EXT_DATA) &&
819*e5436536SAndroid Build Coastguard Worker (prvPayloadType != DVB_DRC_ANC_DATA)) ||
820*e5436536SAndroid Build Coastguard Worker ((drcPayloadType == DVB_DRC_ANC_DATA) &&
821*e5436536SAndroid Build Coastguard Worker (pParams->applyHeavyCompression ==
822*e5436536SAndroid Build Coastguard Worker ON))) { /* copy thread to channel */
823*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
824*e5436536SAndroid Build Coastguard Worker result = 1;
825*e5436536SAndroid Build Coastguard Worker }
826*e5436536SAndroid Build Coastguard Worker }
827*e5436536SAndroid Build Coastguard Worker /* CCEs not supported by now */
828*e5436536SAndroid Build Coastguard Worker }
829*e5436536SAndroid Build Coastguard Worker
830*e5436536SAndroid Build Coastguard Worker /* Increment and check expiry counter for the program reference level: */
831*e5436536SAndroid Build Coastguard Worker if ((pParams->expiryFrame > 0) &&
832*e5436536SAndroid Build Coastguard Worker (self->prlExpiryCount++ >
833*e5436536SAndroid Build Coastguard Worker pParams->expiryFrame)) { /* The program reference level is too old, so
834*e5436536SAndroid Build Coastguard Worker set it back to the target level. */
835*e5436536SAndroid Build Coastguard Worker self->progRefLevelPresent = 0;
836*e5436536SAndroid Build Coastguard Worker self->progRefLevel = pParams->targetRefLevel;
837*e5436536SAndroid Build Coastguard Worker self->prlExpiryCount = 0;
838*e5436536SAndroid Build Coastguard Worker }
839*e5436536SAndroid Build Coastguard Worker
840*e5436536SAndroid Build Coastguard Worker return result;
841*e5436536SAndroid Build Coastguard Worker }
842*e5436536SAndroid Build Coastguard Worker
aacDecoder_drcApply(HANDLE_AAC_DRC self,void * pSbrDec,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CDrcChannelData * pDrcChData,FIXP_DBL * extGain,int ch,int aacFrameSize,int bSbrPresent)843*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec,
844*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
845*e5436536SAndroid Build Coastguard Worker CDrcChannelData *pDrcChData, FIXP_DBL *extGain,
846*e5436536SAndroid Build Coastguard Worker int ch, /* needed only for SBR */
847*e5436536SAndroid Build Coastguard Worker int aacFrameSize, int bSbrPresent) {
848*e5436536SAndroid Build Coastguard Worker int band, bin, numBands;
849*e5436536SAndroid Build Coastguard Worker int bottom = 0;
850*e5436536SAndroid Build Coastguard Worker int modifyBins = 0;
851*e5436536SAndroid Build Coastguard Worker
852*e5436536SAndroid Build Coastguard Worker FIXP_DBL max_mantissa;
853*e5436536SAndroid Build Coastguard Worker INT max_exponent;
854*e5436536SAndroid Build Coastguard Worker
855*e5436536SAndroid Build Coastguard Worker FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f);
856*e5436536SAndroid Build Coastguard Worker INT norm_exponent = 1;
857*e5436536SAndroid Build Coastguard Worker
858*e5436536SAndroid Build Coastguard Worker FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
859*e5436536SAndroid Build Coastguard Worker INT fact_exponent[MAX_DRC_BANDS];
860*e5436536SAndroid Build Coastguard Worker
861*e5436536SAndroid Build Coastguard Worker CDrcParams *pParams = &self->params;
862*e5436536SAndroid Build Coastguard Worker
863*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
864*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
865*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
866*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
867*e5436536SAndroid Build Coastguard Worker
868*e5436536SAndroid Build Coastguard Worker int winSeq = pIcsInfo->WindowSequence;
869*e5436536SAndroid Build Coastguard Worker
870*e5436536SAndroid Build Coastguard Worker /* Increment and check expiry counter */
871*e5436536SAndroid Build Coastguard Worker if ((pParams->expiryFrame > 0) &&
872*e5436536SAndroid Build Coastguard Worker (++pDrcChData->expiryCount >
873*e5436536SAndroid Build Coastguard Worker pParams->expiryFrame)) { /* The DRC data is too old, so delete it. */
874*e5436536SAndroid Build Coastguard Worker aacDecoder_drcInitChannelData(pDrcChData);
875*e5436536SAndroid Build Coastguard Worker }
876*e5436536SAndroid Build Coastguard Worker
877*e5436536SAndroid Build Coastguard Worker if (self->enable != ON) {
878*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcDisable((HANDLE_SBRDECODER)pSbrDec, ch);
879*e5436536SAndroid Build Coastguard Worker if (extGain != NULL) {
880*e5436536SAndroid Build Coastguard Worker INT gainScale = (INT)*extGain;
881*e5436536SAndroid Build Coastguard Worker /* The gain scaling must be passed to the function in the buffer pointed
882*e5436536SAndroid Build Coastguard Worker * on by extGain. */
883*e5436536SAndroid Build Coastguard Worker if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
884*e5436536SAndroid Build Coastguard Worker *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale);
885*e5436536SAndroid Build Coastguard Worker } else {
886*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
887*e5436536SAndroid Build Coastguard Worker }
888*e5436536SAndroid Build Coastguard Worker }
889*e5436536SAndroid Build Coastguard Worker return;
890*e5436536SAndroid Build Coastguard Worker }
891*e5436536SAndroid Build Coastguard Worker
892*e5436536SAndroid Build Coastguard Worker numBands = pDrcChData->numBands;
893*e5436536SAndroid Build Coastguard Worker
894*e5436536SAndroid Build Coastguard Worker /* If program reference normalization is done in the digital domain,
895*e5436536SAndroid Build Coastguard Worker modify factor to perform normalization. prog_ref_level can
896*e5436536SAndroid Build Coastguard Worker alternatively be passed to the system for modification of the level in
897*e5436536SAndroid Build Coastguard Worker the analog domain. Analog level modification avoids problems with
898*e5436536SAndroid Build Coastguard Worker reduced DAC SNR (if signal is attenuated) or clipping (if signal is
899*e5436536SAndroid Build Coastguard Worker boosted) */
900*e5436536SAndroid Build Coastguard Worker
901*e5436536SAndroid Build Coastguard Worker if (pParams->targetRefLevel >= 0) {
902*e5436536SAndroid Build Coastguard Worker /* 0.5^((targetRefLevel - progRefLevel)/24) */
903*e5436536SAndroid Build Coastguard Worker norm_mantissa =
904*e5436536SAndroid Build Coastguard Worker fLdPow(FL2FXCONST_DBL(-1.0), /* log2(0.5) */
905*e5436536SAndroid Build Coastguard Worker 0,
906*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f / 24.0) >> 3) *
907*e5436536SAndroid Build Coastguard Worker (INT)(pParams->targetRefLevel - self->progRefLevel)),
908*e5436536SAndroid Build Coastguard Worker 3, &norm_exponent);
909*e5436536SAndroid Build Coastguard Worker }
910*e5436536SAndroid Build Coastguard Worker /* Always export the normalization gain (if possible). */
911*e5436536SAndroid Build Coastguard Worker if (extGain != NULL) {
912*e5436536SAndroid Build Coastguard Worker INT gainScale = (INT)*extGain;
913*e5436536SAndroid Build Coastguard Worker /* The gain scaling must be passed to the function in the buffer pointed on
914*e5436536SAndroid Build Coastguard Worker * by extGain. */
915*e5436536SAndroid Build Coastguard Worker if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
916*e5436536SAndroid Build Coastguard Worker *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale);
917*e5436536SAndroid Build Coastguard Worker } else {
918*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
919*e5436536SAndroid Build Coastguard Worker }
920*e5436536SAndroid Build Coastguard Worker }
921*e5436536SAndroid Build Coastguard Worker /* Reset normalization gain since this module must not apply it */
922*e5436536SAndroid Build Coastguard Worker norm_mantissa = FL2FXCONST_DBL(0.5f);
923*e5436536SAndroid Build Coastguard Worker norm_exponent = 1;
924*e5436536SAndroid Build Coastguard Worker
925*e5436536SAndroid Build Coastguard Worker /* calc scale factors */
926*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numBands; band++) {
927*e5436536SAndroid Build Coastguard Worker UCHAR drcVal = pDrcChData->drcValue[band];
928*e5436536SAndroid Build Coastguard Worker
929*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
930*e5436536SAndroid Build Coastguard Worker fact_exponent[band] = 1;
931*e5436536SAndroid Build Coastguard Worker
932*e5436536SAndroid Build Coastguard Worker if ((pParams->applyHeavyCompression == ON) &&
933*e5436536SAndroid Build Coastguard Worker ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType ==
934*e5436536SAndroid Build Coastguard Worker DVB_DRC_ANC_DATA)) {
935*e5436536SAndroid Build Coastguard Worker INT compressionFactorVal_e;
936*e5436536SAndroid Build Coastguard Worker int valX, valY;
937*e5436536SAndroid Build Coastguard Worker
938*e5436536SAndroid Build Coastguard Worker valX = drcVal >> 4;
939*e5436536SAndroid Build Coastguard Worker valY = drcVal & 0x0F;
940*e5436536SAndroid Build Coastguard Worker
941*e5436536SAndroid Build Coastguard Worker /* calculate the unscaled heavy compression factor.
942*e5436536SAndroid Build Coastguard Worker compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
943*e5436536SAndroid Build Coastguard Worker range: -48.166 dB to 48.164 dB */
944*e5436536SAndroid Build Coastguard Worker if (drcVal != 0x7F) {
945*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] = fPowInt(
946*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */
947*e5436536SAndroid Build Coastguard Worker 0, valY, &compressionFactorVal_e);
948*e5436536SAndroid Build Coastguard Worker
949*e5436536SAndroid Build Coastguard Worker /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */
950*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] =
951*e5436536SAndroid Build Coastguard Worker fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]);
952*e5436536SAndroid Build Coastguard Worker
953*e5436536SAndroid Build Coastguard Worker fact_exponent[band] =
954*e5436536SAndroid Build Coastguard Worker DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
955*e5436536SAndroid Build Coastguard Worker }
956*e5436536SAndroid Build Coastguard Worker } else if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType ==
957*e5436536SAndroid Build Coastguard Worker MPEG_DRC_EXT_DATA) {
958*e5436536SAndroid Build Coastguard Worker /* apply the scaled dynamic range control words to factor.
959*e5436536SAndroid Build Coastguard Worker * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
960*e5436536SAndroid Build Coastguard Worker * then there is no dynamic range compression
961*e5436536SAndroid Build Coastguard Worker *
962*e5436536SAndroid Build Coastguard Worker * if pDrcChData->drcSgn[band] is
963*e5436536SAndroid Build Coastguard Worker * 1 then gain is < 1 : factor = 2^(-self->cut *
964*e5436536SAndroid Build Coastguard Worker * pDrcChData->drcMag[band] / 24) 0 then gain is > 1 : factor = 2^(
965*e5436536SAndroid Build Coastguard Worker * self->boost * pDrcChData->drcMag[band] / 24)
966*e5436536SAndroid Build Coastguard Worker */
967*e5436536SAndroid Build Coastguard Worker
968*e5436536SAndroid Build Coastguard Worker if ((drcVal & 0x7F) > 0) {
969*e5436536SAndroid Build Coastguard Worker FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost;
970*e5436536SAndroid Build Coastguard Worker
971*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] = f2Pow(
972*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f / 192.0f), tParamVal) *
973*e5436536SAndroid Build Coastguard Worker (drcVal & 0x7F)),
974*e5436536SAndroid Build Coastguard Worker 3 + DRC_PARAM_SCALE, &fact_exponent[band]);
975*e5436536SAndroid Build Coastguard Worker }
976*e5436536SAndroid Build Coastguard Worker }
977*e5436536SAndroid Build Coastguard Worker
978*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa);
979*e5436536SAndroid Build Coastguard Worker fact_exponent[band] += norm_exponent;
980*e5436536SAndroid Build Coastguard Worker
981*e5436536SAndroid Build Coastguard Worker } /* end loop over bands */
982*e5436536SAndroid Build Coastguard Worker
983*e5436536SAndroid Build Coastguard Worker /* normalizations */
984*e5436536SAndroid Build Coastguard Worker {
985*e5436536SAndroid Build Coastguard Worker int res;
986*e5436536SAndroid Build Coastguard Worker
987*e5436536SAndroid Build Coastguard Worker max_mantissa = FL2FXCONST_DBL(0.0f);
988*e5436536SAndroid Build Coastguard Worker max_exponent = 0;
989*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numBands; band++) {
990*e5436536SAndroid Build Coastguard Worker max_mantissa = fixMax(max_mantissa, fact_mantissa[band]);
991*e5436536SAndroid Build Coastguard Worker max_exponent = fixMax(max_exponent, fact_exponent[band]);
992*e5436536SAndroid Build Coastguard Worker }
993*e5436536SAndroid Build Coastguard Worker
994*e5436536SAndroid Build Coastguard Worker /* left shift factors to gain accurancy */
995*e5436536SAndroid Build Coastguard Worker res = CntLeadingZeros(max_mantissa) - 1;
996*e5436536SAndroid Build Coastguard Worker
997*e5436536SAndroid Build Coastguard Worker /* above topmost DRC band gain factor is 1 */
998*e5436536SAndroid Build Coastguard Worker if (((pDrcChData->bandTop[fMax(0, numBands - 1)] + 1) << 2) < aacFrameSize)
999*e5436536SAndroid Build Coastguard Worker res = 0;
1000*e5436536SAndroid Build Coastguard Worker
1001*e5436536SAndroid Build Coastguard Worker if (res > 0) {
1002*e5436536SAndroid Build Coastguard Worker res = fixMin(res, max_exponent);
1003*e5436536SAndroid Build Coastguard Worker max_exponent -= res;
1004*e5436536SAndroid Build Coastguard Worker
1005*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numBands; band++) {
1006*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] <<= res;
1007*e5436536SAndroid Build Coastguard Worker fact_exponent[band] -= res;
1008*e5436536SAndroid Build Coastguard Worker }
1009*e5436536SAndroid Build Coastguard Worker }
1010*e5436536SAndroid Build Coastguard Worker
1011*e5436536SAndroid Build Coastguard Worker /* normalize magnitudes to one scale factor */
1012*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numBands; band++) {
1013*e5436536SAndroid Build Coastguard Worker if (fact_exponent[band] < max_exponent) {
1014*e5436536SAndroid Build Coastguard Worker fact_mantissa[band] >>= max_exponent - fact_exponent[band];
1015*e5436536SAndroid Build Coastguard Worker }
1016*e5436536SAndroid Build Coastguard Worker if (fact_mantissa[band] != FL2FXCONST_DBL(0.5f)) {
1017*e5436536SAndroid Build Coastguard Worker modifyBins = 1;
1018*e5436536SAndroid Build Coastguard Worker }
1019*e5436536SAndroid Build Coastguard Worker }
1020*e5436536SAndroid Build Coastguard Worker if (max_exponent != 1) {
1021*e5436536SAndroid Build Coastguard Worker modifyBins = 1;
1022*e5436536SAndroid Build Coastguard Worker }
1023*e5436536SAndroid Build Coastguard Worker }
1024*e5436536SAndroid Build Coastguard Worker
1025*e5436536SAndroid Build Coastguard Worker /* apply factor to spectral lines
1026*e5436536SAndroid Build Coastguard Worker * short blocks must take care that bands fall on
1027*e5436536SAndroid Build Coastguard Worker * block boundaries!
1028*e5436536SAndroid Build Coastguard Worker */
1029*e5436536SAndroid Build Coastguard Worker if (!bSbrPresent) {
1030*e5436536SAndroid Build Coastguard Worker bottom = 0;
1031*e5436536SAndroid Build Coastguard Worker
1032*e5436536SAndroid Build Coastguard Worker if (!modifyBins) {
1033*e5436536SAndroid Build Coastguard Worker /* We don't have to modify the spectral bins because the fractional part
1034*e5436536SAndroid Build Coastguard Worker of all factors is 0.5. In order to keep accurancy we don't apply the
1035*e5436536SAndroid Build Coastguard Worker factor but decrease the exponent instead. */
1036*e5436536SAndroid Build Coastguard Worker max_exponent -= 1;
1037*e5436536SAndroid Build Coastguard Worker } else {
1038*e5436536SAndroid Build Coastguard Worker for (band = 0; band < numBands; band++) {
1039*e5436536SAndroid Build Coastguard Worker int top = fixMin((int)((pDrcChData->bandTop[band] + 1) << 2),
1040*e5436536SAndroid Build Coastguard Worker aacFrameSize); /* ... * DRC_BAND_MULT; */
1041*e5436536SAndroid Build Coastguard Worker
1042*e5436536SAndroid Build Coastguard Worker for (bin = bottom; bin < top; bin++) {
1043*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient[bin] =
1044*e5436536SAndroid Build Coastguard Worker fMult(pSpectralCoefficient[bin], fact_mantissa[band]);
1045*e5436536SAndroid Build Coastguard Worker }
1046*e5436536SAndroid Build Coastguard Worker
1047*e5436536SAndroid Build Coastguard Worker bottom = top;
1048*e5436536SAndroid Build Coastguard Worker }
1049*e5436536SAndroid Build Coastguard Worker }
1050*e5436536SAndroid Build Coastguard Worker
1051*e5436536SAndroid Build Coastguard Worker /* above topmost DRC band gain factor is 1 */
1052*e5436536SAndroid Build Coastguard Worker if (max_exponent > 0) {
1053*e5436536SAndroid Build Coastguard Worker for (bin = bottom; bin < aacFrameSize; bin += 1) {
1054*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient[bin] >>= max_exponent;
1055*e5436536SAndroid Build Coastguard Worker }
1056*e5436536SAndroid Build Coastguard Worker }
1057*e5436536SAndroid Build Coastguard Worker
1058*e5436536SAndroid Build Coastguard Worker /* adjust scaling */
1059*e5436536SAndroid Build Coastguard Worker pSpecScale[0] += max_exponent;
1060*e5436536SAndroid Build Coastguard Worker
1061*e5436536SAndroid Build Coastguard Worker if (winSeq == BLOCK_SHORT) {
1062*e5436536SAndroid Build Coastguard Worker int win;
1063*e5436536SAndroid Build Coastguard Worker for (win = 1; win < 8; win++) {
1064*e5436536SAndroid Build Coastguard Worker pSpecScale[win] += max_exponent;
1065*e5436536SAndroid Build Coastguard Worker }
1066*e5436536SAndroid Build Coastguard Worker }
1067*e5436536SAndroid Build Coastguard Worker } else {
1068*e5436536SAndroid Build Coastguard Worker HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec;
1069*e5436536SAndroid Build Coastguard Worker numBands = pDrcChData->numBands;
1070*e5436536SAndroid Build Coastguard Worker
1071*e5436536SAndroid Build Coastguard Worker /* feed factors into SBR decoder for application in QMF domain. */
1072*e5436536SAndroid Build Coastguard Worker sbrDecoder_drcFeedChannel(hSbrDecoder, ch, numBands, fact_mantissa,
1073*e5436536SAndroid Build Coastguard Worker max_exponent, pDrcChData->drcInterpolationScheme,
1074*e5436536SAndroid Build Coastguard Worker winSeq, pDrcChData->bandTop);
1075*e5436536SAndroid Build Coastguard Worker }
1076*e5436536SAndroid Build Coastguard Worker
1077*e5436536SAndroid Build Coastguard Worker return;
1078*e5436536SAndroid Build Coastguard Worker }
1079*e5436536SAndroid Build Coastguard Worker
1080*e5436536SAndroid Build Coastguard Worker /*
1081*e5436536SAndroid Build Coastguard Worker * DRC parameter and presentation mode handling
1082*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcParameterHandling(HANDLE_AAC_DRC self,INT aacNumChannels,SCHAR prevDrcProgRefLevel,SCHAR prevDrcPresMode)1083*e5436536SAndroid Build Coastguard Worker static void aacDecoder_drcParameterHandling(HANDLE_AAC_DRC self,
1084*e5436536SAndroid Build Coastguard Worker INT aacNumChannels,
1085*e5436536SAndroid Build Coastguard Worker SCHAR prevDrcProgRefLevel,
1086*e5436536SAndroid Build Coastguard Worker SCHAR prevDrcPresMode) {
1087*e5436536SAndroid Build Coastguard Worker int isDownmix, isMonoDownmix, isStereoDownmix;
1088*e5436536SAndroid Build Coastguard Worker int dDmx, dHr;
1089*e5436536SAndroid Build Coastguard Worker AACDEC_DRC_PARAMETER_HANDLING drcParameterHandling;
1090*e5436536SAndroid Build Coastguard Worker CDrcParams *p;
1091*e5436536SAndroid Build Coastguard Worker
1092*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(self != NULL);
1093*e5436536SAndroid Build Coastguard Worker
1094*e5436536SAndroid Build Coastguard Worker p = &self->params;
1095*e5436536SAndroid Build Coastguard Worker
1096*e5436536SAndroid Build Coastguard Worker if (self->progRefLevel != prevDrcProgRefLevel) self->update = 1;
1097*e5436536SAndroid Build Coastguard Worker
1098*e5436536SAndroid Build Coastguard Worker if (self->presMode != prevDrcPresMode) self->update = 1;
1099*e5436536SAndroid Build Coastguard Worker
1100*e5436536SAndroid Build Coastguard Worker if (self->prevAacNumChannels != aacNumChannels) self->update = 1;
1101*e5436536SAndroid Build Coastguard Worker
1102*e5436536SAndroid Build Coastguard Worker /* return if no relevant parameter has changed */
1103*e5436536SAndroid Build Coastguard Worker if (!self->update) {
1104*e5436536SAndroid Build Coastguard Worker return;
1105*e5436536SAndroid Build Coastguard Worker }
1106*e5436536SAndroid Build Coastguard Worker
1107*e5436536SAndroid Build Coastguard Worker /* derive downmix property. aacNumChannels: number of channels in aac stream,
1108*e5436536SAndroid Build Coastguard Worker * numOutChannels: number of output channels */
1109*e5436536SAndroid Build Coastguard Worker isDownmix = (aacNumChannels > self->numOutChannels);
1110*e5436536SAndroid Build Coastguard Worker isDownmix = (isDownmix && (self->numOutChannels > 0));
1111*e5436536SAndroid Build Coastguard Worker isMonoDownmix = (isDownmix && (self->numOutChannels == 1));
1112*e5436536SAndroid Build Coastguard Worker isStereoDownmix = (isDownmix && (self->numOutChannels == 2));
1113*e5436536SAndroid Build Coastguard Worker
1114*e5436536SAndroid Build Coastguard Worker if ((self->presMode == 1) || (self->presMode == 2)) {
1115*e5436536SAndroid Build Coastguard Worker drcParameterHandling = (AACDEC_DRC_PARAMETER_HANDLING)self->presMode;
1116*e5436536SAndroid Build Coastguard Worker } else { /* no presentation mode -> use parameter handling specified by
1117*e5436536SAndroid Build Coastguard Worker AAC_DRC_DEFAULT_PRESENTATION_MODE */
1118*e5436536SAndroid Build Coastguard Worker drcParameterHandling = p->defaultPresentationMode;
1119*e5436536SAndroid Build Coastguard Worker }
1120*e5436536SAndroid Build Coastguard Worker
1121*e5436536SAndroid Build Coastguard Worker /* by default, do as desired */
1122*e5436536SAndroid Build Coastguard Worker p->cut = p->usrCut;
1123*e5436536SAndroid Build Coastguard Worker p->boost = p->usrBoost;
1124*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = p->usrApplyHeavyCompression;
1125*e5436536SAndroid Build Coastguard Worker
1126*e5436536SAndroid Build Coastguard Worker switch (drcParameterHandling) {
1127*e5436536SAndroid Build Coastguard Worker case DISABLED_PARAMETER_HANDLING:
1128*e5436536SAndroid Build Coastguard Worker default:
1129*e5436536SAndroid Build Coastguard Worker /* use drc parameters as requested */
1130*e5436536SAndroid Build Coastguard Worker break;
1131*e5436536SAndroid Build Coastguard Worker
1132*e5436536SAndroid Build Coastguard Worker case ENABLED_PARAMETER_HANDLING:
1133*e5436536SAndroid Build Coastguard Worker /* dDmx: estimated headroom reduction due to downmix, format: -1/4*dB
1134*e5436536SAndroid Build Coastguard Worker dDmx = floor(-4*20*log10(aacNumChannels/numOutChannels)) */
1135*e5436536SAndroid Build Coastguard Worker if (isDownmix) {
1136*e5436536SAndroid Build Coastguard Worker FIXP_DBL dmxTmp;
1137*e5436536SAndroid Build Coastguard Worker int e_log, e_mult;
1138*e5436536SAndroid Build Coastguard Worker dmxTmp = fDivNorm(self->numOutChannels,
1139*e5436536SAndroid Build Coastguard Worker aacNumChannels); /* inverse division ->
1140*e5436536SAndroid Build Coastguard Worker negative sign after
1141*e5436536SAndroid Build Coastguard Worker logarithm */
1142*e5436536SAndroid Build Coastguard Worker dmxTmp = fLog2(dmxTmp, 0, &e_log);
1143*e5436536SAndroid Build Coastguard Worker dmxTmp = fMultNorm(
1144*e5436536SAndroid Build Coastguard Worker dmxTmp, FL2FXCONST_DBL(4.0f * 20.0f * 0.30103f / (float)(1 << 5)),
1145*e5436536SAndroid Build Coastguard Worker &e_mult); /* e = e_log + e_mult + 5 */
1146*e5436536SAndroid Build Coastguard Worker dDmx = (int)scaleValue(dmxTmp, e_log + e_mult + 5 - (DFRACT_BITS - 1));
1147*e5436536SAndroid Build Coastguard Worker } else {
1148*e5436536SAndroid Build Coastguard Worker dDmx = 0;
1149*e5436536SAndroid Build Coastguard Worker }
1150*e5436536SAndroid Build Coastguard Worker
1151*e5436536SAndroid Build Coastguard Worker /* dHr: Full estimated (decoder) headroom reduction due to loudness
1152*e5436536SAndroid Build Coastguard Worker * normalisation (DTL - PRL) and downmix. Format: -1/4*dB */
1153*e5436536SAndroid Build Coastguard Worker if (p->targetRefLevel >= 0) { /* if target level is provided */
1154*e5436536SAndroid Build Coastguard Worker dHr = p->targetRefLevel + dDmx - self->progRefLevel;
1155*e5436536SAndroid Build Coastguard Worker } else {
1156*e5436536SAndroid Build Coastguard Worker dHr = dDmx;
1157*e5436536SAndroid Build Coastguard Worker }
1158*e5436536SAndroid Build Coastguard Worker
1159*e5436536SAndroid Build Coastguard Worker if (dHr < 0) { /* if headroom is reduced */
1160*e5436536SAndroid Build Coastguard Worker /* Use compression, but as little as possible. */
1161*e5436536SAndroid Build Coastguard Worker /* eHr: Headroom provided by encoder, format: -1/4 dB */
1162*e5436536SAndroid Build Coastguard Worker int eHr = fixMin(p->encoderTargetLevel - self->progRefLevel, 0);
1163*e5436536SAndroid Build Coastguard Worker if (eHr <
1164*e5436536SAndroid Build Coastguard Worker dHr) { /* if encoder provides more headroom than decoder needs */
1165*e5436536SAndroid Build Coastguard Worker /* derive scaling of light DRC */
1166*e5436536SAndroid Build Coastguard Worker FIXP_DBL calcFactor_norm;
1167*e5436536SAndroid Build Coastguard Worker INT calcFactor; /* fraction of DRC gains that is minimally needed for
1168*e5436536SAndroid Build Coastguard Worker clipping prevention */
1169*e5436536SAndroid Build Coastguard Worker calcFactor_norm =
1170*e5436536SAndroid Build Coastguard Worker fDivNorm(-dHr, -eHr); /* 0.0 < calcFactor_norm < 1.0 */
1171*e5436536SAndroid Build Coastguard Worker calcFactor_norm = calcFactor_norm >> DRC_PARAM_SCALE;
1172*e5436536SAndroid Build Coastguard Worker /* quantize to 128 steps */
1173*e5436536SAndroid Build Coastguard Worker calcFactor = convert_drcParam(
1174*e5436536SAndroid Build Coastguard Worker calcFactor_norm); /* convert to integer value between 0 and 127 */
1175*e5436536SAndroid Build Coastguard Worker calcFactor_norm = (FIXP_DBL)(
1176*e5436536SAndroid Build Coastguard Worker (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * calcFactor);
1177*e5436536SAndroid Build Coastguard Worker p->cut = (calcFactor_norm > p->cut)
1178*e5436536SAndroid Build Coastguard Worker ? calcFactor_norm
1179*e5436536SAndroid Build Coastguard Worker : p->cut; /* use calcFactor_norm as lower limit */
1180*e5436536SAndroid Build Coastguard Worker } else {
1181*e5436536SAndroid Build Coastguard Worker /* encoder provides equal or less headroom than decoder needs */
1182*e5436536SAndroid Build Coastguard Worker /* the time domain limiter must always be active in this case. It is
1183*e5436536SAndroid Build Coastguard Worker * assumed that the framework activates it by default */
1184*e5436536SAndroid Build Coastguard Worker p->cut = DRC_SCALING_MAX;
1185*e5436536SAndroid Build Coastguard Worker if ((dHr - eHr) <=
1186*e5436536SAndroid Build Coastguard Worker -4 * DRC_HEAVY_THRESHOLD_DB) { /* use heavy compression if
1187*e5436536SAndroid Build Coastguard Worker headroom deficit is equal or
1188*e5436536SAndroid Build Coastguard Worker higher than
1189*e5436536SAndroid Build Coastguard Worker DRC_HEAVY_THRESHOLD_DB */
1190*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = ON;
1191*e5436536SAndroid Build Coastguard Worker }
1192*e5436536SAndroid Build Coastguard Worker }
1193*e5436536SAndroid Build Coastguard Worker } else { /* dHr >= 0 */
1194*e5436536SAndroid Build Coastguard Worker /* no restrictions required, as headroom is not reduced. */
1195*e5436536SAndroid Build Coastguard Worker /* p->cut = p->usrCut; */
1196*e5436536SAndroid Build Coastguard Worker }
1197*e5436536SAndroid Build Coastguard Worker break;
1198*e5436536SAndroid Build Coastguard Worker
1199*e5436536SAndroid Build Coastguard Worker /* presentation mode 1 and 2 according to ETSI TS 101 154:
1200*e5436536SAndroid Build Coastguard Worker Digital Video Broadcasting (DVB); Specification for the use of Video
1201*e5436536SAndroid Build Coastguard Worker and Audio Coding in Broadcasting Applications based on the MPEG-2
1202*e5436536SAndroid Build Coastguard Worker Transport Stream, section C.5.4., "Decoding", and Table C.33. Also
1203*e5436536SAndroid Build Coastguard Worker according to amendment 4 to ISO/IEC 14496-3, section 4.5.2.14.2.4, and
1204*e5436536SAndroid Build Coastguard Worker Table AMD4.11. ISO DRC -> applyHeavyCompression = OFF (Use
1205*e5436536SAndroid Build Coastguard Worker light compression, MPEG-style) Compression_value ->
1206*e5436536SAndroid Build Coastguard Worker applyHeavyCompression = ON (Use heavy compression, DVB-style) scaling
1207*e5436536SAndroid Build Coastguard Worker restricted -> p->cut = DRC_SCALING_MAX */
1208*e5436536SAndroid Build Coastguard Worker
1209*e5436536SAndroid Build Coastguard Worker case DRC_PRESENTATION_MODE_1: /* presentation mode 1, Light:-31/Heavy:-23 */
1210*e5436536SAndroid Build Coastguard Worker if ((p->targetRefLevel >= 0) &&
1211*e5436536SAndroid Build Coastguard Worker (p->targetRefLevel <
1212*e5436536SAndroid Build Coastguard Worker 124)) { /* if target level is provided and > -31 dB */
1213*e5436536SAndroid Build Coastguard Worker /* playback up to -23 dB */
1214*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = ON;
1215*e5436536SAndroid Build Coastguard Worker } else { /* target level <= -31 dB or not provided */
1216*e5436536SAndroid Build Coastguard Worker /* playback -31 dB */
1217*e5436536SAndroid Build Coastguard Worker if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */
1218*e5436536SAndroid Build Coastguard Worker p->cut = DRC_SCALING_MAX;
1219*e5436536SAndroid Build Coastguard Worker }
1220*e5436536SAndroid Build Coastguard Worker }
1221*e5436536SAndroid Build Coastguard Worker break;
1222*e5436536SAndroid Build Coastguard Worker
1223*e5436536SAndroid Build Coastguard Worker case DRC_PRESENTATION_MODE_2: /* presentation mode 2, Light:-23/Heavy:-23 */
1224*e5436536SAndroid Build Coastguard Worker if ((p->targetRefLevel >= 0) &&
1225*e5436536SAndroid Build Coastguard Worker (p->targetRefLevel <
1226*e5436536SAndroid Build Coastguard Worker 124)) { /* if target level is provided and > -31 dB */
1227*e5436536SAndroid Build Coastguard Worker /* playback up to -23 dB */
1228*e5436536SAndroid Build Coastguard Worker if (isMonoDownmix) { /* if mono downmix */
1229*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = ON;
1230*e5436536SAndroid Build Coastguard Worker } else {
1231*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = OFF;
1232*e5436536SAndroid Build Coastguard Worker p->cut = DRC_SCALING_MAX;
1233*e5436536SAndroid Build Coastguard Worker }
1234*e5436536SAndroid Build Coastguard Worker } else { /* target level <= -31 dB or not provided */
1235*e5436536SAndroid Build Coastguard Worker /* playback -31 dB */
1236*e5436536SAndroid Build Coastguard Worker p->applyHeavyCompression = OFF;
1237*e5436536SAndroid Build Coastguard Worker if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */
1238*e5436536SAndroid Build Coastguard Worker p->cut = DRC_SCALING_MAX;
1239*e5436536SAndroid Build Coastguard Worker }
1240*e5436536SAndroid Build Coastguard Worker }
1241*e5436536SAndroid Build Coastguard Worker break;
1242*e5436536SAndroid Build Coastguard Worker } /* switch (drcParameterHandling) */
1243*e5436536SAndroid Build Coastguard Worker
1244*e5436536SAndroid Build Coastguard Worker /* With heavy compression, there is no scaling.
1245*e5436536SAndroid Build Coastguard Worker Scaling factors are set for notification only. */
1246*e5436536SAndroid Build Coastguard Worker if (p->applyHeavyCompression == ON) {
1247*e5436536SAndroid Build Coastguard Worker p->boost = DRC_SCALING_MAX;
1248*e5436536SAndroid Build Coastguard Worker p->cut = DRC_SCALING_MAX;
1249*e5436536SAndroid Build Coastguard Worker }
1250*e5436536SAndroid Build Coastguard Worker
1251*e5436536SAndroid Build Coastguard Worker /* switch on/off processing */
1252*e5436536SAndroid Build Coastguard Worker self->enable = ((p->boost > (FIXP_DBL)0) || (p->cut > (FIXP_DBL)0) ||
1253*e5436536SAndroid Build Coastguard Worker (p->applyHeavyCompression == ON) || (p->targetRefLevel >= 0));
1254*e5436536SAndroid Build Coastguard Worker
1255*e5436536SAndroid Build Coastguard Worker self->prevAacNumChannels = aacNumChannels;
1256*e5436536SAndroid Build Coastguard Worker self->update = 0;
1257*e5436536SAndroid Build Coastguard Worker }
1258*e5436536SAndroid Build Coastguard Worker
1259*e5436536SAndroid Build Coastguard Worker /*
1260*e5436536SAndroid Build Coastguard Worker * Prepare DRC processing
1261*e5436536SAndroid Build Coastguard Worker * Valid return values are:
1262*e5436536SAndroid Build Coastguard Worker * -1 : An unexpected error occured.
1263*e5436536SAndroid Build Coastguard Worker * 0 : No error and no valid DRC data available.
1264*e5436536SAndroid Build Coastguard Worker * 1 : No error and valid DRC data has been mapped.
1265*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcProlog(HANDLE_AAC_DRC self,HANDLE_FDK_BITSTREAM hBs,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo[],UCHAR pceInstanceTag,UCHAR channelMapping[],int validChannels)1266*e5436536SAndroid Build Coastguard Worker int aacDecoder_drcProlog(
1267*e5436536SAndroid Build Coastguard Worker HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs,
1268*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
1269*e5436536SAndroid Build Coastguard Worker UCHAR pceInstanceTag,
1270*e5436536SAndroid Build Coastguard Worker UCHAR channelMapping[], /* Channel mapping translating drcChannel index to
1271*e5436536SAndroid Build Coastguard Worker canonical channel index */
1272*e5436536SAndroid Build Coastguard Worker int validChannels) {
1273*e5436536SAndroid Build Coastguard Worker int result = 0;
1274*e5436536SAndroid Build Coastguard Worker
1275*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
1276*e5436536SAndroid Build Coastguard Worker return -1;
1277*e5436536SAndroid Build Coastguard Worker }
1278*e5436536SAndroid Build Coastguard Worker
1279*e5436536SAndroid Build Coastguard Worker if (!self->params.bsDelayEnable) {
1280*e5436536SAndroid Build Coastguard Worker /* keep previous progRefLevel and presMode for update flag in
1281*e5436536SAndroid Build Coastguard Worker * drcParameterHandling */
1282*e5436536SAndroid Build Coastguard Worker INT prevPRL, prevPM = 0;
1283*e5436536SAndroid Build Coastguard Worker prevPRL = self->progRefLevel;
1284*e5436536SAndroid Build Coastguard Worker prevPM = self->presMode;
1285*e5436536SAndroid Build Coastguard Worker
1286*e5436536SAndroid Build Coastguard Worker result = aacDecoder_drcExtractAndMap(
1287*e5436536SAndroid Build Coastguard Worker self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping,
1288*e5436536SAndroid Build Coastguard Worker validChannels);
1289*e5436536SAndroid Build Coastguard Worker
1290*e5436536SAndroid Build Coastguard Worker if (result < 0) {
1291*e5436536SAndroid Build Coastguard Worker return result;
1292*e5436536SAndroid Build Coastguard Worker }
1293*e5436536SAndroid Build Coastguard Worker
1294*e5436536SAndroid Build Coastguard Worker /* Drc parameter handling */
1295*e5436536SAndroid Build Coastguard Worker aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM);
1296*e5436536SAndroid Build Coastguard Worker }
1297*e5436536SAndroid Build Coastguard Worker
1298*e5436536SAndroid Build Coastguard Worker return result;
1299*e5436536SAndroid Build Coastguard Worker }
1300*e5436536SAndroid Build Coastguard Worker
1301*e5436536SAndroid Build Coastguard Worker /*
1302*e5436536SAndroid Build Coastguard Worker * Finalize DRC processing
1303*e5436536SAndroid Build Coastguard Worker * Valid return values are:
1304*e5436536SAndroid Build Coastguard Worker * -1 : An unexpected error occured.
1305*e5436536SAndroid Build Coastguard Worker * 0 : No error and no valid DRC data available.
1306*e5436536SAndroid Build Coastguard Worker * 1 : No error and valid DRC data has been mapped.
1307*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcEpilog(HANDLE_AAC_DRC self,HANDLE_FDK_BITSTREAM hBs,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo[],UCHAR pceInstanceTag,UCHAR channelMapping[],int validChannels)1308*e5436536SAndroid Build Coastguard Worker int aacDecoder_drcEpilog(
1309*e5436536SAndroid Build Coastguard Worker HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs,
1310*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
1311*e5436536SAndroid Build Coastguard Worker UCHAR pceInstanceTag,
1312*e5436536SAndroid Build Coastguard Worker UCHAR channelMapping[], /* Channel mapping translating drcChannel index to
1313*e5436536SAndroid Build Coastguard Worker canonical channel index */
1314*e5436536SAndroid Build Coastguard Worker int validChannels) {
1315*e5436536SAndroid Build Coastguard Worker int result = 0;
1316*e5436536SAndroid Build Coastguard Worker
1317*e5436536SAndroid Build Coastguard Worker if (self == NULL) {
1318*e5436536SAndroid Build Coastguard Worker return -1;
1319*e5436536SAndroid Build Coastguard Worker }
1320*e5436536SAndroid Build Coastguard Worker
1321*e5436536SAndroid Build Coastguard Worker if (self->params.bsDelayEnable) {
1322*e5436536SAndroid Build Coastguard Worker /* keep previous progRefLevel and presMode for update flag in
1323*e5436536SAndroid Build Coastguard Worker * drcParameterHandling */
1324*e5436536SAndroid Build Coastguard Worker INT prevPRL, prevPM = 0;
1325*e5436536SAndroid Build Coastguard Worker prevPRL = self->progRefLevel;
1326*e5436536SAndroid Build Coastguard Worker prevPM = self->presMode;
1327*e5436536SAndroid Build Coastguard Worker
1328*e5436536SAndroid Build Coastguard Worker result = aacDecoder_drcExtractAndMap(
1329*e5436536SAndroid Build Coastguard Worker self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping,
1330*e5436536SAndroid Build Coastguard Worker validChannels);
1331*e5436536SAndroid Build Coastguard Worker
1332*e5436536SAndroid Build Coastguard Worker if (result < 0) {
1333*e5436536SAndroid Build Coastguard Worker return result;
1334*e5436536SAndroid Build Coastguard Worker }
1335*e5436536SAndroid Build Coastguard Worker
1336*e5436536SAndroid Build Coastguard Worker /* Drc parameter handling */
1337*e5436536SAndroid Build Coastguard Worker aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM);
1338*e5436536SAndroid Build Coastguard Worker }
1339*e5436536SAndroid Build Coastguard Worker
1340*e5436536SAndroid Build Coastguard Worker return result;
1341*e5436536SAndroid Build Coastguard Worker }
1342*e5436536SAndroid Build Coastguard Worker
1343*e5436536SAndroid Build Coastguard Worker /*
1344*e5436536SAndroid Build Coastguard Worker * Export relevant metadata info from bitstream payload.
1345*e5436536SAndroid Build Coastguard Worker */
aacDecoder_drcGetInfo(HANDLE_AAC_DRC self,SCHAR * pPresMode,SCHAR * pProgRefLevel)1346*e5436536SAndroid Build Coastguard Worker void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode,
1347*e5436536SAndroid Build Coastguard Worker SCHAR *pProgRefLevel) {
1348*e5436536SAndroid Build Coastguard Worker if (self != NULL) {
1349*e5436536SAndroid Build Coastguard Worker if (pPresMode != NULL) {
1350*e5436536SAndroid Build Coastguard Worker *pPresMode = self->presMode;
1351*e5436536SAndroid Build Coastguard Worker }
1352*e5436536SAndroid Build Coastguard Worker if (pProgRefLevel != NULL) {
1353*e5436536SAndroid Build Coastguard Worker if (self->progRefLevelPresent) {
1354*e5436536SAndroid Build Coastguard Worker *pProgRefLevel = self->progRefLevel;
1355*e5436536SAndroid Build Coastguard Worker } else {
1356*e5436536SAndroid Build Coastguard Worker *pProgRefLevel = -1;
1357*e5436536SAndroid Build Coastguard Worker }
1358*e5436536SAndroid Build Coastguard Worker }
1359*e5436536SAndroid Build Coastguard Worker }
1360*e5436536SAndroid Build Coastguard Worker }
1361*e5436536SAndroid Build Coastguard Worker
1362*e5436536SAndroid Build Coastguard Worker /**
1363*e5436536SAndroid Build Coastguard Worker * \brief Apply DRC Level Normalization.
1364*e5436536SAndroid Build Coastguard Worker *
1365*e5436536SAndroid Build Coastguard Worker * This function prepares/applies the gain values for the DRC Level
1366*e5436536SAndroid Build Coastguard Worker * Normalization and returns the exponent of the time data. The following two
1367*e5436536SAndroid Build Coastguard Worker * cases are handled:
1368*e5436536SAndroid Build Coastguard Worker *
1369*e5436536SAndroid Build Coastguard Worker * - Limiter enabled:
1370*e5436536SAndroid Build Coastguard Worker * The input data must be interleaved.
1371*e5436536SAndroid Build Coastguard Worker * One gain per sample is written to the buffer pGainPerSample.
1372*e5436536SAndroid Build Coastguard Worker * If necessary the time data is rescaled.
1373*e5436536SAndroid Build Coastguard Worker *
1374*e5436536SAndroid Build Coastguard Worker * - Limiter disabled:
1375*e5436536SAndroid Build Coastguard Worker * The input data can be interleaved or deinterleaved.
1376*e5436536SAndroid Build Coastguard Worker * The gain values are applied to the time data.
1377*e5436536SAndroid Build Coastguard Worker * If necessary the time data is rescaled.
1378*e5436536SAndroid Build Coastguard Worker *
1379*e5436536SAndroid Build Coastguard Worker * \param hDrcInfo [i/o] handle to drc data structure.
1380*e5436536SAndroid Build Coastguard Worker * \param samplesIn [i/o] pointer to time data.
1381*e5436536SAndroid Build Coastguard Worker * \param pGain [i ] pointer to gain to be applied to
1382*e5436536SAndroid Build Coastguard Worker * the time data.
1383*e5436536SAndroid Build Coastguard Worker * \param pGainPerSample [o ] pointer to the gain per sample to
1384*e5436536SAndroid Build Coastguard Worker * be applied to the time data in the limiter.
1385*e5436536SAndroid Build Coastguard Worker * \param gain_scale [i ] exponent to be applied to the time
1386*e5436536SAndroid Build Coastguard Worker * data.
1387*e5436536SAndroid Build Coastguard Worker * \param gain_delay [i ] delay[samples] with which the gains
1388*e5436536SAndroid Build Coastguard Worker * in pGain shall be applied (gain_delay <= nSamples).
1389*e5436536SAndroid Build Coastguard Worker * \param nSamples [i ] number of samples per frame.
1390*e5436536SAndroid Build Coastguard Worker * \param channels [i ] number of channels.
1391*e5436536SAndroid Build Coastguard Worker * \param stride [i ] channel stride of time data.
1392*e5436536SAndroid Build Coastguard Worker * \param limiterEnabled [i ] 1 if limiter is enabled, otherwise
1393*e5436536SAndroid Build Coastguard Worker * 0.
1394*e5436536SAndroid Build Coastguard Worker *
1395*e5436536SAndroid Build Coastguard Worker * \return exponent of time data
1396*e5436536SAndroid Build Coastguard Worker */
applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo,PCM_DEC * samplesIn,FIXP_DBL * pGain,FIXP_DBL * pGainPerSample,const INT gain_scale,const UINT gain_delay,const UINT nSamples,const UINT channels,const UINT stride,const UINT limiterEnabled)1397*e5436536SAndroid Build Coastguard Worker INT applyDrcLevelNormalization(HANDLE_AAC_DRC hDrcInfo, PCM_DEC *samplesIn,
1398*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pGain, FIXP_DBL *pGainPerSample,
1399*e5436536SAndroid Build Coastguard Worker const INT gain_scale, const UINT gain_delay,
1400*e5436536SAndroid Build Coastguard Worker const UINT nSamples, const UINT channels,
1401*e5436536SAndroid Build Coastguard Worker const UINT stride, const UINT limiterEnabled) {
1402*e5436536SAndroid Build Coastguard Worker UINT i;
1403*e5436536SAndroid Build Coastguard Worker INT additionalGain_scaling;
1404*e5436536SAndroid Build Coastguard Worker FIXP_DBL additionalGain;
1405*e5436536SAndroid Build Coastguard Worker
1406*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(gain_delay <= nSamples);
1407*e5436536SAndroid Build Coastguard Worker
1408*e5436536SAndroid Build Coastguard Worker FIXP_DBL additionalGainSmoothState = hDrcInfo->additionalGainFilterState;
1409*e5436536SAndroid Build Coastguard Worker FIXP_DBL additionalGainSmoothState1 = hDrcInfo->additionalGainFilterState1;
1410*e5436536SAndroid Build Coastguard Worker
1411*e5436536SAndroid Build Coastguard Worker if (!gain_delay) {
1412*e5436536SAndroid Build Coastguard Worker additionalGain = pGain[0];
1413*e5436536SAndroid Build Coastguard Worker
1414*e5436536SAndroid Build Coastguard Worker /* Apply the additional scaling gain_scale[0] that has no delay and no
1415*e5436536SAndroid Build Coastguard Worker * smoothing */
1416*e5436536SAndroid Build Coastguard Worker additionalGain_scaling =
1417*e5436536SAndroid Build Coastguard Worker fMin(gain_scale, CntLeadingZeros(additionalGain) - 1);
1418*e5436536SAndroid Build Coastguard Worker additionalGain = scaleValue(additionalGain, additionalGain_scaling);
1419*e5436536SAndroid Build Coastguard Worker
1420*e5436536SAndroid Build Coastguard Worker /* if it's not possible to fully apply gain_scale to additionalGain, apply
1421*e5436536SAndroid Build Coastguard Worker * it to the input signal */
1422*e5436536SAndroid Build Coastguard Worker additionalGain_scaling -= gain_scale;
1423*e5436536SAndroid Build Coastguard Worker
1424*e5436536SAndroid Build Coastguard Worker if (additionalGain_scaling) {
1425*e5436536SAndroid Build Coastguard Worker scaleValuesSaturate(samplesIn, channels * nSamples,
1426*e5436536SAndroid Build Coastguard Worker -additionalGain_scaling);
1427*e5436536SAndroid Build Coastguard Worker }
1428*e5436536SAndroid Build Coastguard Worker
1429*e5436536SAndroid Build Coastguard Worker if (limiterEnabled) {
1430*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pGainPerSample != NULL);
1431*e5436536SAndroid Build Coastguard Worker
1432*e5436536SAndroid Build Coastguard Worker for (i = 0; i < nSamples; i++) {
1433*e5436536SAndroid Build Coastguard Worker pGainPerSample[i] = additionalGain;
1434*e5436536SAndroid Build Coastguard Worker }
1435*e5436536SAndroid Build Coastguard Worker } else {
1436*e5436536SAndroid Build Coastguard Worker for (i = 0; i < channels * nSamples; i++) {
1437*e5436536SAndroid Build Coastguard Worker samplesIn[i] = FIXP_DBL2PCM_DEC(fMult(samplesIn[i], additionalGain));
1438*e5436536SAndroid Build Coastguard Worker }
1439*e5436536SAndroid Build Coastguard Worker }
1440*e5436536SAndroid Build Coastguard Worker } else {
1441*e5436536SAndroid Build Coastguard Worker UINT inc;
1442*e5436536SAndroid Build Coastguard Worker FIXP_DBL additionalGainUnfiltered;
1443*e5436536SAndroid Build Coastguard Worker
1444*e5436536SAndroid Build Coastguard Worker inc = (stride == 1) ? channels : 1;
1445*e5436536SAndroid Build Coastguard Worker
1446*e5436536SAndroid Build Coastguard Worker for (i = 0; i < nSamples; i++) {
1447*e5436536SAndroid Build Coastguard Worker if (i < gain_delay) {
1448*e5436536SAndroid Build Coastguard Worker additionalGainUnfiltered = hDrcInfo->additionalGainPrev;
1449*e5436536SAndroid Build Coastguard Worker } else {
1450*e5436536SAndroid Build Coastguard Worker additionalGainUnfiltered = pGain[0];
1451*e5436536SAndroid Build Coastguard Worker }
1452*e5436536SAndroid Build Coastguard Worker
1453*e5436536SAndroid Build Coastguard Worker /* Smooth additionalGain */
1454*e5436536SAndroid Build Coastguard Worker
1455*e5436536SAndroid Build Coastguard Worker /* [b,a] = butter(1, 0.01) */
1456*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0),
1457*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(0.015466 * 2.0)};
1458*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL,
1459*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(-0.96907)};
1460*e5436536SAndroid Build Coastguard Worker
1461*e5436536SAndroid Build Coastguard Worker additionalGain = -fMult(additionalGainSmoothState, a[1]) +
1462*e5436536SAndroid Build Coastguard Worker fMultDiv2(additionalGainUnfiltered, b[0]) +
1463*e5436536SAndroid Build Coastguard Worker fMultDiv2(additionalGainSmoothState1, b[1]);
1464*e5436536SAndroid Build Coastguard Worker additionalGainSmoothState1 = additionalGainUnfiltered;
1465*e5436536SAndroid Build Coastguard Worker additionalGainSmoothState = additionalGain;
1466*e5436536SAndroid Build Coastguard Worker
1467*e5436536SAndroid Build Coastguard Worker /* Apply the additional scaling gain_scale[0] that has no delay and no
1468*e5436536SAndroid Build Coastguard Worker * smoothing */
1469*e5436536SAndroid Build Coastguard Worker additionalGain_scaling =
1470*e5436536SAndroid Build Coastguard Worker fMin(gain_scale, CntLeadingZeros(additionalGain) - 1);
1471*e5436536SAndroid Build Coastguard Worker additionalGain = scaleValue(additionalGain, additionalGain_scaling);
1472*e5436536SAndroid Build Coastguard Worker
1473*e5436536SAndroid Build Coastguard Worker /* if it's not possible to fully apply gain_scale[0] to additionalGain,
1474*e5436536SAndroid Build Coastguard Worker * apply it to the input signal */
1475*e5436536SAndroid Build Coastguard Worker additionalGain_scaling -= gain_scale;
1476*e5436536SAndroid Build Coastguard Worker
1477*e5436536SAndroid Build Coastguard Worker if (limiterEnabled) {
1478*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(stride == 1);
1479*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pGainPerSample != NULL);
1480*e5436536SAndroid Build Coastguard Worker
1481*e5436536SAndroid Build Coastguard Worker if (additionalGain_scaling) {
1482*e5436536SAndroid Build Coastguard Worker scaleValuesSaturate(samplesIn, channels, -additionalGain_scaling);
1483*e5436536SAndroid Build Coastguard Worker }
1484*e5436536SAndroid Build Coastguard Worker
1485*e5436536SAndroid Build Coastguard Worker pGainPerSample[i] = additionalGain;
1486*e5436536SAndroid Build Coastguard Worker } else {
1487*e5436536SAndroid Build Coastguard Worker if (additionalGain_scaling) {
1488*e5436536SAndroid Build Coastguard Worker for (UINT k = 0; k < channels; k++) {
1489*e5436536SAndroid Build Coastguard Worker scaleValuesSaturate(&samplesIn[k * stride], 1,
1490*e5436536SAndroid Build Coastguard Worker -additionalGain_scaling);
1491*e5436536SAndroid Build Coastguard Worker }
1492*e5436536SAndroid Build Coastguard Worker }
1493*e5436536SAndroid Build Coastguard Worker
1494*e5436536SAndroid Build Coastguard Worker for (UINT k = 0; k < channels; k++) {
1495*e5436536SAndroid Build Coastguard Worker samplesIn[k * stride] =
1496*e5436536SAndroid Build Coastguard Worker FIXP_DBL2PCM_DEC(fMult(samplesIn[k * stride], additionalGain));
1497*e5436536SAndroid Build Coastguard Worker }
1498*e5436536SAndroid Build Coastguard Worker }
1499*e5436536SAndroid Build Coastguard Worker
1500*e5436536SAndroid Build Coastguard Worker samplesIn += inc;
1501*e5436536SAndroid Build Coastguard Worker }
1502*e5436536SAndroid Build Coastguard Worker }
1503*e5436536SAndroid Build Coastguard Worker
1504*e5436536SAndroid Build Coastguard Worker hDrcInfo->additionalGainPrev = pGain[0];
1505*e5436536SAndroid Build Coastguard Worker hDrcInfo->additionalGainFilterState = additionalGainSmoothState;
1506*e5436536SAndroid Build Coastguard Worker hDrcInfo->additionalGainFilterState1 = additionalGainSmoothState1;
1507*e5436536SAndroid Build Coastguard Worker
1508*e5436536SAndroid Build Coastguard Worker return (AACDEC_DRC_GAIN_SCALING);
1509*e5436536SAndroid Build Coastguard Worker }
1510