xref: /aosp_15_r20/external/aac/libSBRdec/src/sbrdec_drc.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /**************************** SBR 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 SBR
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "sbrdec_drc.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker /* DRC - Offset table for QMF interpolation. Shifted by one index position.
106*e5436536SAndroid Build Coastguard Worker    The table defines the (short) window borders rounded to the nearest QMF
107*e5436536SAndroid Build Coastguard Worker    timeslot. It has the size 16 because it is accessed with the
108*e5436536SAndroid Build Coastguard Worker    drcInterpolationScheme that is read from the bitstream with 4 bit. */
109*e5436536SAndroid Build Coastguard Worker static const UCHAR winBorderToColMappingTab[2][16] = {
110*e5436536SAndroid Build Coastguard Worker     /*-1, 0, 1, 2,  3,  4,  5,  6,  7,  8 */
111*e5436536SAndroid Build Coastguard Worker     {0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32,
112*e5436536SAndroid Build Coastguard Worker      32}, /* 1024 framing */
113*e5436536SAndroid Build Coastguard Worker     {0, 0, 4, 8, 11, 15, 19, 23, 26, 30, 30, 30, 30, 30, 30,
114*e5436536SAndroid Build Coastguard Worker      30} /*  960 framing */
115*e5436536SAndroid Build Coastguard Worker };
116*e5436536SAndroid Build Coastguard Worker 
117*e5436536SAndroid Build Coastguard Worker /*!
118*e5436536SAndroid Build Coastguard Worker   \brief Initialize DRC QMF factors
119*e5436536SAndroid Build Coastguard Worker 
120*e5436536SAndroid Build Coastguard Worker   \hDrcData Handle to DRC channel data.
121*e5436536SAndroid Build Coastguard Worker 
122*e5436536SAndroid Build Coastguard Worker   \return none
123*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData)124*e5436536SAndroid Build Coastguard Worker void sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) {
125*e5436536SAndroid Build Coastguard Worker   int band;
126*e5436536SAndroid Build Coastguard Worker 
127*e5436536SAndroid Build Coastguard Worker   if (hDrcData == NULL) {
128*e5436536SAndroid Build Coastguard Worker     return;
129*e5436536SAndroid Build Coastguard Worker   }
130*e5436536SAndroid Build Coastguard Worker 
131*e5436536SAndroid Build Coastguard Worker   for (band = 0; band < (64); band++) {
132*e5436536SAndroid Build Coastguard Worker     hDrcData->prevFact_mag[band] = FL2FXCONST_DBL(0.5f);
133*e5436536SAndroid Build Coastguard Worker   }
134*e5436536SAndroid Build Coastguard Worker 
135*e5436536SAndroid Build Coastguard Worker   for (band = 0; band < SBRDEC_MAX_DRC_BANDS; band++) {
136*e5436536SAndroid Build Coastguard Worker     hDrcData->currFact_mag[band] = FL2FXCONST_DBL(0.5f);
137*e5436536SAndroid Build Coastguard Worker     hDrcData->nextFact_mag[band] = FL2FXCONST_DBL(0.5f);
138*e5436536SAndroid Build Coastguard Worker   }
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker   hDrcData->prevFact_exp = 1;
141*e5436536SAndroid Build Coastguard Worker   hDrcData->currFact_exp = 1;
142*e5436536SAndroid Build Coastguard Worker   hDrcData->nextFact_exp = 1;
143*e5436536SAndroid Build Coastguard Worker 
144*e5436536SAndroid Build Coastguard Worker   hDrcData->numBandsCurr = 1;
145*e5436536SAndroid Build Coastguard Worker   hDrcData->numBandsNext = 1;
146*e5436536SAndroid Build Coastguard Worker 
147*e5436536SAndroid Build Coastguard Worker   hDrcData->winSequenceCurr = 0;
148*e5436536SAndroid Build Coastguard Worker   hDrcData->winSequenceNext = 0;
149*e5436536SAndroid Build Coastguard Worker 
150*e5436536SAndroid Build Coastguard Worker   hDrcData->drcInterpolationSchemeCurr = 0;
151*e5436536SAndroid Build Coastguard Worker   hDrcData->drcInterpolationSchemeNext = 0;
152*e5436536SAndroid Build Coastguard Worker 
153*e5436536SAndroid Build Coastguard Worker   hDrcData->enable = 0;
154*e5436536SAndroid Build Coastguard Worker }
155*e5436536SAndroid Build Coastguard Worker 
156*e5436536SAndroid Build Coastguard Worker /*!
157*e5436536SAndroid Build Coastguard Worker   \brief Swap DRC QMF scaling factors after they have been applied.
158*e5436536SAndroid Build Coastguard Worker 
159*e5436536SAndroid Build Coastguard Worker   \hDrcData Handle to DRC channel data.
160*e5436536SAndroid Build Coastguard Worker 
161*e5436536SAndroid Build Coastguard Worker   \return none
162*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData)163*e5436536SAndroid Build Coastguard Worker void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) {
164*e5436536SAndroid Build Coastguard Worker   if (hDrcData == NULL) {
165*e5436536SAndroid Build Coastguard Worker     return;
166*e5436536SAndroid Build Coastguard Worker   }
167*e5436536SAndroid Build Coastguard Worker   if (hDrcData->enable != 1) {
168*e5436536SAndroid Build Coastguard Worker     return;
169*e5436536SAndroid Build Coastguard Worker   }
170*e5436536SAndroid Build Coastguard Worker 
171*e5436536SAndroid Build Coastguard Worker   /* swap previous data */
172*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(hDrcData->currFact_mag, hDrcData->nextFact_mag,
173*e5436536SAndroid Build Coastguard Worker             SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL));
174*e5436536SAndroid Build Coastguard Worker 
175*e5436536SAndroid Build Coastguard Worker   hDrcData->currFact_exp = hDrcData->nextFact_exp;
176*e5436536SAndroid Build Coastguard Worker 
177*e5436536SAndroid Build Coastguard Worker   hDrcData->numBandsCurr = hDrcData->numBandsNext;
178*e5436536SAndroid Build Coastguard Worker 
179*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(hDrcData->bandTopCurr, hDrcData->bandTopNext,
180*e5436536SAndroid Build Coastguard Worker             SBRDEC_MAX_DRC_BANDS * sizeof(USHORT));
181*e5436536SAndroid Build Coastguard Worker 
182*e5436536SAndroid Build Coastguard Worker   hDrcData->drcInterpolationSchemeCurr = hDrcData->drcInterpolationSchemeNext;
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker   hDrcData->winSequenceCurr = hDrcData->winSequenceNext;
185*e5436536SAndroid Build Coastguard Worker }
186*e5436536SAndroid Build Coastguard Worker 
187*e5436536SAndroid Build Coastguard Worker /*!
188*e5436536SAndroid Build Coastguard Worker   \brief Apply DRC factors slot based.
189*e5436536SAndroid Build Coastguard Worker 
190*e5436536SAndroid Build Coastguard Worker   \hDrcData Handle to DRC channel data.
191*e5436536SAndroid Build Coastguard Worker   \qmfRealSlot Pointer to real valued QMF data of one time slot.
192*e5436536SAndroid Build Coastguard Worker   \qmfImagSlot Pointer to the imaginary QMF data of one time slot.
193*e5436536SAndroid Build Coastguard Worker   \col Number of the time slot.
194*e5436536SAndroid Build Coastguard Worker   \numQmfSubSamples Total number of time slots for one frame.
195*e5436536SAndroid Build Coastguard Worker   \scaleFactor Pointer to the out scale factor of the time slot.
196*e5436536SAndroid Build Coastguard Worker 
197*e5436536SAndroid Build Coastguard Worker   \return None.
198*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData,FIXP_DBL * qmfRealSlot,FIXP_DBL * qmfImagSlot,int col,int numQmfSubSamples,int maxShift)199*e5436536SAndroid Build Coastguard Worker void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData,
200*e5436536SAndroid Build Coastguard Worker                              FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot,
201*e5436536SAndroid Build Coastguard Worker                              int col, int numQmfSubSamples, int maxShift) {
202*e5436536SAndroid Build Coastguard Worker   const UCHAR *winBorderToColMap;
203*e5436536SAndroid Build Coastguard Worker 
204*e5436536SAndroid Build Coastguard Worker   int band, bottomMdct, topMdct, bin, useLP;
205*e5436536SAndroid Build Coastguard Worker   int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */
206*e5436536SAndroid Build Coastguard Worker   int frameLenFlag = (numQmfSubSamples == 30) ? 1 : 0;
207*e5436536SAndroid Build Coastguard Worker   int frameSize = (frameLenFlag == 1) ? 960 : 1024;
208*e5436536SAndroid Build Coastguard Worker 
209*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL *fact_mag = NULL;
210*e5436536SAndroid Build Coastguard Worker   INT fact_exp = 0;
211*e5436536SAndroid Build Coastguard Worker   UINT numBands = 0;
212*e5436536SAndroid Build Coastguard Worker   USHORT *bandTop = NULL;
213*e5436536SAndroid Build Coastguard Worker   int shortDrc = 0;
214*e5436536SAndroid Build Coastguard Worker 
215*e5436536SAndroid Build Coastguard Worker   FIXP_DBL alphaValue = FL2FXCONST_DBL(0.0f);
216*e5436536SAndroid Build Coastguard Worker 
217*e5436536SAndroid Build Coastguard Worker   if (hDrcData == NULL) {
218*e5436536SAndroid Build Coastguard Worker     return;
219*e5436536SAndroid Build Coastguard Worker   }
220*e5436536SAndroid Build Coastguard Worker   if (hDrcData->enable != 1) {
221*e5436536SAndroid Build Coastguard Worker     return;
222*e5436536SAndroid Build Coastguard Worker   }
223*e5436536SAndroid Build Coastguard Worker 
224*e5436536SAndroid Build Coastguard Worker   winBorderToColMap = winBorderToColMappingTab[frameLenFlag];
225*e5436536SAndroid Build Coastguard Worker 
226*e5436536SAndroid Build Coastguard Worker   useLP = (qmfImagSlot == NULL) ? 1 : 0;
227*e5436536SAndroid Build Coastguard Worker 
228*e5436536SAndroid Build Coastguard Worker   col += indx;
229*e5436536SAndroid Build Coastguard Worker   bottomMdct = 0;
230*e5436536SAndroid Build Coastguard Worker 
231*e5436536SAndroid Build Coastguard Worker   /* get respective data and calc interpolation factor */
232*e5436536SAndroid Build Coastguard Worker   if (col < (numQmfSubSamples >> 1)) {    /* first half of current frame */
233*e5436536SAndroid Build Coastguard Worker     if (hDrcData->winSequenceCurr != 2) { /* long window */
234*e5436536SAndroid Build Coastguard Worker       int j = col + (numQmfSubSamples >> 1);
235*e5436536SAndroid Build Coastguard Worker 
236*e5436536SAndroid Build Coastguard Worker       if (j < winBorderToColMap[15]) {
237*e5436536SAndroid Build Coastguard Worker         if (hDrcData->drcInterpolationSchemeCurr == 0) {
238*e5436536SAndroid Build Coastguard Worker           INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
239*e5436536SAndroid Build Coastguard Worker 
240*e5436536SAndroid Build Coastguard Worker           alphaValue = (FIXP_DBL)(j * k);
241*e5436536SAndroid Build Coastguard Worker         } else {
242*e5436536SAndroid Build Coastguard Worker           if (j >=
243*e5436536SAndroid Build Coastguard Worker               (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) {
244*e5436536SAndroid Build Coastguard Worker             alphaValue = (FIXP_DBL)MAXVAL_DBL;
245*e5436536SAndroid Build Coastguard Worker           }
246*e5436536SAndroid Build Coastguard Worker         }
247*e5436536SAndroid Build Coastguard Worker       } else {
248*e5436536SAndroid Build Coastguard Worker         alphaValue = (FIXP_DBL)MAXVAL_DBL;
249*e5436536SAndroid Build Coastguard Worker       }
250*e5436536SAndroid Build Coastguard Worker     } else { /* short windows */
251*e5436536SAndroid Build Coastguard Worker       shortDrc = 1;
252*e5436536SAndroid Build Coastguard Worker     }
253*e5436536SAndroid Build Coastguard Worker 
254*e5436536SAndroid Build Coastguard Worker     fact_mag = hDrcData->currFact_mag;
255*e5436536SAndroid Build Coastguard Worker     fact_exp = hDrcData->currFact_exp;
256*e5436536SAndroid Build Coastguard Worker     numBands = hDrcData->numBandsCurr;
257*e5436536SAndroid Build Coastguard Worker     bandTop = hDrcData->bandTopCurr;
258*e5436536SAndroid Build Coastguard Worker   } else if (col < numQmfSubSamples) {    /* second half of current frame */
259*e5436536SAndroid Build Coastguard Worker     if (hDrcData->winSequenceNext != 2) { /* next: long window */
260*e5436536SAndroid Build Coastguard Worker       int j = col - (numQmfSubSamples >> 1);
261*e5436536SAndroid Build Coastguard Worker 
262*e5436536SAndroid Build Coastguard Worker       if (j < winBorderToColMap[15]) {
263*e5436536SAndroid Build Coastguard Worker         if (hDrcData->drcInterpolationSchemeNext == 0) {
264*e5436536SAndroid Build Coastguard Worker           INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
265*e5436536SAndroid Build Coastguard Worker 
266*e5436536SAndroid Build Coastguard Worker           alphaValue = (FIXP_DBL)(j * k);
267*e5436536SAndroid Build Coastguard Worker         } else {
268*e5436536SAndroid Build Coastguard Worker           if (j >=
269*e5436536SAndroid Build Coastguard Worker               (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
270*e5436536SAndroid Build Coastguard Worker             alphaValue = (FIXP_DBL)MAXVAL_DBL;
271*e5436536SAndroid Build Coastguard Worker           }
272*e5436536SAndroid Build Coastguard Worker         }
273*e5436536SAndroid Build Coastguard Worker       } else {
274*e5436536SAndroid Build Coastguard Worker         alphaValue = (FIXP_DBL)MAXVAL_DBL;
275*e5436536SAndroid Build Coastguard Worker       }
276*e5436536SAndroid Build Coastguard Worker 
277*e5436536SAndroid Build Coastguard Worker       fact_mag = hDrcData->nextFact_mag;
278*e5436536SAndroid Build Coastguard Worker       fact_exp = hDrcData->nextFact_exp;
279*e5436536SAndroid Build Coastguard Worker       numBands = hDrcData->numBandsNext;
280*e5436536SAndroid Build Coastguard Worker       bandTop = hDrcData->bandTopNext;
281*e5436536SAndroid Build Coastguard Worker     } else {                                /* next: short windows */
282*e5436536SAndroid Build Coastguard Worker       if (hDrcData->winSequenceCurr != 2) { /* current: long window */
283*e5436536SAndroid Build Coastguard Worker         alphaValue = (FIXP_DBL)0;
284*e5436536SAndroid Build Coastguard Worker 
285*e5436536SAndroid Build Coastguard Worker         fact_mag = hDrcData->nextFact_mag;
286*e5436536SAndroid Build Coastguard Worker         fact_exp = hDrcData->nextFact_exp;
287*e5436536SAndroid Build Coastguard Worker         numBands = hDrcData->numBandsNext;
288*e5436536SAndroid Build Coastguard Worker         bandTop = hDrcData->bandTopNext;
289*e5436536SAndroid Build Coastguard Worker       } else { /* current: short windows */
290*e5436536SAndroid Build Coastguard Worker         shortDrc = 1;
291*e5436536SAndroid Build Coastguard Worker 
292*e5436536SAndroid Build Coastguard Worker         fact_mag = hDrcData->currFact_mag;
293*e5436536SAndroid Build Coastguard Worker         fact_exp = hDrcData->currFact_exp;
294*e5436536SAndroid Build Coastguard Worker         numBands = hDrcData->numBandsCurr;
295*e5436536SAndroid Build Coastguard Worker         bandTop = hDrcData->bandTopCurr;
296*e5436536SAndroid Build Coastguard Worker       }
297*e5436536SAndroid Build Coastguard Worker     }
298*e5436536SAndroid Build Coastguard Worker   } else {                                /* first half of next frame */
299*e5436536SAndroid Build Coastguard Worker     if (hDrcData->winSequenceNext != 2) { /* long window */
300*e5436536SAndroid Build Coastguard Worker       int j = col - (numQmfSubSamples >> 1);
301*e5436536SAndroid Build Coastguard Worker 
302*e5436536SAndroid Build Coastguard Worker       if (j < winBorderToColMap[15]) {
303*e5436536SAndroid Build Coastguard Worker         if (hDrcData->drcInterpolationSchemeNext == 0) {
304*e5436536SAndroid Build Coastguard Worker           INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
305*e5436536SAndroid Build Coastguard Worker 
306*e5436536SAndroid Build Coastguard Worker           alphaValue = (FIXP_DBL)(j * k);
307*e5436536SAndroid Build Coastguard Worker         } else {
308*e5436536SAndroid Build Coastguard Worker           if (j >=
309*e5436536SAndroid Build Coastguard Worker               (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
310*e5436536SAndroid Build Coastguard Worker             alphaValue = (FIXP_DBL)MAXVAL_DBL;
311*e5436536SAndroid Build Coastguard Worker           }
312*e5436536SAndroid Build Coastguard Worker         }
313*e5436536SAndroid Build Coastguard Worker       } else {
314*e5436536SAndroid Build Coastguard Worker         alphaValue = (FIXP_DBL)MAXVAL_DBL;
315*e5436536SAndroid Build Coastguard Worker       }
316*e5436536SAndroid Build Coastguard Worker     } else { /* short windows */
317*e5436536SAndroid Build Coastguard Worker       shortDrc = 1;
318*e5436536SAndroid Build Coastguard Worker     }
319*e5436536SAndroid Build Coastguard Worker 
320*e5436536SAndroid Build Coastguard Worker     fact_mag = hDrcData->nextFact_mag;
321*e5436536SAndroid Build Coastguard Worker     fact_exp = hDrcData->nextFact_exp;
322*e5436536SAndroid Build Coastguard Worker     numBands = hDrcData->numBandsNext;
323*e5436536SAndroid Build Coastguard Worker     bandTop = hDrcData->bandTopNext;
324*e5436536SAndroid Build Coastguard Worker 
325*e5436536SAndroid Build Coastguard Worker     col -= numQmfSubSamples;
326*e5436536SAndroid Build Coastguard Worker   }
327*e5436536SAndroid Build Coastguard Worker 
328*e5436536SAndroid Build Coastguard Worker   /* process bands */
329*e5436536SAndroid Build Coastguard Worker   for (band = 0; band < (int)numBands; band++) {
330*e5436536SAndroid Build Coastguard Worker     int bottomQmf, topQmf;
331*e5436536SAndroid Build Coastguard Worker 
332*e5436536SAndroid Build Coastguard Worker     FIXP_DBL drcFact_mag = (FIXP_DBL)MAXVAL_DBL;
333*e5436536SAndroid Build Coastguard Worker 
334*e5436536SAndroid Build Coastguard Worker     topMdct = (bandTop[band] + 1) << 2;
335*e5436536SAndroid Build Coastguard Worker 
336*e5436536SAndroid Build Coastguard Worker     if (!shortDrc) { /* long window */
337*e5436536SAndroid Build Coastguard Worker       if (frameLenFlag) {
338*e5436536SAndroid Build Coastguard Worker         /* 960 framing */
339*e5436536SAndroid Build Coastguard Worker         bottomQmf = fMultIfloor((FIXP_DBL)0x4444445, bottomMdct);
340*e5436536SAndroid Build Coastguard Worker         topQmf = fMultIfloor((FIXP_DBL)0x4444445, topMdct);
341*e5436536SAndroid Build Coastguard Worker 
342*e5436536SAndroid Build Coastguard Worker         topMdct = 30 * topQmf;
343*e5436536SAndroid Build Coastguard Worker       } else {
344*e5436536SAndroid Build Coastguard Worker         /* 1024 framing */
345*e5436536SAndroid Build Coastguard Worker         topMdct &= ~0x1f;
346*e5436536SAndroid Build Coastguard Worker 
347*e5436536SAndroid Build Coastguard Worker         bottomQmf = bottomMdct >> 5;
348*e5436536SAndroid Build Coastguard Worker         topQmf = topMdct >> 5;
349*e5436536SAndroid Build Coastguard Worker       }
350*e5436536SAndroid Build Coastguard Worker 
351*e5436536SAndroid Build Coastguard Worker       if (band == ((int)numBands - 1)) {
352*e5436536SAndroid Build Coastguard Worker         topQmf = (64);
353*e5436536SAndroid Build Coastguard Worker       }
354*e5436536SAndroid Build Coastguard Worker 
355*e5436536SAndroid Build Coastguard Worker       for (bin = bottomQmf; bin < topQmf; bin++) {
356*e5436536SAndroid Build Coastguard Worker         FIXP_DBL drcFact1_mag = hDrcData->prevFact_mag[bin];
357*e5436536SAndroid Build Coastguard Worker         FIXP_DBL drcFact2_mag = fact_mag[band];
358*e5436536SAndroid Build Coastguard Worker 
359*e5436536SAndroid Build Coastguard Worker         /* normalize scale factors */
360*e5436536SAndroid Build Coastguard Worker         if (hDrcData->prevFact_exp < maxShift) {
361*e5436536SAndroid Build Coastguard Worker           drcFact1_mag >>= maxShift - hDrcData->prevFact_exp;
362*e5436536SAndroid Build Coastguard Worker         }
363*e5436536SAndroid Build Coastguard Worker         if (fact_exp < maxShift) {
364*e5436536SAndroid Build Coastguard Worker           drcFact2_mag >>= maxShift - fact_exp;
365*e5436536SAndroid Build Coastguard Worker         }
366*e5436536SAndroid Build Coastguard Worker 
367*e5436536SAndroid Build Coastguard Worker         /* interpolate */
368*e5436536SAndroid Build Coastguard Worker         if (alphaValue == (FIXP_DBL)0) {
369*e5436536SAndroid Build Coastguard Worker           drcFact_mag = drcFact1_mag;
370*e5436536SAndroid Build Coastguard Worker         } else if (alphaValue == (FIXP_DBL)MAXVAL_DBL) {
371*e5436536SAndroid Build Coastguard Worker           drcFact_mag = drcFact2_mag;
372*e5436536SAndroid Build Coastguard Worker         } else {
373*e5436536SAndroid Build Coastguard Worker           drcFact_mag =
374*e5436536SAndroid Build Coastguard Worker               fMult(alphaValue, drcFact2_mag) +
375*e5436536SAndroid Build Coastguard Worker               fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag);
376*e5436536SAndroid Build Coastguard Worker         }
377*e5436536SAndroid Build Coastguard Worker 
378*e5436536SAndroid Build Coastguard Worker         /* apply scaling */
379*e5436536SAndroid Build Coastguard Worker         qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag);
380*e5436536SAndroid Build Coastguard Worker         if (!useLP) {
381*e5436536SAndroid Build Coastguard Worker           qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag);
382*e5436536SAndroid Build Coastguard Worker         }
383*e5436536SAndroid Build Coastguard Worker 
384*e5436536SAndroid Build Coastguard Worker         /* save previous factors */
385*e5436536SAndroid Build Coastguard Worker         if (col == (numQmfSubSamples >> 1) - 1) {
386*e5436536SAndroid Build Coastguard Worker           hDrcData->prevFact_mag[bin] = fact_mag[band];
387*e5436536SAndroid Build Coastguard Worker         }
388*e5436536SAndroid Build Coastguard Worker       }
389*e5436536SAndroid Build Coastguard Worker     } else { /* short windows */
390*e5436536SAndroid Build Coastguard Worker       unsigned startWinIdx, stopWinIdx;
391*e5436536SAndroid Build Coastguard Worker       int startCol, stopCol;
392*e5436536SAndroid Build Coastguard Worker       FIXP_DBL invFrameSizeDiv8 =
393*e5436536SAndroid Build Coastguard Worker           (frameLenFlag) ? (FIXP_DBL)0x1111112 : (FIXP_DBL)0x1000000;
394*e5436536SAndroid Build Coastguard Worker 
395*e5436536SAndroid Build Coastguard Worker       /* limit top at the frame borders */
396*e5436536SAndroid Build Coastguard Worker       if (topMdct < 0) {
397*e5436536SAndroid Build Coastguard Worker         topMdct = 0;
398*e5436536SAndroid Build Coastguard Worker       }
399*e5436536SAndroid Build Coastguard Worker       if (topMdct >= frameSize) {
400*e5436536SAndroid Build Coastguard Worker         topMdct = frameSize - 1;
401*e5436536SAndroid Build Coastguard Worker       }
402*e5436536SAndroid Build Coastguard Worker 
403*e5436536SAndroid Build Coastguard Worker       if (frameLenFlag) {
404*e5436536SAndroid Build Coastguard Worker         /*  960 framing */
405*e5436536SAndroid Build Coastguard Worker         topMdct = fMultIfloor((FIXP_DBL)0x78000000,
406*e5436536SAndroid Build Coastguard Worker                               fMultIfloor((FIXP_DBL)0x22222223, topMdct) << 2);
407*e5436536SAndroid Build Coastguard Worker 
408*e5436536SAndroid Build Coastguard Worker         startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) +
409*e5436536SAndroid Build Coastguard Worker                       1; /* winBorderToColMap table has offset of 1 */
410*e5436536SAndroid Build Coastguard Worker         stopWinIdx = fMultIceil(invFrameSizeDiv8 - (FIXP_DBL)1, topMdct) + 1;
411*e5436536SAndroid Build Coastguard Worker       } else {
412*e5436536SAndroid Build Coastguard Worker         /* 1024 framing */
413*e5436536SAndroid Build Coastguard Worker         topMdct &= ~0x03;
414*e5436536SAndroid Build Coastguard Worker 
415*e5436536SAndroid Build Coastguard Worker         startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + 1;
416*e5436536SAndroid Build Coastguard Worker         stopWinIdx = fMultIceil(invFrameSizeDiv8, topMdct) + 1;
417*e5436536SAndroid Build Coastguard Worker       }
418*e5436536SAndroid Build Coastguard Worker 
419*e5436536SAndroid Build Coastguard Worker       /* startCol is truncated to the nearest corresponding start subsample in
420*e5436536SAndroid Build Coastguard Worker          the QMF of the short window bottom is present in:*/
421*e5436536SAndroid Build Coastguard Worker       startCol = (int)winBorderToColMap[startWinIdx];
422*e5436536SAndroid Build Coastguard Worker 
423*e5436536SAndroid Build Coastguard Worker       /* stopCol is rounded upwards to the nearest corresponding stop subsample
424*e5436536SAndroid Build Coastguard Worker          in the QMF of the short window top is present in. */
425*e5436536SAndroid Build Coastguard Worker       stopCol = (int)winBorderToColMap[stopWinIdx];
426*e5436536SAndroid Build Coastguard Worker 
427*e5436536SAndroid Build Coastguard Worker       bottomQmf = fMultIfloor(invFrameSizeDiv8,
428*e5436536SAndroid Build Coastguard Worker                               ((bottomMdct % (numQmfSubSamples << 2)) << 5));
429*e5436536SAndroid Build Coastguard Worker       topQmf = fMultIfloor(invFrameSizeDiv8,
430*e5436536SAndroid Build Coastguard Worker                            ((topMdct % (numQmfSubSamples << 2)) << 5));
431*e5436536SAndroid Build Coastguard Worker 
432*e5436536SAndroid Build Coastguard Worker       /* extend last band */
433*e5436536SAndroid Build Coastguard Worker       if (band == ((int)numBands - 1)) {
434*e5436536SAndroid Build Coastguard Worker         topQmf = (64);
435*e5436536SAndroid Build Coastguard Worker         stopCol = numQmfSubSamples;
436*e5436536SAndroid Build Coastguard Worker         stopWinIdx = 10;
437*e5436536SAndroid Build Coastguard Worker       }
438*e5436536SAndroid Build Coastguard Worker 
439*e5436536SAndroid Build Coastguard Worker       if (topQmf == 0) {
440*e5436536SAndroid Build Coastguard Worker         if (frameLenFlag) {
441*e5436536SAndroid Build Coastguard Worker           FIXP_DBL rem = fMult(invFrameSizeDiv8,
442*e5436536SAndroid Build Coastguard Worker                                (FIXP_DBL)(topMdct << (DFRACT_BITS - 12)));
443*e5436536SAndroid Build Coastguard Worker           if ((LONG)rem & (LONG)0x1F) {
444*e5436536SAndroid Build Coastguard Worker             stopWinIdx -= 1;
445*e5436536SAndroid Build Coastguard Worker             stopCol = (int)winBorderToColMap[stopWinIdx];
446*e5436536SAndroid Build Coastguard Worker           }
447*e5436536SAndroid Build Coastguard Worker         }
448*e5436536SAndroid Build Coastguard Worker         topQmf = (64);
449*e5436536SAndroid Build Coastguard Worker       }
450*e5436536SAndroid Build Coastguard Worker 
451*e5436536SAndroid Build Coastguard Worker       /* save previous factors */
452*e5436536SAndroid Build Coastguard Worker       if (stopCol == numQmfSubSamples) {
453*e5436536SAndroid Build Coastguard Worker         int tmpBottom = bottomQmf;
454*e5436536SAndroid Build Coastguard Worker 
455*e5436536SAndroid Build Coastguard Worker         if ((int)winBorderToColMap[8] > startCol) {
456*e5436536SAndroid Build Coastguard Worker           tmpBottom = 0; /* band starts in previous short window */
457*e5436536SAndroid Build Coastguard Worker         }
458*e5436536SAndroid Build Coastguard Worker 
459*e5436536SAndroid Build Coastguard Worker         for (bin = tmpBottom; bin < topQmf; bin++) {
460*e5436536SAndroid Build Coastguard Worker           hDrcData->prevFact_mag[bin] = fact_mag[band];
461*e5436536SAndroid Build Coastguard Worker         }
462*e5436536SAndroid Build Coastguard Worker       }
463*e5436536SAndroid Build Coastguard Worker 
464*e5436536SAndroid Build Coastguard Worker       /* apply */
465*e5436536SAndroid Build Coastguard Worker       if ((col >= startCol) && (col < stopCol)) {
466*e5436536SAndroid Build Coastguard Worker         if (col >= (int)winBorderToColMap[startWinIdx + 1]) {
467*e5436536SAndroid Build Coastguard Worker           bottomQmf = 0; /* band starts in previous short window */
468*e5436536SAndroid Build Coastguard Worker         }
469*e5436536SAndroid Build Coastguard Worker         if (col < (int)winBorderToColMap[stopWinIdx - 1]) {
470*e5436536SAndroid Build Coastguard Worker           topQmf = (64); /* band ends in next short window */
471*e5436536SAndroid Build Coastguard Worker         }
472*e5436536SAndroid Build Coastguard Worker 
473*e5436536SAndroid Build Coastguard Worker         drcFact_mag = fact_mag[band];
474*e5436536SAndroid Build Coastguard Worker 
475*e5436536SAndroid Build Coastguard Worker         /* normalize scale factor */
476*e5436536SAndroid Build Coastguard Worker         if (fact_exp < maxShift) {
477*e5436536SAndroid Build Coastguard Worker           drcFact_mag >>= maxShift - fact_exp;
478*e5436536SAndroid Build Coastguard Worker         }
479*e5436536SAndroid Build Coastguard Worker 
480*e5436536SAndroid Build Coastguard Worker         /* apply scaling */
481*e5436536SAndroid Build Coastguard Worker         for (bin = bottomQmf; bin < topQmf; bin++) {
482*e5436536SAndroid Build Coastguard Worker           qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag);
483*e5436536SAndroid Build Coastguard Worker           if (!useLP) {
484*e5436536SAndroid Build Coastguard Worker             qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag);
485*e5436536SAndroid Build Coastguard Worker           }
486*e5436536SAndroid Build Coastguard Worker         }
487*e5436536SAndroid Build Coastguard Worker       }
488*e5436536SAndroid Build Coastguard Worker     }
489*e5436536SAndroid Build Coastguard Worker 
490*e5436536SAndroid Build Coastguard Worker     bottomMdct = topMdct;
491*e5436536SAndroid Build Coastguard Worker   } /* end of bands loop */
492*e5436536SAndroid Build Coastguard Worker 
493*e5436536SAndroid Build Coastguard Worker   if (col == (numQmfSubSamples >> 1) - 1) {
494*e5436536SAndroid Build Coastguard Worker     hDrcData->prevFact_exp = fact_exp;
495*e5436536SAndroid Build Coastguard Worker   }
496*e5436536SAndroid Build Coastguard Worker }
497*e5436536SAndroid Build Coastguard Worker 
498*e5436536SAndroid Build Coastguard Worker /*!
499*e5436536SAndroid Build Coastguard Worker   \brief Apply DRC factors frame based.
500*e5436536SAndroid Build Coastguard Worker 
501*e5436536SAndroid Build Coastguard Worker   \hDrcData Handle to DRC channel data.
502*e5436536SAndroid Build Coastguard Worker   \qmfRealSlot Pointer to real valued QMF data of the whole frame.
503*e5436536SAndroid Build Coastguard Worker   \qmfImagSlot Pointer to the imaginary QMF data of the whole frame.
504*e5436536SAndroid Build Coastguard Worker   \numQmfSubSamples Total number of time slots for one frame.
505*e5436536SAndroid Build Coastguard Worker   \scaleFactor Pointer to the out scale factor of the frame.
506*e5436536SAndroid Build Coastguard Worker 
507*e5436536SAndroid Build Coastguard Worker   \return None.
508*e5436536SAndroid Build Coastguard Worker */
sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData,FIXP_DBL ** QmfBufferReal,FIXP_DBL ** QmfBufferImag,int numQmfSubSamples,int * scaleFactor)509*e5436536SAndroid Build Coastguard Worker void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData,
510*e5436536SAndroid Build Coastguard Worker                          FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag,
511*e5436536SAndroid Build Coastguard Worker                          int numQmfSubSamples, int *scaleFactor) {
512*e5436536SAndroid Build Coastguard Worker   int col;
513*e5436536SAndroid Build Coastguard Worker   int maxShift = 0;
514*e5436536SAndroid Build Coastguard Worker 
515*e5436536SAndroid Build Coastguard Worker   if (hDrcData == NULL) {
516*e5436536SAndroid Build Coastguard Worker     return;
517*e5436536SAndroid Build Coastguard Worker   }
518*e5436536SAndroid Build Coastguard Worker   if (hDrcData->enable == 0) {
519*e5436536SAndroid Build Coastguard Worker     return; /* Avoid changing the scaleFactor even though the processing is
520*e5436536SAndroid Build Coastguard Worker                disabled. */
521*e5436536SAndroid Build Coastguard Worker   }
522*e5436536SAndroid Build Coastguard Worker 
523*e5436536SAndroid Build Coastguard Worker   /* get max scale factor */
524*e5436536SAndroid Build Coastguard Worker   if (hDrcData->prevFact_exp > maxShift) {
525*e5436536SAndroid Build Coastguard Worker     maxShift = hDrcData->prevFact_exp;
526*e5436536SAndroid Build Coastguard Worker   }
527*e5436536SAndroid Build Coastguard Worker   if (hDrcData->currFact_exp > maxShift) {
528*e5436536SAndroid Build Coastguard Worker     maxShift = hDrcData->currFact_exp;
529*e5436536SAndroid Build Coastguard Worker   }
530*e5436536SAndroid Build Coastguard Worker   if (hDrcData->nextFact_exp > maxShift) {
531*e5436536SAndroid Build Coastguard Worker     maxShift = hDrcData->nextFact_exp;
532*e5436536SAndroid Build Coastguard Worker   }
533*e5436536SAndroid Build Coastguard Worker 
534*e5436536SAndroid Build Coastguard Worker   for (col = 0; col < numQmfSubSamples; col++) {
535*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *qmfSlotReal = QmfBufferReal[col];
536*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *qmfSlotImag = (QmfBufferImag == NULL) ? NULL : QmfBufferImag[col];
537*e5436536SAndroid Build Coastguard Worker 
538*e5436536SAndroid Build Coastguard Worker     sbrDecoder_drcApplySlot(hDrcData, qmfSlotReal, qmfSlotImag, col,
539*e5436536SAndroid Build Coastguard Worker                             numQmfSubSamples, maxShift);
540*e5436536SAndroid Build Coastguard Worker   }
541*e5436536SAndroid Build Coastguard Worker 
542*e5436536SAndroid Build Coastguard Worker   *scaleFactor += maxShift;
543*e5436536SAndroid Build Coastguard Worker }
544