1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /************************* 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_process.h"
106*e5436536SAndroid Build Coastguard Worker
107*e5436536SAndroid Build Coastguard Worker #define E_TGAINSTEP 12
108*e5436536SAndroid Build Coastguard Worker
_prepareLnbIndex(ACTIVE_DRC * pActiveDrc,const int channelOffset,const int drcChannelOffset,const int numChannelsProcessed,const int lnbPointer)109*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _prepareLnbIndex(ACTIVE_DRC* pActiveDrc,
110*e5436536SAndroid Build Coastguard Worker const int channelOffset,
111*e5436536SAndroid Build Coastguard Worker const int drcChannelOffset,
112*e5436536SAndroid Build Coastguard Worker const int numChannelsProcessed,
113*e5436536SAndroid Build Coastguard Worker const int lnbPointer) {
114*e5436536SAndroid Build Coastguard Worker int g, c;
115*e5436536SAndroid Build Coastguard Worker DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst;
116*e5436536SAndroid Build Coastguard Worker
117*e5436536SAndroid Build Coastguard Worker /* channelOffset: start index of physical channels
118*e5436536SAndroid Build Coastguard Worker numChannelsProcessed: number of processed channels, physical channels and
119*e5436536SAndroid Build Coastguard Worker DRC channels channelOffset + drcChannelOffset: start index of DRC channels,
120*e5436536SAndroid Build Coastguard Worker i.e. the channel order referenced in pInst.sequenceIndex */
121*e5436536SAndroid Build Coastguard Worker
122*e5436536SAndroid Build Coastguard Worker /* sanity checks */
123*e5436536SAndroid Build Coastguard Worker if ((channelOffset + numChannelsProcessed) > 8) return DE_NOT_OK;
124*e5436536SAndroid Build Coastguard Worker
125*e5436536SAndroid Build Coastguard Worker if ((channelOffset + drcChannelOffset + numChannelsProcessed) > 8)
126*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker if ((channelOffset + drcChannelOffset) < 0) return DE_NOT_OK;
129*e5436536SAndroid Build Coastguard Worker
130*e5436536SAndroid Build Coastguard Worker /* prepare lnbIndexForChannel, a map of indices from each channel to its
131*e5436536SAndroid Build Coastguard Worker * corresponding linearNodeBuffer instance */
132*e5436536SAndroid Build Coastguard Worker for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) {
133*e5436536SAndroid Build Coastguard Worker if (pInst->drcSetId > 0) {
134*e5436536SAndroid Build Coastguard Worker int drcChannel = c + drcChannelOffset;
135*e5436536SAndroid Build Coastguard Worker /* fallback for configuration with more physical channels than DRC
136*e5436536SAndroid Build Coastguard Worker channels: reuse DRC gain of first channel. This is necessary for HE-AAC
137*e5436536SAndroid Build Coastguard Worker mono with stereo output */
138*e5436536SAndroid Build Coastguard Worker if (drcChannel >= pInst->drcChannelCount) drcChannel = 0;
139*e5436536SAndroid Build Coastguard Worker g = pActiveDrc->channelGroupForChannel[drcChannel];
140*e5436536SAndroid Build Coastguard Worker if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) {
141*e5436536SAndroid Build Coastguard Worker pActiveDrc->lnbIndexForChannel[c][lnbPointer] =
142*e5436536SAndroid Build Coastguard Worker pActiveDrc->activeDrcOffset + pActiveDrc->gainElementForGroup[g];
143*e5436536SAndroid Build Coastguard Worker }
144*e5436536SAndroid Build Coastguard Worker }
145*e5436536SAndroid Build Coastguard Worker }
146*e5436536SAndroid Build Coastguard Worker
147*e5436536SAndroid Build Coastguard Worker return DE_OK;
148*e5436536SAndroid Build Coastguard Worker }
149*e5436536SAndroid Build Coastguard Worker
_interpolateDrcGain(const GAIN_INTERPOLATION_TYPE gainInterpolationType,const SHORT timePrev,const SHORT tGainStep,const SHORT start,const SHORT stop,const SHORT stepsize,const FIXP_DBL gainLeft,const FIXP_DBL gainRight,const FIXP_DBL slopeLeft,const FIXP_DBL slopeRight,FIXP_DBL * buffer)150*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _interpolateDrcGain(
151*e5436536SAndroid Build Coastguard Worker const GAIN_INTERPOLATION_TYPE gainInterpolationType,
152*e5436536SAndroid Build Coastguard Worker const SHORT timePrev, /* time0 */
153*e5436536SAndroid Build Coastguard Worker const SHORT tGainStep, /* time1 - time0 */
154*e5436536SAndroid Build Coastguard Worker const SHORT start, const SHORT stop, const SHORT stepsize,
155*e5436536SAndroid Build Coastguard Worker const FIXP_DBL gainLeft, const FIXP_DBL gainRight, const FIXP_DBL slopeLeft,
156*e5436536SAndroid Build Coastguard Worker const FIXP_DBL slopeRight, FIXP_DBL* buffer) {
157*e5436536SAndroid Build Coastguard Worker int n, n_buf;
158*e5436536SAndroid Build Coastguard Worker int start_modulo, start_offset;
159*e5436536SAndroid Build Coastguard Worker
160*e5436536SAndroid Build Coastguard Worker if (tGainStep < 0) {
161*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
162*e5436536SAndroid Build Coastguard Worker }
163*e5436536SAndroid Build Coastguard Worker if (tGainStep == 0) {
164*e5436536SAndroid Build Coastguard Worker return DE_OK;
165*e5436536SAndroid Build Coastguard Worker }
166*e5436536SAndroid Build Coastguard Worker
167*e5436536SAndroid Build Coastguard Worker /* get start index offset and buffer index for downsampled interpolation */
168*e5436536SAndroid Build Coastguard Worker /* start_modulo = (start+timePrev)%stepsize; */ /* stepsize is a power of 2 */
169*e5436536SAndroid Build Coastguard Worker start_modulo = (start + timePrev) & (stepsize - 1);
170*e5436536SAndroid Build Coastguard Worker start_offset = (start_modulo ? stepsize - start_modulo : 0);
171*e5436536SAndroid Build Coastguard Worker /* n_buf = (start + timePrev + start_offset)/stepsize; */
172*e5436536SAndroid Build Coastguard Worker n_buf = (start + timePrev + start_offset) >> (15 - fixnormz_S(stepsize));
173*e5436536SAndroid Build Coastguard Worker
174*e5436536SAndroid Build Coastguard Worker { /* gainInterpolationType == GIT_LINEAR */
175*e5436536SAndroid Build Coastguard Worker LONG a;
176*e5436536SAndroid Build Coastguard Worker /* runs = ceil((stop - start - start_offset)/stepsize). This works for
177*e5436536SAndroid Build Coastguard Worker * stepsize = 2^N only. */
178*e5436536SAndroid Build Coastguard Worker INT runs = (INT)(stop - start - start_offset + stepsize - 1) >>
179*e5436536SAndroid Build Coastguard Worker (30 - CountLeadingBits(stepsize));
180*e5436536SAndroid Build Coastguard Worker INT n_min = fMin(
181*e5436536SAndroid Build Coastguard Worker fMin(CntLeadingZeros(gainRight), CntLeadingZeros(gainLeft)) - 1, 8);
182*e5436536SAndroid Build Coastguard Worker a = (LONG)((gainRight << n_min) - (gainLeft << n_min)) / tGainStep;
183*e5436536SAndroid Build Coastguard Worker LONG a_step = a * stepsize;
184*e5436536SAndroid Build Coastguard Worker n = start + start_offset;
185*e5436536SAndroid Build Coastguard Worker a = a * n + (LONG)(gainLeft << n_min);
186*e5436536SAndroid Build Coastguard Worker buffer += n_buf;
187*e5436536SAndroid Build Coastguard Worker #if defined(FUNCTION_interpolateDrcGain_func1)
188*e5436536SAndroid Build Coastguard Worker interpolateDrcGain_func1(buffer, a, a_step, n_min, runs);
189*e5436536SAndroid Build Coastguard Worker #else
190*e5436536SAndroid Build Coastguard Worker a -= a_step;
191*e5436536SAndroid Build Coastguard Worker n_min = 8 - n_min;
192*e5436536SAndroid Build Coastguard Worker for (int i = 0; i < runs; i++) {
193*e5436536SAndroid Build Coastguard Worker a += a_step;
194*e5436536SAndroid Build Coastguard Worker buffer[i] = fMultDiv2(buffer[i], (FIXP_DBL)a) << n_min;
195*e5436536SAndroid Build Coastguard Worker }
196*e5436536SAndroid Build Coastguard Worker #endif /* defined(FUNCTION_interpolateDrcGain_func1) */
197*e5436536SAndroid Build Coastguard Worker }
198*e5436536SAndroid Build Coastguard Worker return DE_OK;
199*e5436536SAndroid Build Coastguard Worker }
200*e5436536SAndroid Build Coastguard Worker
_processNodeSegments(const int frameSize,const GAIN_INTERPOLATION_TYPE gainInterpolationType,const int nNodes,const NODE_LIN * pNodeLin,const int offset,const SHORT stepsize,const NODE_LIN nodePrevious,const FIXP_DBL channelGain,FIXP_DBL * buffer)201*e5436536SAndroid Build Coastguard Worker static DRC_ERROR _processNodeSegments(
202*e5436536SAndroid Build Coastguard Worker const int frameSize, const GAIN_INTERPOLATION_TYPE gainInterpolationType,
203*e5436536SAndroid Build Coastguard Worker const int nNodes, const NODE_LIN* pNodeLin, const int offset,
204*e5436536SAndroid Build Coastguard Worker const SHORT stepsize,
205*e5436536SAndroid Build Coastguard Worker const NODE_LIN nodePrevious, /* the last node of the previous frame */
206*e5436536SAndroid Build Coastguard Worker const FIXP_DBL channelGain, FIXP_DBL* buffer) {
207*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
208*e5436536SAndroid Build Coastguard Worker SHORT timePrev, duration, start, stop, time;
209*e5436536SAndroid Build Coastguard Worker int n;
210*e5436536SAndroid Build Coastguard Worker FIXP_DBL gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)), gainLinPrev;
211*e5436536SAndroid Build Coastguard Worker FIXP_DBL slopeLin = (FIXP_DBL)0, slopeLinPrev = (FIXP_DBL)0;
212*e5436536SAndroid Build Coastguard Worker
213*e5436536SAndroid Build Coastguard Worker timePrev = nodePrevious.time + offset;
214*e5436536SAndroid Build Coastguard Worker gainLinPrev = nodePrevious.gainLin;
215*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nNodes; n++) {
216*e5436536SAndroid Build Coastguard Worker time = pNodeLin[n].time + offset;
217*e5436536SAndroid Build Coastguard Worker duration = time - timePrev;
218*e5436536SAndroid Build Coastguard Worker gainLin = pNodeLin[n].gainLin;
219*e5436536SAndroid Build Coastguard Worker if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8)))
220*e5436536SAndroid Build Coastguard Worker gainLin =
221*e5436536SAndroid Build Coastguard Worker SATURATE_LEFT_SHIFT(fMultDiv2(gainLin, channelGain), 9, DFRACT_BITS);
222*e5436536SAndroid Build Coastguard Worker
223*e5436536SAndroid Build Coastguard Worker if ((timePrev >= (frameSize - 1)) ||
224*e5436536SAndroid Build Coastguard Worker (time < 0)) { /* This segment (between previous and current node) lies
225*e5436536SAndroid Build Coastguard Worker outside of this audio frame */
226*e5436536SAndroid Build Coastguard Worker timePrev = time;
227*e5436536SAndroid Build Coastguard Worker gainLinPrev = gainLin;
228*e5436536SAndroid Build Coastguard Worker slopeLinPrev = slopeLin;
229*e5436536SAndroid Build Coastguard Worker continue;
230*e5436536SAndroid Build Coastguard Worker }
231*e5436536SAndroid Build Coastguard Worker
232*e5436536SAndroid Build Coastguard Worker /* start and stop are the boundaries of the region of this segment that lie
233*e5436536SAndroid Build Coastguard Worker within this audio frame. Their values are relative to the beginning of
234*e5436536SAndroid Build Coastguard Worker this segment. stop is the first sample that isn't processed any more. */
235*e5436536SAndroid Build Coastguard Worker start = fMax(-timePrev, 1);
236*e5436536SAndroid Build Coastguard Worker stop = fMin(time, (SHORT)(frameSize - 1)) - timePrev + 1;
237*e5436536SAndroid Build Coastguard Worker
238*e5436536SAndroid Build Coastguard Worker err = _interpolateDrcGain(gainInterpolationType, timePrev, duration, start,
239*e5436536SAndroid Build Coastguard Worker stop, stepsize, gainLinPrev, gainLin,
240*e5436536SAndroid Build Coastguard Worker slopeLinPrev, slopeLin, buffer);
241*e5436536SAndroid Build Coastguard Worker if (err) return err;
242*e5436536SAndroid Build Coastguard Worker
243*e5436536SAndroid Build Coastguard Worker timePrev = time;
244*e5436536SAndroid Build Coastguard Worker gainLinPrev = gainLin;
245*e5436536SAndroid Build Coastguard Worker }
246*e5436536SAndroid Build Coastguard Worker return err;
247*e5436536SAndroid Build Coastguard Worker }
248*e5436536SAndroid Build Coastguard Worker
249*e5436536SAndroid Build Coastguard Worker /* process DRC on time-domain signal */
250*e5436536SAndroid Build Coastguard Worker DRC_ERROR
processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec,const int activeDrcIndex,const int delaySamples,const int channelOffset,const int drcChannelOffset,const int numChannelsProcessed,const int timeDataChannelOffset,FIXP_DBL * deinterleavedAudio)251*e5436536SAndroid Build Coastguard Worker processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex,
252*e5436536SAndroid Build Coastguard Worker const int delaySamples, const int channelOffset,
253*e5436536SAndroid Build Coastguard Worker const int drcChannelOffset, const int numChannelsProcessed,
254*e5436536SAndroid Build Coastguard Worker const int timeDataChannelOffset, FIXP_DBL* deinterleavedAudio) {
255*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
256*e5436536SAndroid Build Coastguard Worker int c, b, i;
257*e5436536SAndroid Build Coastguard Worker ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]);
258*e5436536SAndroid Build Coastguard Worker DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers);
259*e5436536SAndroid Build Coastguard Worker int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx;
260*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer;
261*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER* pDummyLnb = &(pDrcGainBuffers->dummyLnb);
262*e5436536SAndroid Build Coastguard Worker int offset = 0;
263*e5436536SAndroid Build Coastguard Worker
264*e5436536SAndroid Build Coastguard Worker if (hGainDec->delayMode == DM_REGULAR_DELAY) {
265*e5436536SAndroid Build Coastguard Worker offset = hGainDec->frameSize;
266*e5436536SAndroid Build Coastguard Worker }
267*e5436536SAndroid Build Coastguard Worker
268*e5436536SAndroid Build Coastguard Worker if ((delaySamples + offset) >
269*e5436536SAndroid Build Coastguard Worker (NUM_LNB_FRAMES - 2) *
270*e5436536SAndroid Build Coastguard Worker hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES
271*e5436536SAndroid Build Coastguard Worker should be increased */
272*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
273*e5436536SAndroid Build Coastguard Worker
274*e5436536SAndroid Build Coastguard Worker err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset,
275*e5436536SAndroid Build Coastguard Worker numChannelsProcessed, lnbPointer);
276*e5436536SAndroid Build Coastguard Worker if (err) return err;
277*e5436536SAndroid Build Coastguard Worker
278*e5436536SAndroid Build Coastguard Worker deinterleavedAudio +=
279*e5436536SAndroid Build Coastguard Worker channelOffset * timeDataChannelOffset; /* apply channelOffset */
280*e5436536SAndroid Build Coastguard Worker
281*e5436536SAndroid Build Coastguard Worker /* signal processing loop */
282*e5436536SAndroid Build Coastguard Worker for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) {
283*e5436536SAndroid Build Coastguard Worker if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex)
284*e5436536SAndroid Build Coastguard Worker pDrcGainBuffers->channelGain[c][lnbPointer] = hGainDec->channelGain[c];
285*e5436536SAndroid Build Coastguard Worker
286*e5436536SAndroid Build Coastguard Worker b = 0;
287*e5436536SAndroid Build Coastguard Worker {
288*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER *pLnb, *pLnbPrevious;
289*e5436536SAndroid Build Coastguard Worker NODE_LIN nodePrevious;
290*e5436536SAndroid Build Coastguard Worker int lnbPointerDiff;
291*e5436536SAndroid Build Coastguard Worker FIXP_DBL channelGain;
292*e5436536SAndroid Build Coastguard Worker /* get pointer to oldest linearNodes */
293*e5436536SAndroid Build Coastguard Worker lnbIx = lnbPointer + 1 - NUM_LNB_FRAMES;
294*e5436536SAndroid Build Coastguard Worker while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES;
295*e5436536SAndroid Build Coastguard Worker
296*e5436536SAndroid Build Coastguard Worker if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex)
297*e5436536SAndroid Build Coastguard Worker channelGain = pDrcGainBuffers->channelGain[c][lnbIx];
298*e5436536SAndroid Build Coastguard Worker else
299*e5436536SAndroid Build Coastguard Worker channelGain = FL2FXCONST_DBL(1.0f / (float)(1 << 8));
300*e5436536SAndroid Build Coastguard Worker
301*e5436536SAndroid Build Coastguard Worker /* Loop over all node buffers in linearNodeBuffer.
302*e5436536SAndroid Build Coastguard Worker All nodes which are not relevant for the current frame are sorted out
303*e5436536SAndroid Build Coastguard Worker inside _processNodeSegments. */
304*e5436536SAndroid Build Coastguard Worker for (i = 0; i < NUM_LNB_FRAMES - 1; i++) {
305*e5436536SAndroid Build Coastguard Worker /* Prepare previous node */
306*e5436536SAndroid Build Coastguard Worker if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0)
307*e5436536SAndroid Build Coastguard Worker pLnbPrevious = &(
308*e5436536SAndroid Build Coastguard Worker pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]);
309*e5436536SAndroid Build Coastguard Worker else
310*e5436536SAndroid Build Coastguard Worker pLnbPrevious = pDummyLnb;
311*e5436536SAndroid Build Coastguard Worker nodePrevious =
312*e5436536SAndroid Build Coastguard Worker pLnbPrevious->linearNode[lnbIx][pLnbPrevious->nNodes[lnbIx] - 1];
313*e5436536SAndroid Build Coastguard Worker nodePrevious.time -= hGainDec->frameSize;
314*e5436536SAndroid Build Coastguard Worker if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8)))
315*e5436536SAndroid Build Coastguard Worker nodePrevious.gainLin = SATURATE_LEFT_SHIFT(
316*e5436536SAndroid Build Coastguard Worker fMultDiv2(nodePrevious.gainLin,
317*e5436536SAndroid Build Coastguard Worker pDrcGainBuffers->channelGain[c][lnbIx]),
318*e5436536SAndroid Build Coastguard Worker 9, DFRACT_BITS);
319*e5436536SAndroid Build Coastguard Worker
320*e5436536SAndroid Build Coastguard Worker /* Prepare current linearNodeBuffer instance */
321*e5436536SAndroid Build Coastguard Worker lnbIx++;
322*e5436536SAndroid Build Coastguard Worker if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0;
323*e5436536SAndroid Build Coastguard Worker
324*e5436536SAndroid Build Coastguard Worker /* if lnbIndexForChannel changes over time, use the old indices for
325*e5436536SAndroid Build Coastguard Worker * smooth transitions */
326*e5436536SAndroid Build Coastguard Worker if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0)
327*e5436536SAndroid Build Coastguard Worker pLnb = &(
328*e5436536SAndroid Build Coastguard Worker pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]);
329*e5436536SAndroid Build Coastguard Worker else /* lnbIndexForChannel = -1 means "no DRC processing", due to
330*e5436536SAndroid Build Coastguard Worker drcInstructionsIndex < 0, drcSetId < 0 or channel group < 0 */
331*e5436536SAndroid Build Coastguard Worker pLnb = pDummyLnb;
332*e5436536SAndroid Build Coastguard Worker
333*e5436536SAndroid Build Coastguard Worker if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex)
334*e5436536SAndroid Build Coastguard Worker channelGain = pDrcGainBuffers->channelGain[c][lnbIx];
335*e5436536SAndroid Build Coastguard Worker
336*e5436536SAndroid Build Coastguard Worker /* number of frames of offset with respect to lnbPointer */
337*e5436536SAndroid Build Coastguard Worker lnbPointerDiff = i - (NUM_LNB_FRAMES - 2);
338*e5436536SAndroid Build Coastguard Worker
339*e5436536SAndroid Build Coastguard Worker err = _processNodeSegments(
340*e5436536SAndroid Build Coastguard Worker hGainDec->frameSize, pLnb->gainInterpolationType,
341*e5436536SAndroid Build Coastguard Worker pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx],
342*e5436536SAndroid Build Coastguard Worker lnbPointerDiff * hGainDec->frameSize + delaySamples + offset, 1,
343*e5436536SAndroid Build Coastguard Worker nodePrevious, channelGain, deinterleavedAudio);
344*e5436536SAndroid Build Coastguard Worker if (err) return err;
345*e5436536SAndroid Build Coastguard Worker }
346*e5436536SAndroid Build Coastguard Worker deinterleavedAudio += timeDataChannelOffset; /* proceed to next channel */
347*e5436536SAndroid Build Coastguard Worker }
348*e5436536SAndroid Build Coastguard Worker }
349*e5436536SAndroid Build Coastguard Worker return DE_OK;
350*e5436536SAndroid Build Coastguard Worker }
351*e5436536SAndroid Build Coastguard Worker
352*e5436536SAndroid Build Coastguard Worker /* process DRC on subband-domain signal */
353*e5436536SAndroid Build Coastguard Worker DRC_ERROR
processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec,const int activeDrcIndex,const int delaySamples,const int channelOffset,const int drcChannelOffset,const int numChannelsProcessed,const int processSingleTimeslot,FIXP_DBL * deinterleavedAudioReal[],FIXP_DBL * deinterleavedAudioImag[])354*e5436536SAndroid Build Coastguard Worker processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex,
355*e5436536SAndroid Build Coastguard Worker const int delaySamples, const int channelOffset,
356*e5436536SAndroid Build Coastguard Worker const int drcChannelOffset, const int numChannelsProcessed,
357*e5436536SAndroid Build Coastguard Worker const int processSingleTimeslot,
358*e5436536SAndroid Build Coastguard Worker FIXP_DBL* deinterleavedAudioReal[],
359*e5436536SAndroid Build Coastguard Worker FIXP_DBL* deinterleavedAudioImag[]) {
360*e5436536SAndroid Build Coastguard Worker DRC_ERROR err = DE_OK;
361*e5436536SAndroid Build Coastguard Worker int b, c, g, m, m_start, m_stop, s, i;
362*e5436536SAndroid Build Coastguard Worker FIXP_DBL gainSb;
363*e5436536SAndroid Build Coastguard Worker DRC_INSTRUCTIONS_UNI_DRC* pInst = hGainDec->activeDrc[activeDrcIndex].pInst;
364*e5436536SAndroid Build Coastguard Worker DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers);
365*e5436536SAndroid Build Coastguard Worker ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]);
366*e5436536SAndroid Build Coastguard Worker int activeDrcOffset = pActiveDrc->activeDrcOffset;
367*e5436536SAndroid Build Coastguard Worker int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx;
368*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer;
369*e5436536SAndroid Build Coastguard Worker FIXP_DBL(*subbandGains)[4 * 1024 / 256] = hGainDec->subbandGains;
370*e5436536SAndroid Build Coastguard Worker FIXP_DBL* dummySubbandGains = hGainDec->dummySubbandGains;
371*e5436536SAndroid Build Coastguard Worker SUBBAND_DOMAIN_MODE subbandDomainMode = hGainDec->subbandDomainSupported;
372*e5436536SAndroid Build Coastguard Worker int signalIndex = 0;
373*e5436536SAndroid Build Coastguard Worker int frameSizeSb = 0;
374*e5436536SAndroid Build Coastguard Worker int nDecoderSubbands;
375*e5436536SAndroid Build Coastguard Worker SHORT L = 0; /* L: downsampling factor */
376*e5436536SAndroid Build Coastguard Worker int offset = 0;
377*e5436536SAndroid Build Coastguard Worker FIXP_DBL *audioReal = NULL, *audioImag = NULL;
378*e5436536SAndroid Build Coastguard Worker
379*e5436536SAndroid Build Coastguard Worker if (hGainDec->delayMode == DM_REGULAR_DELAY) {
380*e5436536SAndroid Build Coastguard Worker offset = hGainDec->frameSize;
381*e5436536SAndroid Build Coastguard Worker }
382*e5436536SAndroid Build Coastguard Worker
383*e5436536SAndroid Build Coastguard Worker if ((delaySamples + offset) >
384*e5436536SAndroid Build Coastguard Worker (NUM_LNB_FRAMES - 2) *
385*e5436536SAndroid Build Coastguard Worker hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES
386*e5436536SAndroid Build Coastguard Worker should be increased */
387*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
388*e5436536SAndroid Build Coastguard Worker
389*e5436536SAndroid Build Coastguard Worker switch (subbandDomainMode) {
390*e5436536SAndroid Build Coastguard Worker #if ((1024 / 256) >= (4096 / SUBBAND_DOWNSAMPLING_FACTOR_QMF64))
391*e5436536SAndroid Build Coastguard Worker case SDM_QMF64:
392*e5436536SAndroid Build Coastguard Worker nDecoderSubbands = SUBBAND_NUM_BANDS_QMF64;
393*e5436536SAndroid Build Coastguard Worker L = SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
394*e5436536SAndroid Build Coastguard Worker /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF64; */
395*e5436536SAndroid Build Coastguard Worker break;
396*e5436536SAndroid Build Coastguard Worker case SDM_QMF71:
397*e5436536SAndroid Build Coastguard Worker nDecoderSubbands = SUBBAND_NUM_BANDS_QMF71;
398*e5436536SAndroid Build Coastguard Worker L = SUBBAND_DOWNSAMPLING_FACTOR_QMF71;
399*e5436536SAndroid Build Coastguard Worker /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF71; */
400*e5436536SAndroid Build Coastguard Worker break;
401*e5436536SAndroid Build Coastguard Worker #else
402*e5436536SAndroid Build Coastguard Worker case SDM_QMF64:
403*e5436536SAndroid Build Coastguard Worker case SDM_QMF71:
404*e5436536SAndroid Build Coastguard Worker /* QMF domain processing is not supported. */
405*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
406*e5436536SAndroid Build Coastguard Worker #endif
407*e5436536SAndroid Build Coastguard Worker case SDM_STFT256:
408*e5436536SAndroid Build Coastguard Worker nDecoderSubbands = SUBBAND_NUM_BANDS_STFT256;
409*e5436536SAndroid Build Coastguard Worker L = SUBBAND_DOWNSAMPLING_FACTOR_STFT256;
410*e5436536SAndroid Build Coastguard Worker /* analysisDelay = SUBBAND_ANALYSIS_DELAY_STFT256; */
411*e5436536SAndroid Build Coastguard Worker break;
412*e5436536SAndroid Build Coastguard Worker default:
413*e5436536SAndroid Build Coastguard Worker return DE_NOT_OK;
414*e5436536SAndroid Build Coastguard Worker }
415*e5436536SAndroid Build Coastguard Worker
416*e5436536SAndroid Build Coastguard Worker /* frameSizeSb = hGainDec->frameSize/L; */ /* L is a power of 2 */
417*e5436536SAndroid Build Coastguard Worker frameSizeSb =
418*e5436536SAndroid Build Coastguard Worker hGainDec->frameSize >> (15 - fixnormz_S(L)); /* timeslots per frame */
419*e5436536SAndroid Build Coastguard Worker
420*e5436536SAndroid Build Coastguard Worker if ((processSingleTimeslot < 0) || (processSingleTimeslot >= frameSizeSb)) {
421*e5436536SAndroid Build Coastguard Worker m_start = 0;
422*e5436536SAndroid Build Coastguard Worker m_stop = frameSizeSb;
423*e5436536SAndroid Build Coastguard Worker } else {
424*e5436536SAndroid Build Coastguard Worker m_start = processSingleTimeslot;
425*e5436536SAndroid Build Coastguard Worker m_stop = m_start + 1;
426*e5436536SAndroid Build Coastguard Worker }
427*e5436536SAndroid Build Coastguard Worker
428*e5436536SAndroid Build Coastguard Worker err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset,
429*e5436536SAndroid Build Coastguard Worker numChannelsProcessed, lnbPointer);
430*e5436536SAndroid Build Coastguard Worker if (err) return err;
431*e5436536SAndroid Build Coastguard Worker
432*e5436536SAndroid Build Coastguard Worker if (!pActiveDrc->subbandGainsReady) /* only for the first time per frame that
433*e5436536SAndroid Build Coastguard Worker processDrcSubband is called */
434*e5436536SAndroid Build Coastguard Worker {
435*e5436536SAndroid Build Coastguard Worker /* write subbandGains */
436*e5436536SAndroid Build Coastguard Worker for (g = 0; g < pInst->nDrcChannelGroups; g++) {
437*e5436536SAndroid Build Coastguard Worker b = 0;
438*e5436536SAndroid Build Coastguard Worker {
439*e5436536SAndroid Build Coastguard Worker LINEAR_NODE_BUFFER* pLnb =
440*e5436536SAndroid Build Coastguard Worker &(pLinearNodeBuffer[activeDrcOffset +
441*e5436536SAndroid Build Coastguard Worker pActiveDrc->gainElementForGroup[g] + b]);
442*e5436536SAndroid Build Coastguard Worker NODE_LIN nodePrevious;
443*e5436536SAndroid Build Coastguard Worker int lnbPointerDiff;
444*e5436536SAndroid Build Coastguard Worker
445*e5436536SAndroid Build Coastguard Worker for (m = 0; m < frameSizeSb; m++) {
446*e5436536SAndroid Build Coastguard Worker subbandGains[activeDrcOffset + g][b * frameSizeSb + m] =
447*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(1.0f / (float)(1 << 7));
448*e5436536SAndroid Build Coastguard Worker }
449*e5436536SAndroid Build Coastguard Worker
450*e5436536SAndroid Build Coastguard Worker lnbIx = lnbPointer - (NUM_LNB_FRAMES - 1);
451*e5436536SAndroid Build Coastguard Worker while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES;
452*e5436536SAndroid Build Coastguard Worker
453*e5436536SAndroid Build Coastguard Worker /* Loop over all node buffers in linearNodeBuffer.
454*e5436536SAndroid Build Coastguard Worker All nodes which are not relevant for the current frame are sorted out
455*e5436536SAndroid Build Coastguard Worker inside _processNodeSegments. */
456*e5436536SAndroid Build Coastguard Worker for (i = 0; i < NUM_LNB_FRAMES - 1; i++) {
457*e5436536SAndroid Build Coastguard Worker /* Prepare previous node */
458*e5436536SAndroid Build Coastguard Worker nodePrevious = pLnb->linearNode[lnbIx][pLnb->nNodes[lnbIx] - 1];
459*e5436536SAndroid Build Coastguard Worker nodePrevious.time -= hGainDec->frameSize;
460*e5436536SAndroid Build Coastguard Worker
461*e5436536SAndroid Build Coastguard Worker lnbIx++;
462*e5436536SAndroid Build Coastguard Worker if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0;
463*e5436536SAndroid Build Coastguard Worker
464*e5436536SAndroid Build Coastguard Worker /* number of frames of offset with respect to lnbPointer */
465*e5436536SAndroid Build Coastguard Worker lnbPointerDiff = i - (NUM_LNB_FRAMES - 2);
466*e5436536SAndroid Build Coastguard Worker
467*e5436536SAndroid Build Coastguard Worker err = _processNodeSegments(
468*e5436536SAndroid Build Coastguard Worker hGainDec->frameSize, pLnb->gainInterpolationType,
469*e5436536SAndroid Build Coastguard Worker pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx],
470*e5436536SAndroid Build Coastguard Worker lnbPointerDiff * hGainDec->frameSize + delaySamples + offset -
471*e5436536SAndroid Build Coastguard Worker (L - 1) / 2,
472*e5436536SAndroid Build Coastguard Worker L, nodePrevious, FL2FXCONST_DBL(1.0f / (float)(1 << 8)),
473*e5436536SAndroid Build Coastguard Worker &(subbandGains[activeDrcOffset + g][b * frameSizeSb]));
474*e5436536SAndroid Build Coastguard Worker if (err) return err;
475*e5436536SAndroid Build Coastguard Worker }
476*e5436536SAndroid Build Coastguard Worker }
477*e5436536SAndroid Build Coastguard Worker }
478*e5436536SAndroid Build Coastguard Worker pActiveDrc->subbandGainsReady = 1;
479*e5436536SAndroid Build Coastguard Worker }
480*e5436536SAndroid Build Coastguard Worker
481*e5436536SAndroid Build Coastguard Worker for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) {
482*e5436536SAndroid Build Coastguard Worker FIXP_DBL* thisSubbandGainsBuffer;
483*e5436536SAndroid Build Coastguard Worker if (pInst->drcSetId > 0)
484*e5436536SAndroid Build Coastguard Worker g = pActiveDrc->channelGroupForChannel[c + drcChannelOffset];
485*e5436536SAndroid Build Coastguard Worker else
486*e5436536SAndroid Build Coastguard Worker g = -1;
487*e5436536SAndroid Build Coastguard Worker
488*e5436536SAndroid Build Coastguard Worker audioReal = deinterleavedAudioReal[signalIndex];
489*e5436536SAndroid Build Coastguard Worker if (subbandDomainMode != SDM_STFT256) {
490*e5436536SAndroid Build Coastguard Worker audioImag = deinterleavedAudioImag[signalIndex];
491*e5436536SAndroid Build Coastguard Worker }
492*e5436536SAndroid Build Coastguard Worker
493*e5436536SAndroid Build Coastguard Worker if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) {
494*e5436536SAndroid Build Coastguard Worker thisSubbandGainsBuffer = subbandGains[activeDrcOffset + g];
495*e5436536SAndroid Build Coastguard Worker } else {
496*e5436536SAndroid Build Coastguard Worker thisSubbandGainsBuffer = dummySubbandGains;
497*e5436536SAndroid Build Coastguard Worker }
498*e5436536SAndroid Build Coastguard Worker
499*e5436536SAndroid Build Coastguard Worker for (m = m_start; m < m_stop; m++) {
500*e5436536SAndroid Build Coastguard Worker INT n_min = 8;
501*e5436536SAndroid Build Coastguard Worker { /* single-band DRC */
502*e5436536SAndroid Build Coastguard Worker gainSb = thisSubbandGainsBuffer[m];
503*e5436536SAndroid Build Coastguard Worker if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex)
504*e5436536SAndroid Build Coastguard Worker gainSb = SATURATE_LEFT_SHIFT(
505*e5436536SAndroid Build Coastguard Worker fMultDiv2(gainSb, hGainDec->channelGain[c]), 9, DFRACT_BITS);
506*e5436536SAndroid Build Coastguard Worker /* normalize gainSb for keeping signal precision */
507*e5436536SAndroid Build Coastguard Worker n_min = fMin(CntLeadingZeros(gainSb) - 1, n_min);
508*e5436536SAndroid Build Coastguard Worker gainSb <<= n_min;
509*e5436536SAndroid Build Coastguard Worker n_min = 8 - n_min;
510*e5436536SAndroid Build Coastguard Worker if (subbandDomainMode ==
511*e5436536SAndroid Build Coastguard Worker SDM_STFT256) { /* For STFT filterbank, real and imaginary parts are
512*e5436536SAndroid Build Coastguard Worker interleaved. */
513*e5436536SAndroid Build Coastguard Worker for (s = 0; s < nDecoderSubbands; s++) {
514*e5436536SAndroid Build Coastguard Worker *audioReal = fMultDiv2(*audioReal, gainSb) << n_min;
515*e5436536SAndroid Build Coastguard Worker audioReal++;
516*e5436536SAndroid Build Coastguard Worker *audioReal = fMultDiv2(*audioReal, gainSb) << n_min;
517*e5436536SAndroid Build Coastguard Worker audioReal++;
518*e5436536SAndroid Build Coastguard Worker }
519*e5436536SAndroid Build Coastguard Worker } else {
520*e5436536SAndroid Build Coastguard Worker for (s = 0; s < nDecoderSubbands; s++) {
521*e5436536SAndroid Build Coastguard Worker *audioReal = fMultDiv2(*audioReal, gainSb) << n_min;
522*e5436536SAndroid Build Coastguard Worker audioReal++;
523*e5436536SAndroid Build Coastguard Worker *audioImag = fMultDiv2(*audioImag, gainSb) << n_min;
524*e5436536SAndroid Build Coastguard Worker audioImag++;
525*e5436536SAndroid Build Coastguard Worker }
526*e5436536SAndroid Build Coastguard Worker }
527*e5436536SAndroid Build Coastguard Worker }
528*e5436536SAndroid Build Coastguard Worker }
529*e5436536SAndroid Build Coastguard Worker signalIndex++;
530*e5436536SAndroid Build Coastguard Worker }
531*e5436536SAndroid Build Coastguard Worker return DE_OK;
532*e5436536SAndroid Build Coastguard Worker }
533