xref: /aosp_15_r20/external/aac/libDRCdec/src/drcDec_gainDecoder.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /************************* MPEG-D DRC decoder library **************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description:
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "drcDec_types.h"
104*e5436536SAndroid Build Coastguard Worker #include "drcDec_gainDecoder.h"
105*e5436536SAndroid Build Coastguard Worker #include "drcGainDec_preprocess.h"
106*e5436536SAndroid Build Coastguard Worker #include "drcGainDec_init.h"
107*e5436536SAndroid Build Coastguard Worker #include "drcGainDec_process.h"
108*e5436536SAndroid Build Coastguard Worker #include "drcDec_tools.h"
109*e5436536SAndroid Build Coastguard Worker 
110*e5436536SAndroid Build Coastguard Worker /*******************************************/
111*e5436536SAndroid Build Coastguard Worker /* static functions                        */
112*e5436536SAndroid Build Coastguard Worker /*******************************************/
113*e5436536SAndroid Build Coastguard Worker 
_fitsLocation(DRC_INSTRUCTIONS_UNI_DRC * pInst,const GAIN_DEC_LOCATION drcLocation)114*e5436536SAndroid Build Coastguard Worker static int _fitsLocation(DRC_INSTRUCTIONS_UNI_DRC* pInst,
115*e5436536SAndroid Build Coastguard Worker                          const GAIN_DEC_LOCATION drcLocation) {
116*e5436536SAndroid Build Coastguard Worker   int downmixId = pInst->drcApplyToDownmix ? pInst->downmixId[0] : 0;
117*e5436536SAndroid Build Coastguard Worker   switch (drcLocation) {
118*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_DRC1:
119*e5436536SAndroid Build Coastguard Worker       return (downmixId == 0);
120*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_DRC1_DRC2:
121*e5436536SAndroid Build Coastguard Worker       return ((downmixId == 0) || (downmixId == DOWNMIX_ID_ANY_DOWNMIX));
122*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_DRC2:
123*e5436536SAndroid Build Coastguard Worker       return (downmixId == DOWNMIX_ID_ANY_DOWNMIX);
124*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_DRC3:
125*e5436536SAndroid Build Coastguard Worker       return ((downmixId != 0) && (downmixId != DOWNMIX_ID_ANY_DOWNMIX));
126*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_DRC2_DRC3:
127*e5436536SAndroid Build Coastguard Worker       return (downmixId != 0);
128*e5436536SAndroid Build Coastguard Worker   }
129*e5436536SAndroid Build Coastguard Worker   return 0;
130*e5436536SAndroid Build Coastguard Worker }
131*e5436536SAndroid Build Coastguard Worker 
_setChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec,const int numChannelGains,const FIXP_DBL * channelGainDb)132*e5436536SAndroid Build Coastguard Worker static void _setChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec,
133*e5436536SAndroid Build Coastguard Worker                              const int numChannelGains,
134*e5436536SAndroid Build Coastguard Worker                              const FIXP_DBL* channelGainDb) {
135*e5436536SAndroid Build Coastguard Worker   int i, channelGain_e;
136*e5436536SAndroid Build Coastguard Worker   FIXP_DBL channelGain;
137*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(numChannelGains <= 8);
138*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numChannelGains; i++) {
139*e5436536SAndroid Build Coastguard Worker     if (channelGainDb[i] == (FIXP_DBL)MINVAL_DBL) {
140*e5436536SAndroid Build Coastguard Worker       hGainDec->channelGain[i] = (FIXP_DBL)0;
141*e5436536SAndroid Build Coastguard Worker     } else {
142*e5436536SAndroid Build Coastguard Worker       /* add loudness normalisation gain (dB) to channel gain (dB) */
143*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp_channelGainDb = (channelGainDb[i] >> 1) +
144*e5436536SAndroid Build Coastguard Worker                                    (hGainDec->loudnessNormalisationGainDb >> 2);
145*e5436536SAndroid Build Coastguard Worker       tmp_channelGainDb =
146*e5436536SAndroid Build Coastguard Worker           SATURATE_LEFT_SHIFT(tmp_channelGainDb, 1, DFRACT_BITS);
147*e5436536SAndroid Build Coastguard Worker       channelGain = dB2lin(tmp_channelGainDb, 8, &channelGain_e);
148*e5436536SAndroid Build Coastguard Worker       hGainDec->channelGain[i] = scaleValue(channelGain, channelGain_e - 8);
149*e5436536SAndroid Build Coastguard Worker     }
150*e5436536SAndroid Build Coastguard Worker   }
151*e5436536SAndroid Build Coastguard Worker }
152*e5436536SAndroid Build Coastguard Worker 
153*e5436536SAndroid Build Coastguard Worker /*******************************************/
154*e5436536SAndroid Build Coastguard Worker /* public functions                        */
155*e5436536SAndroid Build Coastguard Worker /*******************************************/
156*e5436536SAndroid Build Coastguard Worker 
157*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER * phGainDec)158*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec) {
159*e5436536SAndroid Build Coastguard Worker   DRC_GAIN_DECODER* hGainDec = NULL;
160*e5436536SAndroid Build Coastguard Worker 
161*e5436536SAndroid Build Coastguard Worker   hGainDec = (DRC_GAIN_DECODER*)FDKcalloc(1, sizeof(DRC_GAIN_DECODER));
162*e5436536SAndroid Build Coastguard Worker   if (hGainDec == NULL) return DE_MEMORY_ERROR;
163*e5436536SAndroid Build Coastguard Worker 
164*e5436536SAndroid Build Coastguard Worker   hGainDec->multiBandActiveDrcIndex = -1;
165*e5436536SAndroid Build Coastguard Worker   hGainDec->channelGainActiveDrcIndex = -1;
166*e5436536SAndroid Build Coastguard Worker 
167*e5436536SAndroid Build Coastguard Worker   *phGainDec = hGainDec;
168*e5436536SAndroid Build Coastguard Worker 
169*e5436536SAndroid Build Coastguard Worker   return DE_OK;
170*e5436536SAndroid Build Coastguard Worker }
171*e5436536SAndroid Build Coastguard Worker 
172*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec)173*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec) {
174*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
175*e5436536SAndroid Build Coastguard Worker 
176*e5436536SAndroid Build Coastguard Worker   err = initGainDec(hGainDec);
177*e5436536SAndroid Build Coastguard Worker   if (err) return err;
178*e5436536SAndroid Build Coastguard Worker 
179*e5436536SAndroid Build Coastguard Worker   initDrcGainBuffers(hGainDec->frameSize, &hGainDec->drcGainBuffers);
180*e5436536SAndroid Build Coastguard Worker 
181*e5436536SAndroid Build Coastguard Worker   return err;
182*e5436536SAndroid Build Coastguard Worker }
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec,const GAIN_DEC_PARAM paramType,const int paramValue)185*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_SetParam(HANDLE_DRC_GAIN_DECODER hGainDec,
186*e5436536SAndroid Build Coastguard Worker                             const GAIN_DEC_PARAM paramType,
187*e5436536SAndroid Build Coastguard Worker                             const int paramValue) {
188*e5436536SAndroid Build Coastguard Worker   switch (paramType) {
189*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_FRAME_SIZE:
190*e5436536SAndroid Build Coastguard Worker       if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE;
191*e5436536SAndroid Build Coastguard Worker       hGainDec->frameSize = paramValue;
192*e5436536SAndroid Build Coastguard Worker       break;
193*e5436536SAndroid Build Coastguard Worker     case GAIN_DEC_SAMPLE_RATE:
194*e5436536SAndroid Build Coastguard Worker       if (paramValue < 0) return DE_PARAM_OUT_OF_RANGE;
195*e5436536SAndroid Build Coastguard Worker       hGainDec->deltaTminDefault = getDeltaTmin(paramValue);
196*e5436536SAndroid Build Coastguard Worker       break;
197*e5436536SAndroid Build Coastguard Worker     default:
198*e5436536SAndroid Build Coastguard Worker       return DE_PARAM_INVALID;
199*e5436536SAndroid Build Coastguard Worker   }
200*e5436536SAndroid Build Coastguard Worker   return DE_OK;
201*e5436536SAndroid Build Coastguard Worker }
202*e5436536SAndroid Build Coastguard Worker 
203*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_SetCodecDependentParameters(HANDLE_DRC_GAIN_DECODER hGainDec,const DELAY_MODE delayMode,const int timeDomainSupported,const SUBBAND_DOMAIN_MODE subbandDomainSupported)204*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_SetCodecDependentParameters(
205*e5436536SAndroid Build Coastguard Worker     HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode,
206*e5436536SAndroid Build Coastguard Worker     const int timeDomainSupported,
207*e5436536SAndroid Build Coastguard Worker     const SUBBAND_DOMAIN_MODE subbandDomainSupported) {
208*e5436536SAndroid Build Coastguard Worker   if ((delayMode != DM_REGULAR_DELAY) && (delayMode != DM_LOW_DELAY)) {
209*e5436536SAndroid Build Coastguard Worker     return DE_NOT_OK;
210*e5436536SAndroid Build Coastguard Worker   }
211*e5436536SAndroid Build Coastguard Worker   hGainDec->delayMode = delayMode;
212*e5436536SAndroid Build Coastguard Worker   hGainDec->timeDomainSupported = timeDomainSupported;
213*e5436536SAndroid Build Coastguard Worker   hGainDec->subbandDomainSupported = subbandDomainSupported;
214*e5436536SAndroid Build Coastguard Worker 
215*e5436536SAndroid Build Coastguard Worker   return DE_OK;
216*e5436536SAndroid Build Coastguard Worker }
217*e5436536SAndroid Build Coastguard Worker 
218*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec,HANDLE_UNI_DRC_CONFIG hUniDrcConfig,const UCHAR numSelectedDrcSets,const SCHAR * selectedDrcSetIds,const UCHAR * selectedDownmixIds)219*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec,
220*e5436536SAndroid Build Coastguard Worker                           HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
221*e5436536SAndroid Build Coastguard Worker                           const UCHAR numSelectedDrcSets,
222*e5436536SAndroid Build Coastguard Worker                           const SCHAR* selectedDrcSetIds,
223*e5436536SAndroid Build Coastguard Worker                           const UCHAR* selectedDownmixIds) {
224*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
225*e5436536SAndroid Build Coastguard Worker   int a;
226*e5436536SAndroid Build Coastguard Worker 
227*e5436536SAndroid Build Coastguard Worker   hGainDec->nActiveDrcs = 0;
228*e5436536SAndroid Build Coastguard Worker   hGainDec->multiBandActiveDrcIndex = -1;
229*e5436536SAndroid Build Coastguard Worker   hGainDec->channelGainActiveDrcIndex = -1;
230*e5436536SAndroid Build Coastguard Worker   for (a = 0; a < numSelectedDrcSets; a++) {
231*e5436536SAndroid Build Coastguard Worker     err = initActiveDrc(hGainDec, hUniDrcConfig, selectedDrcSetIds[a],
232*e5436536SAndroid Build Coastguard Worker                         selectedDownmixIds[a]);
233*e5436536SAndroid Build Coastguard Worker     if (err) return err;
234*e5436536SAndroid Build Coastguard Worker   }
235*e5436536SAndroid Build Coastguard Worker 
236*e5436536SAndroid Build Coastguard Worker   err = initActiveDrcOffset(hGainDec);
237*e5436536SAndroid Build Coastguard Worker   if (err) return err;
238*e5436536SAndroid Build Coastguard Worker 
239*e5436536SAndroid Build Coastguard Worker   return err;
240*e5436536SAndroid Build Coastguard Worker }
241*e5436536SAndroid Build Coastguard Worker 
242*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER * phGainDec)243*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER* phGainDec) {
244*e5436536SAndroid Build Coastguard Worker   if (*phGainDec != NULL) {
245*e5436536SAndroid Build Coastguard Worker     FDKfree(*phGainDec);
246*e5436536SAndroid Build Coastguard Worker     *phGainDec = NULL;
247*e5436536SAndroid Build Coastguard Worker   }
248*e5436536SAndroid Build Coastguard Worker 
249*e5436536SAndroid Build Coastguard Worker   return DE_OK;
250*e5436536SAndroid Build Coastguard Worker }
251*e5436536SAndroid Build Coastguard Worker 
252*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec,HANDLE_UNI_DRC_GAIN hUniDrcGain,const FIXP_DBL loudnessNormalizationGainDb,const FIXP_SGL boost,const FIXP_SGL compress)253*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec,
254*e5436536SAndroid Build Coastguard Worker                               HANDLE_UNI_DRC_GAIN hUniDrcGain,
255*e5436536SAndroid Build Coastguard Worker                               const FIXP_DBL loudnessNormalizationGainDb,
256*e5436536SAndroid Build Coastguard Worker                               const FIXP_SGL boost, const FIXP_SGL compress) {
257*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
258*e5436536SAndroid Build Coastguard Worker   int a, c;
259*e5436536SAndroid Build Coastguard Worker 
260*e5436536SAndroid Build Coastguard Worker   /* lnbPointer is the index on the most recent node buffer */
261*e5436536SAndroid Build Coastguard Worker   hGainDec->drcGainBuffers.lnbPointer++;
262*e5436536SAndroid Build Coastguard Worker   if (hGainDec->drcGainBuffers.lnbPointer >= NUM_LNB_FRAMES)
263*e5436536SAndroid Build Coastguard Worker     hGainDec->drcGainBuffers.lnbPointer = 0;
264*e5436536SAndroid Build Coastguard Worker 
265*e5436536SAndroid Build Coastguard Worker   for (a = 0; a < hGainDec->nActiveDrcs; a++) {
266*e5436536SAndroid Build Coastguard Worker     /* prepare gain interpolation of sequences used by copying and modifying
267*e5436536SAndroid Build Coastguard Worker      * nodes in node buffers */
268*e5436536SAndroid Build Coastguard Worker     err = prepareDrcGain(hGainDec, hUniDrcGain, compress, boost,
269*e5436536SAndroid Build Coastguard Worker                          loudnessNormalizationGainDb, a);
270*e5436536SAndroid Build Coastguard Worker     if (err) return err;
271*e5436536SAndroid Build Coastguard Worker   }
272*e5436536SAndroid Build Coastguard Worker 
273*e5436536SAndroid Build Coastguard Worker   for (a = 0; a < MAX_ACTIVE_DRCS; a++) {
274*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < 8; c++) {
275*e5436536SAndroid Build Coastguard Worker       hGainDec->activeDrc[a]
276*e5436536SAndroid Build Coastguard Worker           .lnbIndexForChannel[c][hGainDec->drcGainBuffers.lnbPointer] =
277*e5436536SAndroid Build Coastguard Worker           -1; /* "no DRC processing" */
278*e5436536SAndroid Build Coastguard Worker     }
279*e5436536SAndroid Build Coastguard Worker     hGainDec->activeDrc[a].subbandGainsReady = 0;
280*e5436536SAndroid Build Coastguard Worker   }
281*e5436536SAndroid Build Coastguard Worker 
282*e5436536SAndroid Build Coastguard Worker   for (c = 0; c < 8; c++) {
283*e5436536SAndroid Build Coastguard Worker     hGainDec->drcGainBuffers
284*e5436536SAndroid Build Coastguard Worker         .channelGain[c][hGainDec->drcGainBuffers.lnbPointer] =
285*e5436536SAndroid Build Coastguard Worker         FL2FXCONST_DBL(1.0f / (float)(1 << 8));
286*e5436536SAndroid Build Coastguard Worker   }
287*e5436536SAndroid Build Coastguard Worker 
288*e5436536SAndroid Build Coastguard Worker   return err;
289*e5436536SAndroid Build Coastguard Worker }
290*e5436536SAndroid Build Coastguard Worker 
291*e5436536SAndroid Build Coastguard Worker /* create gain sequence out of gain sequences of last frame for concealment and
292*e5436536SAndroid Build Coastguard Worker  * flushing */
293*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec,HANDLE_UNI_DRC_CONFIG hUniDrcConfig,HANDLE_UNI_DRC_GAIN hUniDrcGain)294*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec,
295*e5436536SAndroid Build Coastguard Worker                            HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
296*e5436536SAndroid Build Coastguard Worker                            HANDLE_UNI_DRC_GAIN hUniDrcGain) {
297*e5436536SAndroid Build Coastguard Worker   int seq, gainSequenceCount;
298*e5436536SAndroid Build Coastguard Worker   DRC_COEFFICIENTS_UNI_DRC* pCoef =
299*e5436536SAndroid Build Coastguard Worker       selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED);
300*e5436536SAndroid Build Coastguard Worker   if (pCoef && pCoef->gainSequenceCount) {
301*e5436536SAndroid Build Coastguard Worker     gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12);
302*e5436536SAndroid Build Coastguard Worker   } else {
303*e5436536SAndroid Build Coastguard Worker     gainSequenceCount = 1;
304*e5436536SAndroid Build Coastguard Worker   }
305*e5436536SAndroid Build Coastguard Worker 
306*e5436536SAndroid Build Coastguard Worker   for (seq = 0; seq < gainSequenceCount; seq++) {
307*e5436536SAndroid Build Coastguard Worker     int lastNodeIndex = 0;
308*e5436536SAndroid Build Coastguard Worker     FIXP_SGL lastGainDb = (FIXP_SGL)0;
309*e5436536SAndroid Build Coastguard Worker 
310*e5436536SAndroid Build Coastguard Worker     lastNodeIndex = hUniDrcGain->nNodes[seq] - 1;
311*e5436536SAndroid Build Coastguard Worker     if ((lastNodeIndex >= 0) && (lastNodeIndex < 16)) {
312*e5436536SAndroid Build Coastguard Worker       lastGainDb = hUniDrcGain->gainNode[seq][lastNodeIndex].gainDb;
313*e5436536SAndroid Build Coastguard Worker     }
314*e5436536SAndroid Build Coastguard Worker 
315*e5436536SAndroid Build Coastguard Worker     hUniDrcGain->nNodes[seq] = 1;
316*e5436536SAndroid Build Coastguard Worker     if (lastGainDb > (FIXP_SGL)0) {
317*e5436536SAndroid Build Coastguard Worker       hUniDrcGain->gainNode[seq][0].gainDb =
318*e5436536SAndroid Build Coastguard Worker           FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.9f), lastGainDb));
319*e5436536SAndroid Build Coastguard Worker     } else {
320*e5436536SAndroid Build Coastguard Worker       hUniDrcGain->gainNode[seq][0].gainDb =
321*e5436536SAndroid Build Coastguard Worker           FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.98f), lastGainDb));
322*e5436536SAndroid Build Coastguard Worker     }
323*e5436536SAndroid Build Coastguard Worker     hUniDrcGain->gainNode[seq][0].time = hGainDec->frameSize - 1;
324*e5436536SAndroid Build Coastguard Worker   }
325*e5436536SAndroid Build Coastguard Worker   return DE_OK;
326*e5436536SAndroid Build Coastguard Worker }
327*e5436536SAndroid Build Coastguard Worker 
drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec,const int numChannels,const int frameSize,const FIXP_DBL * channelGainDb,const int audioBufferChannelOffset,FIXP_DBL * audioBuffer)328*e5436536SAndroid Build Coastguard Worker void drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec,
329*e5436536SAndroid Build Coastguard Worker                                         const int numChannels,
330*e5436536SAndroid Build Coastguard Worker                                         const int frameSize,
331*e5436536SAndroid Build Coastguard Worker                                         const FIXP_DBL* channelGainDb,
332*e5436536SAndroid Build Coastguard Worker                                         const int audioBufferChannelOffset,
333*e5436536SAndroid Build Coastguard Worker                                         FIXP_DBL* audioBuffer) {
334*e5436536SAndroid Build Coastguard Worker   int c, i;
335*e5436536SAndroid Build Coastguard Worker 
336*e5436536SAndroid Build Coastguard Worker   if (hGainDec->channelGainActiveDrcIndex >= 0) {
337*e5436536SAndroid Build Coastguard Worker     /* channel gains will be applied in drcDec_GainDecoder_ProcessTimeDomain or
338*e5436536SAndroid Build Coastguard Worker      * drcDec_GainDecoder_ProcessSubbandDomain, respectively. */
339*e5436536SAndroid Build Coastguard Worker     _setChannelGains(hGainDec, numChannels, channelGainDb);
340*e5436536SAndroid Build Coastguard Worker 
341*e5436536SAndroid Build Coastguard Worker     if (!hGainDec->status) { /* overwrite previous channel gains at startup */
342*e5436536SAndroid Build Coastguard Worker       DRC_GAIN_BUFFERS* pDrcGainBuffers = &hGainDec->drcGainBuffers;
343*e5436536SAndroid Build Coastguard Worker       for (c = 0; c < numChannels; c++) {
344*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < NUM_LNB_FRAMES; i++) {
345*e5436536SAndroid Build Coastguard Worker           pDrcGainBuffers->channelGain[c][i] = hGainDec->channelGain[c];
346*e5436536SAndroid Build Coastguard Worker         }
347*e5436536SAndroid Build Coastguard Worker       }
348*e5436536SAndroid Build Coastguard Worker       hGainDec->status = 1;
349*e5436536SAndroid Build Coastguard Worker     }
350*e5436536SAndroid Build Coastguard Worker   } else {
351*e5436536SAndroid Build Coastguard Worker     /* smooth and apply channel gains */
352*e5436536SAndroid Build Coastguard Worker     FIXP_DBL prevChannelGain[8];
353*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < numChannels; c++) {
354*e5436536SAndroid Build Coastguard Worker       prevChannelGain[c] = hGainDec->channelGain[c];
355*e5436536SAndroid Build Coastguard Worker     }
356*e5436536SAndroid Build Coastguard Worker 
357*e5436536SAndroid Build Coastguard Worker     _setChannelGains(hGainDec, numChannels, channelGainDb);
358*e5436536SAndroid Build Coastguard Worker 
359*e5436536SAndroid Build Coastguard Worker     if (!hGainDec->status) { /* overwrite previous channel gains at startup */
360*e5436536SAndroid Build Coastguard Worker       for (c = 0; c < numChannels; c++)
361*e5436536SAndroid Build Coastguard Worker         prevChannelGain[c] = hGainDec->channelGain[c];
362*e5436536SAndroid Build Coastguard Worker       hGainDec->status = 1;
363*e5436536SAndroid Build Coastguard Worker     }
364*e5436536SAndroid Build Coastguard Worker 
365*e5436536SAndroid Build Coastguard Worker     for (c = 0; c < numChannels; c++) {
366*e5436536SAndroid Build Coastguard Worker       INT n_min = fMin(fMin(CntLeadingZeros(prevChannelGain[c]),
367*e5436536SAndroid Build Coastguard Worker                             CntLeadingZeros(hGainDec->channelGain[c])) -
368*e5436536SAndroid Build Coastguard Worker                            1,
369*e5436536SAndroid Build Coastguard Worker                        9);
370*e5436536SAndroid Build Coastguard Worker       FIXP_DBL gain = prevChannelGain[c] << n_min;
371*e5436536SAndroid Build Coastguard Worker       FIXP_DBL stepsize = ((hGainDec->channelGain[c] << n_min) - gain);
372*e5436536SAndroid Build Coastguard Worker       if (stepsize != (FIXP_DBL)0) {
373*e5436536SAndroid Build Coastguard Worker         if (frameSize == 1024)
374*e5436536SAndroid Build Coastguard Worker           stepsize = stepsize >> 10;
375*e5436536SAndroid Build Coastguard Worker         else
376*e5436536SAndroid Build Coastguard Worker           stepsize = (LONG)stepsize / frameSize;
377*e5436536SAndroid Build Coastguard Worker       }
378*e5436536SAndroid Build Coastguard Worker       n_min = 9 - n_min;
379*e5436536SAndroid Build Coastguard Worker #ifdef FUNCTION_drcDec_GainDecoder_SetChannelGains_func1
380*e5436536SAndroid Build Coastguard Worker       drcDec_GainDecoder_SetChannelGains_func1(audioBuffer, gain, stepsize,
381*e5436536SAndroid Build Coastguard Worker                                                n_min, frameSize);
382*e5436536SAndroid Build Coastguard Worker #else
383*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < frameSize; i++) {
384*e5436536SAndroid Build Coastguard Worker         audioBuffer[i] = fMultDiv2(audioBuffer[i], gain) << n_min;
385*e5436536SAndroid Build Coastguard Worker         gain += stepsize;
386*e5436536SAndroid Build Coastguard Worker       }
387*e5436536SAndroid Build Coastguard Worker #endif
388*e5436536SAndroid Build Coastguard Worker       audioBuffer += audioBufferChannelOffset;
389*e5436536SAndroid Build Coastguard Worker     }
390*e5436536SAndroid Build Coastguard Worker   }
391*e5436536SAndroid Build Coastguard Worker }
392*e5436536SAndroid Build Coastguard Worker 
393*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_ProcessTimeDomain(HANDLE_DRC_GAIN_DECODER hGainDec,const int delaySamples,const GAIN_DEC_LOCATION drcLocation,const int channelOffset,const int drcChannelOffset,const int numChannelsProcessed,const int timeDataChannelOffset,FIXP_DBL * audioIOBuffer)394*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_ProcessTimeDomain(
395*e5436536SAndroid Build Coastguard Worker     HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples,
396*e5436536SAndroid Build Coastguard Worker     const GAIN_DEC_LOCATION drcLocation, const int channelOffset,
397*e5436536SAndroid Build Coastguard Worker     const int drcChannelOffset, const int numChannelsProcessed,
398*e5436536SAndroid Build Coastguard Worker     const int timeDataChannelOffset, FIXP_DBL* audioIOBuffer) {
399*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
400*e5436536SAndroid Build Coastguard Worker   int a;
401*e5436536SAndroid Build Coastguard Worker 
402*e5436536SAndroid Build Coastguard Worker   if (!hGainDec->timeDomainSupported) {
403*e5436536SAndroid Build Coastguard Worker     return DE_NOT_OK;
404*e5436536SAndroid Build Coastguard Worker   }
405*e5436536SAndroid Build Coastguard Worker 
406*e5436536SAndroid Build Coastguard Worker   for (a = 0; a < hGainDec->nActiveDrcs; a++) {
407*e5436536SAndroid Build Coastguard Worker     if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue;
408*e5436536SAndroid Build Coastguard Worker 
409*e5436536SAndroid Build Coastguard Worker     /* Apply DRC */
410*e5436536SAndroid Build Coastguard Worker     err = processDrcTime(hGainDec, a, delaySamples, channelOffset,
411*e5436536SAndroid Build Coastguard Worker                          drcChannelOffset, numChannelsProcessed,
412*e5436536SAndroid Build Coastguard Worker                          timeDataChannelOffset, audioIOBuffer);
413*e5436536SAndroid Build Coastguard Worker     if (err) return err;
414*e5436536SAndroid Build Coastguard Worker   }
415*e5436536SAndroid Build Coastguard Worker 
416*e5436536SAndroid Build Coastguard Worker   return err;
417*e5436536SAndroid Build Coastguard Worker }
418*e5436536SAndroid Build Coastguard Worker 
419*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_ProcessSubbandDomain(HANDLE_DRC_GAIN_DECODER hGainDec,const int delaySamples,const GAIN_DEC_LOCATION drcLocation,const int channelOffset,const int drcChannelOffset,const int numChannelsProcessed,const int processSingleTimeslot,FIXP_DBL * audioIOBufferReal[],FIXP_DBL * audioIOBufferImag[])420*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_ProcessSubbandDomain(
421*e5436536SAndroid Build Coastguard Worker     HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples,
422*e5436536SAndroid Build Coastguard Worker     const GAIN_DEC_LOCATION drcLocation, const int channelOffset,
423*e5436536SAndroid Build Coastguard Worker     const int drcChannelOffset, const int numChannelsProcessed,
424*e5436536SAndroid Build Coastguard Worker     const int processSingleTimeslot, FIXP_DBL* audioIOBufferReal[],
425*e5436536SAndroid Build Coastguard Worker     FIXP_DBL* audioIOBufferImag[]) {
426*e5436536SAndroid Build Coastguard Worker   DRC_ERROR err = DE_OK;
427*e5436536SAndroid Build Coastguard Worker   int a;
428*e5436536SAndroid Build Coastguard Worker 
429*e5436536SAndroid Build Coastguard Worker   if (hGainDec->subbandDomainSupported == SDM_OFF) {
430*e5436536SAndroid Build Coastguard Worker     return DE_NOT_OK;
431*e5436536SAndroid Build Coastguard Worker   }
432*e5436536SAndroid Build Coastguard Worker 
433*e5436536SAndroid Build Coastguard Worker   for (a = 0; a < hGainDec->nActiveDrcs; a++) {
434*e5436536SAndroid Build Coastguard Worker     if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue;
435*e5436536SAndroid Build Coastguard Worker 
436*e5436536SAndroid Build Coastguard Worker     /* Apply DRC */
437*e5436536SAndroid Build Coastguard Worker     err = processDrcSubband(hGainDec, a, delaySamples, channelOffset,
438*e5436536SAndroid Build Coastguard Worker                             drcChannelOffset, numChannelsProcessed,
439*e5436536SAndroid Build Coastguard Worker                             processSingleTimeslot, audioIOBufferReal,
440*e5436536SAndroid Build Coastguard Worker                             audioIOBufferImag);
441*e5436536SAndroid Build Coastguard Worker     if (err) return err;
442*e5436536SAndroid Build Coastguard Worker   }
443*e5436536SAndroid Build Coastguard Worker 
444*e5436536SAndroid Build Coastguard Worker   return err;
445*e5436536SAndroid Build Coastguard Worker }
446*e5436536SAndroid Build Coastguard Worker 
447*e5436536SAndroid Build Coastguard Worker DRC_ERROR
drcDec_GainDecoder_SetLoudnessNormalizationGainDb(HANDLE_DRC_GAIN_DECODER hGainDec,FIXP_DBL loudnessNormalizationGainDb)448*e5436536SAndroid Build Coastguard Worker drcDec_GainDecoder_SetLoudnessNormalizationGainDb(
449*e5436536SAndroid Build Coastguard Worker     HANDLE_DRC_GAIN_DECODER hGainDec, FIXP_DBL loudnessNormalizationGainDb) {
450*e5436536SAndroid Build Coastguard Worker   hGainDec->loudnessNormalisationGainDb = loudnessNormalizationGainDb;
451*e5436536SAndroid Build Coastguard Worker 
452*e5436536SAndroid Build Coastguard Worker   return DE_OK;
453*e5436536SAndroid Build Coastguard Worker }
454*e5436536SAndroid Build Coastguard Worker 
drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec)455*e5436536SAndroid Build Coastguard Worker int drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec) {
456*e5436536SAndroid Build Coastguard Worker   if (hGainDec == NULL) return -1;
457*e5436536SAndroid Build Coastguard Worker 
458*e5436536SAndroid Build Coastguard Worker   return hGainDec->frameSize;
459*e5436536SAndroid Build Coastguard Worker }
460*e5436536SAndroid Build Coastguard Worker 
drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec)461*e5436536SAndroid Build Coastguard Worker int drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec) {
462*e5436536SAndroid Build Coastguard Worker   if (hGainDec == NULL) return -1;
463*e5436536SAndroid Build Coastguard Worker 
464*e5436536SAndroid Build Coastguard Worker   return hGainDec->deltaTminDefault;
465*e5436536SAndroid Build Coastguard Worker }
466