xref: /aosp_15_r20/external/aac/libSACdec/src/sac_process.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 - 2021 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 surround 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: SAC Processing
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker /* data structures and interfaces for spatial audio reference software */
104*e5436536SAndroid Build Coastguard Worker #include "sac_process.h"
105*e5436536SAndroid Build Coastguard Worker 
106*e5436536SAndroid Build Coastguard Worker #include "sac_bitdec.h"
107*e5436536SAndroid Build Coastguard Worker #include "sac_calcM1andM2.h"
108*e5436536SAndroid Build Coastguard Worker #include "sac_smoothing.h"
109*e5436536SAndroid Build Coastguard Worker #include "sac_rom.h"
110*e5436536SAndroid Build Coastguard Worker 
111*e5436536SAndroid Build Coastguard Worker #include "sac_dec_errorcodes.h"
112*e5436536SAndroid Build Coastguard Worker 
113*e5436536SAndroid Build Coastguard Worker #include "FDK_trigFcts.h"
114*e5436536SAndroid Build Coastguard Worker #include "FDK_decorrelate.h"
115*e5436536SAndroid Build Coastguard Worker 
116*e5436536SAndroid Build Coastguard Worker #define SAC_DEC_APPLY_M2_SCALE(spec, s) ((spec) >> (-(s)))
117*e5436536SAndroid Build Coastguard Worker 
118*e5436536SAndroid Build Coastguard Worker /**
119*e5436536SAndroid Build Coastguard Worker  * \brief  Linear interpolation between two parameter values.
120*e5436536SAndroid Build Coastguard Worker  *         a*alpha + b*(1-alpha)
121*e5436536SAndroid Build Coastguard Worker  *       = a*alpha + b - b*alpha
122*e5436536SAndroid Build Coastguard Worker  *
123*e5436536SAndroid Build Coastguard Worker  * \param alpha               Weighting factor.
124*e5436536SAndroid Build Coastguard Worker  * \param a                   Parameter a.
125*e5436536SAndroid Build Coastguard Worker  * \param b                   Parameter b.
126*e5436536SAndroid Build Coastguard Worker  *
127*e5436536SAndroid Build Coastguard Worker  * \return Interpolated parameter value.
128*e5436536SAndroid Build Coastguard Worker  */
interpolateParameter(const FIXP_SGL alpha,const FIXP_DBL a,const FIXP_DBL b)129*e5436536SAndroid Build Coastguard Worker FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a,
130*e5436536SAndroid Build Coastguard Worker                                          const FIXP_DBL b) {
131*e5436536SAndroid Build Coastguard Worker   return (b - fMult(alpha, b) + fMult(alpha, a));
132*e5436536SAndroid Build Coastguard Worker }
133*e5436536SAndroid Build Coastguard Worker 
134*e5436536SAndroid Build Coastguard Worker /**
135*e5436536SAndroid Build Coastguard Worker  * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices.
136*e5436536SAndroid Build Coastguard Worker  * \param self Spatial decoder handle.
137*e5436536SAndroid Build Coastguard Worker  * \param ch MPEG Surround channel index.
138*e5436536SAndroid Build Coastguard Worker  * \return MPEG 4 PCE style channel index, corresponding to the given MPEG
139*e5436536SAndroid Build Coastguard Worker  * Surround channel index.
140*e5436536SAndroid Build Coastguard Worker  */
mapChannel(spatialDec * self,UINT ch)141*e5436536SAndroid Build Coastguard Worker static UINT mapChannel(spatialDec *self, UINT ch) {
142*e5436536SAndroid Build Coastguard Worker   static const UCHAR chanelIdx[][8] = {
143*e5436536SAndroid Build Coastguard Worker       {0, 1, 2, 3, 4, 5, 6, 7}, /*  binaural, TREE_212, arbitrary tree */
144*e5436536SAndroid Build Coastguard Worker   };
145*e5436536SAndroid Build Coastguard Worker 
146*e5436536SAndroid Build Coastguard Worker   int idx = 0;
147*e5436536SAndroid Build Coastguard Worker 
148*e5436536SAndroid Build Coastguard Worker   return (chanelIdx[idx][ch]);
149*e5436536SAndroid Build Coastguard Worker }
150*e5436536SAndroid Build Coastguard Worker 
getChGain(spatialDec * self,UINT ch,INT * scale)151*e5436536SAndroid Build Coastguard Worker FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) {
152*e5436536SAndroid Build Coastguard Worker   /* init no gain modifier */
153*e5436536SAndroid Build Coastguard Worker   FIXP_DBL gain = 0x80000000;
154*e5436536SAndroid Build Coastguard Worker   *scale = 0;
155*e5436536SAndroid Build Coastguard Worker 
156*e5436536SAndroid Build Coastguard Worker   if ((!isTwoChMode(self->upmixType)) &&
157*e5436536SAndroid Build Coastguard Worker       (self->upmixType != UPMIXTYPE_BYPASS)) {
158*e5436536SAndroid Build Coastguard Worker     if ((ch == 0) || (ch == 1) || (ch == 2)) {
159*e5436536SAndroid Build Coastguard Worker       /* no modifier */
160*e5436536SAndroid Build Coastguard Worker     }
161*e5436536SAndroid Build Coastguard Worker   }
162*e5436536SAndroid Build Coastguard Worker 
163*e5436536SAndroid Build Coastguard Worker   return gain;
164*e5436536SAndroid Build Coastguard Worker }
165*e5436536SAndroid Build Coastguard Worker 
SpatialDecQMFAnalysis(spatialDec * self,const PCM_MPS * inData,const INT ts,const INT bypassMode,FIXP_DBL ** qmfReal,FIXP_DBL ** qmfImag,const int numInputChannels)166*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData,
167*e5436536SAndroid Build Coastguard Worker                                    const INT ts, const INT bypassMode,
168*e5436536SAndroid Build Coastguard Worker                                    FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
169*e5436536SAndroid Build Coastguard Worker                                    const int numInputChannels) {
170*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
171*e5436536SAndroid Build Coastguard Worker   int ch, offset;
172*e5436536SAndroid Build Coastguard Worker 
173*e5436536SAndroid Build Coastguard Worker   offset = self->pQmfDomain->globalConf.nBandsSynthesis *
174*e5436536SAndroid Build Coastguard Worker            self->pQmfDomain->globalConf.nQmfTimeSlots;
175*e5436536SAndroid Build Coastguard Worker 
176*e5436536SAndroid Build Coastguard Worker   {
177*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < numInputChannels; ch++) {
178*e5436536SAndroid Build Coastguard Worker       const PCM_MPS *inSamples =
179*e5436536SAndroid Build Coastguard Worker           &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis];
180*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */
181*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pQmfImagAnalysis = qmfImag[ch];
182*e5436536SAndroid Build Coastguard Worker 
183*e5436536SAndroid Build Coastguard Worker       CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb,
184*e5436536SAndroid Build Coastguard Worker                                 inSamples + (ch * offset), pQmfRealAnalysis,
185*e5436536SAndroid Build Coastguard Worker                                 pQmfImagAnalysis);
186*e5436536SAndroid Build Coastguard Worker 
187*e5436536SAndroid Build Coastguard Worker       if (!isTwoChMode(self->upmixType) && !bypassMode) {
188*e5436536SAndroid Build Coastguard Worker         int i;
189*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < self->qmfBands; i++) {
190*e5436536SAndroid Build Coastguard Worker           qmfReal[ch][i] = fMult(
191*e5436536SAndroid Build Coastguard Worker               scaleValueSaturate(qmfReal[ch][i], self->sacInDataHeadroom - (1)),
192*e5436536SAndroid Build Coastguard Worker               self->clipProtectGain__FDK);
193*e5436536SAndroid Build Coastguard Worker           qmfImag[ch][i] = fMult(
194*e5436536SAndroid Build Coastguard Worker               scaleValueSaturate(qmfImag[ch][i], self->sacInDataHeadroom - (1)),
195*e5436536SAndroid Build Coastguard Worker               self->clipProtectGain__FDK);
196*e5436536SAndroid Build Coastguard Worker         }
197*e5436536SAndroid Build Coastguard Worker       }
198*e5436536SAndroid Build Coastguard Worker     }
199*e5436536SAndroid Build Coastguard Worker   }
200*e5436536SAndroid Build Coastguard Worker 
201*e5436536SAndroid Build Coastguard Worker   self->qmfInputDelayBufPos =
202*e5436536SAndroid Build Coastguard Worker       (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
203*e5436536SAndroid Build Coastguard Worker 
204*e5436536SAndroid Build Coastguard Worker   return err;
205*e5436536SAndroid Build Coastguard Worker }
206*e5436536SAndroid Build Coastguard Worker 
SpatialDecFeedQMF(spatialDec * self,FIXP_DBL ** qmfInDataReal,FIXP_DBL ** qmfInDataImag,const INT ts,const INT bypassMode,FIXP_DBL ** qmfReal__FDK,FIXP_DBL ** qmfImag__FDK,const INT numInputChannels)207*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal,
208*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **qmfInDataImag, const INT ts,
209*e5436536SAndroid Build Coastguard Worker                                const INT bypassMode, FIXP_DBL **qmfReal__FDK,
210*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **qmfImag__FDK,
211*e5436536SAndroid Build Coastguard Worker                                const INT numInputChannels) {
212*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
213*e5436536SAndroid Build Coastguard Worker   int ch;
214*e5436536SAndroid Build Coastguard Worker 
215*e5436536SAndroid Build Coastguard Worker   {
216*e5436536SAndroid Build Coastguard Worker     for (ch = 0; ch < numInputChannels; ch++) {
217*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pQmfRealAnalysis =
218*e5436536SAndroid Build Coastguard Worker           qmfReal__FDK[ch]; /* no delay in blind mode */
219*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch];
220*e5436536SAndroid Build Coastguard Worker 
221*e5436536SAndroid Build Coastguard Worker       /* Write Input data to pQmfRealAnalysis. */
222*e5436536SAndroid Build Coastguard Worker       if (self->bShareDelayWithSBR) {
223*e5436536SAndroid Build Coastguard Worker         FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch],
224*e5436536SAndroid Build Coastguard Worker                               ts + HYBRID_FILTER_DELAY, 0,
225*e5436536SAndroid Build Coastguard Worker                               MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis,
226*e5436536SAndroid Build Coastguard Worker                               pQmfImagAnalysis, 15 + (1));
227*e5436536SAndroid Build Coastguard Worker         FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts,
228*e5436536SAndroid Build Coastguard Worker                               MAX_QMF_BANDS_TO_HYBRID, self->qmfBands,
229*e5436536SAndroid Build Coastguard Worker                               pQmfRealAnalysis, pQmfImagAnalysis, 15 + (1));
230*e5436536SAndroid Build Coastguard Worker       } else {
231*e5436536SAndroid Build Coastguard Worker         FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0,
232*e5436536SAndroid Build Coastguard Worker                               self->qmfBands, pQmfRealAnalysis,
233*e5436536SAndroid Build Coastguard Worker                               pQmfImagAnalysis, 15 + (1));
234*e5436536SAndroid Build Coastguard Worker       }
235*e5436536SAndroid Build Coastguard Worker       if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) {
236*e5436536SAndroid Build Coastguard Worker         /* Is currently also needed in case we dont have any overlap. We need to
237*e5436536SAndroid Build Coastguard Worker          * save lb_scale to ov_lb_scale */
238*e5436536SAndroid Build Coastguard Worker         FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0);
239*e5436536SAndroid Build Coastguard Worker       }
240*e5436536SAndroid Build Coastguard Worker 
241*e5436536SAndroid Build Coastguard Worker       /* Apply clip protection to output. */
242*e5436536SAndroid Build Coastguard Worker       if (!isTwoChMode(self->upmixType) && !bypassMode) {
243*e5436536SAndroid Build Coastguard Worker         int i;
244*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < self->qmfBands; i++) {
245*e5436536SAndroid Build Coastguard Worker           qmfReal__FDK[ch][i] =
246*e5436536SAndroid Build Coastguard Worker               fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK);
247*e5436536SAndroid Build Coastguard Worker           qmfImag__FDK[ch][i] =
248*e5436536SAndroid Build Coastguard Worker               fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK);
249*e5436536SAndroid Build Coastguard Worker         }
250*e5436536SAndroid Build Coastguard Worker       }
251*e5436536SAndroid Build Coastguard Worker 
252*e5436536SAndroid Build Coastguard Worker     } /* End of loop over numInputChannels */
253*e5436536SAndroid Build Coastguard Worker   }
254*e5436536SAndroid Build Coastguard Worker 
255*e5436536SAndroid Build Coastguard Worker   self->qmfInputDelayBufPos =
256*e5436536SAndroid Build Coastguard Worker       (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay;
257*e5436536SAndroid Build Coastguard Worker 
258*e5436536SAndroid Build Coastguard Worker   return err;
259*e5436536SAndroid Build Coastguard Worker }
260*e5436536SAndroid Build Coastguard Worker 
261*e5436536SAndroid Build Coastguard Worker /*******************************************************************************
262*e5436536SAndroid Build Coastguard Worker  Functionname: SpatialDecHybridAnalysis
263*e5436536SAndroid Build Coastguard Worker  *******************************************************************************
264*e5436536SAndroid Build Coastguard Worker 
265*e5436536SAndroid Build Coastguard Worker  Description:
266*e5436536SAndroid Build Coastguard Worker 
267*e5436536SAndroid Build Coastguard Worker  Arguments:
268*e5436536SAndroid Build Coastguard Worker 
269*e5436536SAndroid Build Coastguard Worker  Input:
270*e5436536SAndroid Build Coastguard Worker   float** pointers[4] leftReal, leftIm, rightReal, rightIm
271*e5436536SAndroid Build Coastguard Worker 
272*e5436536SAndroid Build Coastguard Worker  Output:
273*e5436536SAndroid Build Coastguard Worker   float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
274*e5436536SAndroid Build Coastguard Worker   float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS];
275*e5436536SAndroid Build Coastguard Worker 
276*e5436536SAndroid Build Coastguard Worker   float
277*e5436536SAndroid Build Coastguard Worker self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float
278*e5436536SAndroid Build Coastguard Worker self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS];
279*e5436536SAndroid Build Coastguard Worker 
280*e5436536SAndroid Build Coastguard Worker 
281*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
SpatialDecHybridAnalysis(spatialDec * self,FIXP_DBL ** qmfInputReal,FIXP_DBL ** qmfInputImag,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,const INT ts,const INT numInputChannels)282*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal,
283*e5436536SAndroid Build Coastguard Worker                                       FIXP_DBL **qmfInputImag,
284*e5436536SAndroid Build Coastguard Worker                                       FIXP_DBL **hybOutputReal,
285*e5436536SAndroid Build Coastguard Worker                                       FIXP_DBL **hybOutputImag, const INT ts,
286*e5436536SAndroid Build Coastguard Worker                                       const INT numInputChannels) {
287*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
288*e5436536SAndroid Build Coastguard Worker   int ch;
289*e5436536SAndroid Build Coastguard Worker 
290*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < numInputChannels;
291*e5436536SAndroid Build Coastguard Worker        ch++) /* hybrid filtering for down-mix signals */
292*e5436536SAndroid Build Coastguard Worker   {
293*e5436536SAndroid Build Coastguard Worker     if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
294*e5436536SAndroid Build Coastguard Worker       int k;
295*e5436536SAndroid Build Coastguard Worker       /* No hybrid filtering. Just copy the QMF data. */
296*e5436536SAndroid Build Coastguard Worker       for (k = 0; k < self->hybridBands; k += 1) {
297*e5436536SAndroid Build Coastguard Worker         hybOutputReal[ch][k] = qmfInputReal[ch][k];
298*e5436536SAndroid Build Coastguard Worker         hybOutputImag[ch][k] = qmfInputImag[ch][k];
299*e5436536SAndroid Build Coastguard Worker       }
300*e5436536SAndroid Build Coastguard Worker     } else {
301*e5436536SAndroid Build Coastguard Worker       self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR;
302*e5436536SAndroid Build Coastguard Worker 
303*e5436536SAndroid Build Coastguard Worker       if (self->stereoConfigIndex == 3)
304*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0);
305*e5436536SAndroid Build Coastguard Worker       FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch],
306*e5436536SAndroid Build Coastguard Worker                              qmfInputImag[ch], hybOutputReal[ch],
307*e5436536SAndroid Build Coastguard Worker                              hybOutputImag[ch]);
308*e5436536SAndroid Build Coastguard Worker     }
309*e5436536SAndroid Build Coastguard Worker   }
310*e5436536SAndroid Build Coastguard Worker 
311*e5436536SAndroid Build Coastguard Worker   if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) &&
312*e5436536SAndroid Build Coastguard Worker       self->residualCoding) {
313*e5436536SAndroid Build Coastguard Worker     self->hybridAnalysis[numInputChannels].hfMode = 0;
314*e5436536SAndroid Build Coastguard Worker     FDKhybridAnalysisApply(
315*e5436536SAndroid Build Coastguard Worker         &self->hybridAnalysis[numInputChannels],
316*e5436536SAndroid Build Coastguard Worker         self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0],
317*e5436536SAndroid Build Coastguard Worker         self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]);
318*e5436536SAndroid Build Coastguard Worker   }
319*e5436536SAndroid Build Coastguard Worker 
320*e5436536SAndroid Build Coastguard Worker   return err;
321*e5436536SAndroid Build Coastguard Worker }
322*e5436536SAndroid Build Coastguard Worker 
SpatialDecCreateX(spatialDec * self,FIXP_DBL ** hybInputReal,FIXP_DBL ** hybInputImag,FIXP_DBL ** pxReal,FIXP_DBL ** pxImag)323*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal,
324*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **hybInputImag, FIXP_DBL **pxReal,
325*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **pxImag) {
326*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
327*e5436536SAndroid Build Coastguard Worker   int row;
328*e5436536SAndroid Build Coastguard Worker 
329*e5436536SAndroid Build Coastguard Worker   /* Creating wDry */
330*e5436536SAndroid Build Coastguard Worker   for (row = 0; row < self->numInputChannels; row++) {
331*e5436536SAndroid Build Coastguard Worker     /* pointer to direct signals */
332*e5436536SAndroid Build Coastguard Worker     pxReal[row] = hybInputReal[row];
333*e5436536SAndroid Build Coastguard Worker     pxImag[row] = hybInputImag[row];
334*e5436536SAndroid Build Coastguard Worker   }
335*e5436536SAndroid Build Coastguard Worker 
336*e5436536SAndroid Build Coastguard Worker   return err;
337*e5436536SAndroid Build Coastguard Worker }
338*e5436536SAndroid Build Coastguard Worker 
M2ParamToKernelMult(FIXP_SGL * RESTRICT pKernel,FIXP_DBL * RESTRICT Mparam,FIXP_DBL * RESTRICT MparamPrev,int * RESTRICT pWidth,FIXP_SGL alpha__FDK,int nBands)339*e5436536SAndroid Build Coastguard Worker static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel,
340*e5436536SAndroid Build Coastguard Worker                                 FIXP_DBL *RESTRICT Mparam,
341*e5436536SAndroid Build Coastguard Worker                                 FIXP_DBL *RESTRICT MparamPrev,
342*e5436536SAndroid Build Coastguard Worker                                 int *RESTRICT pWidth, FIXP_SGL alpha__FDK,
343*e5436536SAndroid Build Coastguard Worker                                 int nBands) {
344*e5436536SAndroid Build Coastguard Worker   int pb;
345*e5436536SAndroid Build Coastguard Worker 
346*e5436536SAndroid Build Coastguard Worker   for (pb = 0; pb < nBands; pb++) {
347*e5436536SAndroid Build Coastguard Worker     FIXP_SGL tmp = FX_DBL2FX_SGL(
348*e5436536SAndroid Build Coastguard Worker         interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb]));
349*e5436536SAndroid Build Coastguard Worker 
350*e5436536SAndroid Build Coastguard Worker     int i = pWidth[pb];
351*e5436536SAndroid Build Coastguard Worker     if (i & 1) *pKernel++ = tmp;
352*e5436536SAndroid Build Coastguard Worker     if (i & 2) {
353*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
354*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
355*e5436536SAndroid Build Coastguard Worker     }
356*e5436536SAndroid Build Coastguard Worker     for (i >>= 2; i--;) {
357*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
358*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
359*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
360*e5436536SAndroid Build Coastguard Worker       *pKernel++ = tmp;
361*e5436536SAndroid Build Coastguard Worker     }
362*e5436536SAndroid Build Coastguard Worker   }
363*e5436536SAndroid Build Coastguard Worker }
364*e5436536SAndroid Build Coastguard Worker 
SpatialDecApplyM1_CreateW_Mode212(spatialDec * self,const SPATIAL_BS_FRAME * frame,FIXP_DBL ** xReal,FIXP_DBL ** xImag,FIXP_DBL ** vReal,FIXP_DBL ** vImag)365*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212(
366*e5436536SAndroid Build Coastguard Worker     spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal,
367*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) {
368*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
369*e5436536SAndroid Build Coastguard Worker   int res;
370*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *decorrInReal = vReal[0];
371*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *decorrInImag = vImag[0];
372*e5436536SAndroid Build Coastguard Worker 
373*e5436536SAndroid Build Coastguard Worker   /* M1 does not do anything in 212 mode, so use simplified processing */
374*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(self->numVChannels == 2);
375*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(self->numDirektSignals == 1);
376*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(self->numDecorSignals == 1);
377*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL));
378*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL));
379*e5436536SAndroid Build Coastguard Worker 
380*e5436536SAndroid Build Coastguard Worker   if (isTsdActive(frame->TsdData)) {
381*e5436536SAndroid Build Coastguard Worker     /* Generate v_{x,nonTr} as input for allpass based decorrelator */
382*e5436536SAndroid Build Coastguard Worker     TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0],
383*e5436536SAndroid Build Coastguard Worker                      vImag[0], vReal[1], vImag[1], &decorrInReal,
384*e5436536SAndroid Build Coastguard Worker                      &decorrInImag);
385*e5436536SAndroid Build Coastguard Worker   }
386*e5436536SAndroid Build Coastguard Worker   /* - Decorrelate */
387*e5436536SAndroid Build Coastguard Worker   res = SpatialDecGetResidualIndex(self, 1);
388*e5436536SAndroid Build Coastguard Worker   if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag,
389*e5436536SAndroid Build Coastguard Worker                           vReal[1], vImag[1],
390*e5436536SAndroid Build Coastguard Worker                           self->param2hyb[self->residualBands[res]])) {
391*e5436536SAndroid Build Coastguard Worker     return MPS_NOTOK;
392*e5436536SAndroid Build Coastguard Worker   }
393*e5436536SAndroid Build Coastguard Worker   if (isTsdActive(frame->TsdData)) {
394*e5436536SAndroid Build Coastguard Worker     /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based
395*e5436536SAndroid Build Coastguard Worker      * decorrelator output */
396*e5436536SAndroid Build Coastguard Worker     TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs,
397*e5436536SAndroid Build Coastguard Worker              vReal[0], /* input: v_x */
398*e5436536SAndroid Build Coastguard Worker              vImag[0],
399*e5436536SAndroid Build Coastguard Worker              vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */
400*e5436536SAndroid Build Coastguard Worker              vImag[1]);
401*e5436536SAndroid Build Coastguard Worker   }
402*e5436536SAndroid Build Coastguard Worker 
403*e5436536SAndroid Build Coastguard Worker   /* Write residual signal in approriate parameter bands */
404*e5436536SAndroid Build Coastguard Worker   if (self->residualBands[res] > 0) {
405*e5436536SAndroid Build Coastguard Worker     int stopBand = self->param2hyb[self->residualBands[res]];
406*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res],
407*e5436536SAndroid Build Coastguard Worker               fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
408*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res],
409*e5436536SAndroid Build Coastguard Worker               fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL));
410*e5436536SAndroid Build Coastguard Worker   } /* (self->residualBands[res]>0) */
411*e5436536SAndroid Build Coastguard Worker 
412*e5436536SAndroid Build Coastguard Worker   return err;
413*e5436536SAndroid Build Coastguard Worker }
414*e5436536SAndroid Build Coastguard Worker 
SpatialDecApplyM2_Mode212(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry)415*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps,
416*e5436536SAndroid Build Coastguard Worker                                        const FIXP_SGL alpha, FIXP_DBL **wReal,
417*e5436536SAndroid Build Coastguard Worker                                        FIXP_DBL **wImag,
418*e5436536SAndroid Build Coastguard Worker                                        FIXP_DBL **hybOutputRealDry,
419*e5436536SAndroid Build Coastguard Worker                                        FIXP_DBL **hybOutputImagDry) {
420*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
421*e5436536SAndroid Build Coastguard Worker   INT row;
422*e5436536SAndroid Build Coastguard Worker 
423*e5436536SAndroid Build Coastguard Worker   INT *pWidth = self->kernels_width;
424*e5436536SAndroid Build Coastguard Worker   /* for stereoConfigIndex == 3 case hybridBands is < 71 */
425*e5436536SAndroid Build Coastguard Worker   INT pb_max = self->kernels[self->hybridBands - 1] + 1;
426*e5436536SAndroid Build Coastguard Worker   INT max_row = self->numOutputChannels;
427*e5436536SAndroid Build Coastguard Worker 
428*e5436536SAndroid Build Coastguard Worker   INT M2_exp = 0;
429*e5436536SAndroid Build Coastguard Worker   if (self->residualCoding) M2_exp = 3;
430*e5436536SAndroid Build Coastguard Worker 
431*e5436536SAndroid Build Coastguard Worker   for (row = 0; row < max_row; row++)  // 2 times
432*e5436536SAndroid Build Coastguard Worker   {
433*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0];
434*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1];
435*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0];
436*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1];
437*e5436536SAndroid Build Coastguard Worker 
438*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
439*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
440*e5436536SAndroid Build Coastguard Worker 
441*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWReal0 = wReal[0];
442*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWReal1 = wReal[1];
443*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWImag0 = wImag[0];
444*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWImag1 = wImag[1];
445*e5436536SAndroid Build Coastguard Worker     for (INT pb = 0; pb < pb_max; pb++) {
446*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp0, tmp1;
447*e5436536SAndroid Build Coastguard Worker 
448*e5436536SAndroid Build Coastguard Worker       tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]);
449*e5436536SAndroid Build Coastguard Worker       tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]);
450*e5436536SAndroid Build Coastguard Worker 
451*e5436536SAndroid Build Coastguard Worker       INT i = pWidth[pb];
452*e5436536SAndroid Build Coastguard Worker 
453*e5436536SAndroid Build Coastguard Worker       do  // about 3-4 times
454*e5436536SAndroid Build Coastguard Worker       {
455*e5436536SAndroid Build Coastguard Worker         FIXP_DBL var0, var1, real, imag;
456*e5436536SAndroid Build Coastguard Worker 
457*e5436536SAndroid Build Coastguard Worker         var0 = *pWReal0++;
458*e5436536SAndroid Build Coastguard Worker         var1 = *pWReal1++;
459*e5436536SAndroid Build Coastguard Worker         real = fMultDiv2(var0, tmp0);
460*e5436536SAndroid Build Coastguard Worker         var0 = *pWImag0++;
461*e5436536SAndroid Build Coastguard Worker         real = fMultAddDiv2(real, var1, tmp1);
462*e5436536SAndroid Build Coastguard Worker         var1 = *pWImag1++;
463*e5436536SAndroid Build Coastguard Worker         imag = fMultDiv2(var0, tmp0);
464*e5436536SAndroid Build Coastguard Worker         *pHybOutRealDry++ = real << (1 + M2_exp);
465*e5436536SAndroid Build Coastguard Worker         imag = fMultAddDiv2(imag, var1, tmp1);
466*e5436536SAndroid Build Coastguard Worker         *pHybOutImagDry++ = imag << (1 + M2_exp);
467*e5436536SAndroid Build Coastguard Worker       } while (--i != 0);
468*e5436536SAndroid Build Coastguard Worker     }
469*e5436536SAndroid Build Coastguard Worker   }
470*e5436536SAndroid Build Coastguard Worker   return err;
471*e5436536SAndroid Build Coastguard Worker }
472*e5436536SAndroid Build Coastguard Worker 
SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry)473*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
474*e5436536SAndroid Build Coastguard Worker     spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal,
475*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry,
476*e5436536SAndroid Build Coastguard Worker     FIXP_DBL **hybOutputImagDry) {
477*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
478*e5436536SAndroid Build Coastguard Worker   INT row;
479*e5436536SAndroid Build Coastguard Worker   INT scale_param_m2;
480*e5436536SAndroid Build Coastguard Worker   INT *pWidth = self->kernels_width;
481*e5436536SAndroid Build Coastguard Worker   INT pb_max = self->kernels[self->hybridBands - 1] + 1;
482*e5436536SAndroid Build Coastguard Worker 
483*e5436536SAndroid Build Coastguard Worker   scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2;
484*e5436536SAndroid Build Coastguard Worker 
485*e5436536SAndroid Build Coastguard Worker   for (row = 0; row < self->numM2rows; row++) {
486*e5436536SAndroid Build Coastguard Worker     INT qs, pb;
487*e5436536SAndroid Build Coastguard Worker 
488*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWReal0 = wReal[0];
489*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWImag0 = wImag[0];
490*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWReal1 = wReal[1];
491*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWImag1 = wImag[1];
492*e5436536SAndroid Build Coastguard Worker 
493*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MReal0 = self->M2Real__FDK[row][0];
494*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0];
495*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MReal1 = self->M2Real__FDK[row][1];
496*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0];
497*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0];
498*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1];
499*e5436536SAndroid Build Coastguard Worker 
500*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row];
501*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row];
502*e5436536SAndroid Build Coastguard Worker 
503*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD));
504*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3);
505*e5436536SAndroid Build Coastguard Worker 
506*e5436536SAndroid Build Coastguard Worker     for (pb = 0, qs = 3; pb < 2; pb++) {
507*e5436536SAndroid Build Coastguard Worker       INT s;
508*e5436536SAndroid Build Coastguard Worker       FIXP_DBL maxVal;
509*e5436536SAndroid Build Coastguard Worker       FIXP_DBL mReal1;
510*e5436536SAndroid Build Coastguard Worker       FIXP_DBL mReal0, mImag0;
511*e5436536SAndroid Build Coastguard Worker       FIXP_DBL iReal0, iImag0, iReal1;
512*e5436536SAndroid Build Coastguard Worker 
513*e5436536SAndroid Build Coastguard Worker       iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
514*e5436536SAndroid Build Coastguard Worker       iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
515*e5436536SAndroid Build Coastguard Worker       iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
516*e5436536SAndroid Build Coastguard Worker 
517*e5436536SAndroid Build Coastguard Worker       maxVal = fAbs(iReal0) | fAbs(iImag0);
518*e5436536SAndroid Build Coastguard Worker       maxVal |= fAbs(iReal1);
519*e5436536SAndroid Build Coastguard Worker 
520*e5436536SAndroid Build Coastguard Worker       s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
521*e5436536SAndroid Build Coastguard Worker 
522*e5436536SAndroid Build Coastguard Worker       mReal0 = scaleValue(iReal0, s);
523*e5436536SAndroid Build Coastguard Worker       mImag0 = scaleValue(iImag0, s);
524*e5436536SAndroid Build Coastguard Worker       mReal1 = scaleValue(iReal1, s);
525*e5436536SAndroid Build Coastguard Worker 
526*e5436536SAndroid Build Coastguard Worker       s = scale_param_m2 - s;
527*e5436536SAndroid Build Coastguard Worker 
528*e5436536SAndroid Build Coastguard Worker       INT i = pWidth[pb];
529*e5436536SAndroid Build Coastguard Worker 
530*e5436536SAndroid Build Coastguard Worker       do {
531*e5436536SAndroid Build Coastguard Worker         FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
532*e5436536SAndroid Build Coastguard Worker 
533*e5436536SAndroid Build Coastguard Worker         wReal0 = *pWReal0++;
534*e5436536SAndroid Build Coastguard Worker         wImag0 = *pWImag0++;
535*e5436536SAndroid Build Coastguard Worker         wReal1 = *pWReal1++;
536*e5436536SAndroid Build Coastguard Worker         wImag1 = *pWImag1++;
537*e5436536SAndroid Build Coastguard Worker 
538*e5436536SAndroid Build Coastguard Worker         cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
539*e5436536SAndroid Build Coastguard Worker 
540*e5436536SAndroid Build Coastguard Worker         *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
541*e5436536SAndroid Build Coastguard Worker         *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
542*e5436536SAndroid Build Coastguard Worker 
543*e5436536SAndroid Build Coastguard Worker         if (qs > 0) {
544*e5436536SAndroid Build Coastguard Worker           mImag0 = -mImag0;
545*e5436536SAndroid Build Coastguard Worker           qs--;
546*e5436536SAndroid Build Coastguard Worker         }
547*e5436536SAndroid Build Coastguard Worker       } while (--i != 0);
548*e5436536SAndroid Build Coastguard Worker     }
549*e5436536SAndroid Build Coastguard Worker 
550*e5436536SAndroid Build Coastguard Worker     for (; pb < pb_max; pb++) {
551*e5436536SAndroid Build Coastguard Worker       INT s;
552*e5436536SAndroid Build Coastguard Worker       FIXP_DBL maxVal;
553*e5436536SAndroid Build Coastguard Worker       FIXP_SGL mReal1;
554*e5436536SAndroid Build Coastguard Worker       FIXP_SGL mReal0, mImag0;
555*e5436536SAndroid Build Coastguard Worker       FIXP_DBL iReal0, iImag0, iReal1;
556*e5436536SAndroid Build Coastguard Worker 
557*e5436536SAndroid Build Coastguard Worker       iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]);
558*e5436536SAndroid Build Coastguard Worker       iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]);
559*e5436536SAndroid Build Coastguard Worker       iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]);
560*e5436536SAndroid Build Coastguard Worker 
561*e5436536SAndroid Build Coastguard Worker       maxVal = fAbs(iReal0) | fAbs(iImag0);
562*e5436536SAndroid Build Coastguard Worker       maxVal |= fAbs(iReal1);
563*e5436536SAndroid Build Coastguard Worker 
564*e5436536SAndroid Build Coastguard Worker       s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
565*e5436536SAndroid Build Coastguard Worker 
566*e5436536SAndroid Build Coastguard Worker       mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
567*e5436536SAndroid Build Coastguard Worker       mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
568*e5436536SAndroid Build Coastguard Worker       mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
569*e5436536SAndroid Build Coastguard Worker 
570*e5436536SAndroid Build Coastguard Worker       s = scale_param_m2 - s;
571*e5436536SAndroid Build Coastguard Worker 
572*e5436536SAndroid Build Coastguard Worker       INT i = pWidth[pb];
573*e5436536SAndroid Build Coastguard Worker 
574*e5436536SAndroid Build Coastguard Worker       do {
575*e5436536SAndroid Build Coastguard Worker         FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1;
576*e5436536SAndroid Build Coastguard Worker 
577*e5436536SAndroid Build Coastguard Worker         wReal0 = *pWReal0++;
578*e5436536SAndroid Build Coastguard Worker         wImag0 = *pWImag0++;
579*e5436536SAndroid Build Coastguard Worker         wReal1 = *pWReal1++;
580*e5436536SAndroid Build Coastguard Worker         wImag1 = *pWImag1++;
581*e5436536SAndroid Build Coastguard Worker 
582*e5436536SAndroid Build Coastguard Worker         cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0);
583*e5436536SAndroid Build Coastguard Worker 
584*e5436536SAndroid Build Coastguard Worker         *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s;
585*e5436536SAndroid Build Coastguard Worker         *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s;
586*e5436536SAndroid Build Coastguard Worker       } while (--i != 0);
587*e5436536SAndroid Build Coastguard Worker     }
588*e5436536SAndroid Build Coastguard Worker   }
589*e5436536SAndroid Build Coastguard Worker 
590*e5436536SAndroid Build Coastguard Worker   return err;
591*e5436536SAndroid Build Coastguard Worker }
592*e5436536SAndroid Build Coastguard Worker 
SpatialDecApplyM2(spatialDec * self,INT ps,const FIXP_SGL alpha,FIXP_DBL ** wReal,FIXP_DBL ** wImag,FIXP_DBL ** hybOutputRealDry,FIXP_DBL ** hybOutputImagDry,FIXP_DBL ** hybOutputRealWet,FIXP_DBL ** hybOutputImagWet)593*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha,
594*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **wReal, FIXP_DBL **wImag,
595*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **hybOutputRealDry,
596*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **hybOutputImagDry,
597*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **hybOutputRealWet,
598*e5436536SAndroid Build Coastguard Worker                                FIXP_DBL **hybOutputImagWet) {
599*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
600*e5436536SAndroid Build Coastguard Worker 
601*e5436536SAndroid Build Coastguard Worker   {
602*e5436536SAndroid Build Coastguard Worker     int qs, row, col;
603*e5436536SAndroid Build Coastguard Worker     int complexHybBands;
604*e5436536SAndroid Build Coastguard Worker     int complexParBands;
605*e5436536SAndroid Build Coastguard Worker     int scale_param_m2 = 0;
606*e5436536SAndroid Build Coastguard Worker     int toolsDisabled;
607*e5436536SAndroid Build Coastguard Worker 
608*e5436536SAndroid Build Coastguard Worker     UCHAR activParamBands;
609*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry,
610*e5436536SAndroid Build Coastguard Worker         *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet,
611*e5436536SAndroid Build Coastguard Worker         *RESTRICT pHybOutImagWet;
612*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
613*e5436536SAndroid Build Coastguard Worker 
614*e5436536SAndroid Build Coastguard Worker     /* The wet signal is added to the dry signal directly in applyM2 if GES and
615*e5436536SAndroid Build Coastguard Worker      * STP are disabled */
616*e5436536SAndroid Build Coastguard Worker     toolsDisabled =
617*e5436536SAndroid Build Coastguard Worker         ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1;
618*e5436536SAndroid Build Coastguard Worker 
619*e5436536SAndroid Build Coastguard Worker     {
620*e5436536SAndroid Build Coastguard Worker       complexHybBands = self->hybridBands;
621*e5436536SAndroid Build Coastguard Worker       complexParBands = self->numParameterBands;
622*e5436536SAndroid Build Coastguard Worker     }
623*e5436536SAndroid Build Coastguard Worker 
624*e5436536SAndroid Build Coastguard Worker     FDKmemclear(hybOutputImagDry[0],
625*e5436536SAndroid Build Coastguard Worker                 self->createParams.maxNumOutputChannels *
626*e5436536SAndroid Build Coastguard Worker                     self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL));
627*e5436536SAndroid Build Coastguard Worker     FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels *
628*e5436536SAndroid Build Coastguard Worker                                          self->createParams.maxNumHybridBands *
629*e5436536SAndroid Build Coastguard Worker                                          sizeof(FIXP_DBL));
630*e5436536SAndroid Build Coastguard Worker 
631*e5436536SAndroid Build Coastguard Worker     if (!toolsDisabled) {
632*e5436536SAndroid Build Coastguard Worker       FDKmemclear(hybOutputRealWet[0],
633*e5436536SAndroid Build Coastguard Worker                   self->createParams.maxNumOutputChannels *
634*e5436536SAndroid Build Coastguard Worker                       self->createParams.maxNumHybridBands * sizeof(FIXP_DBL));
635*e5436536SAndroid Build Coastguard Worker       FDKmemclear(hybOutputImagWet[0],
636*e5436536SAndroid Build Coastguard Worker                   self->createParams.maxNumOutputChannels *
637*e5436536SAndroid Build Coastguard Worker                       self->createParams.maxNumCmplxHybBands *
638*e5436536SAndroid Build Coastguard Worker                       sizeof(FIXP_DBL));
639*e5436536SAndroid Build Coastguard Worker     }
640*e5436536SAndroid Build Coastguard Worker 
641*e5436536SAndroid Build Coastguard Worker     if (self->phaseCoding == 3) {
642*e5436536SAndroid Build Coastguard Worker       scale_param_m2 = -(SCALE_DATA_APPLY_M2_PC - 1);
643*e5436536SAndroid Build Coastguard Worker     }
644*e5436536SAndroid Build Coastguard Worker 
645*e5436536SAndroid Build Coastguard Worker     for (row = 0; row < self->numM2rows; row++) {
646*e5436536SAndroid Build Coastguard Worker       pHybOutRealDry = hybOutputRealDry[row];
647*e5436536SAndroid Build Coastguard Worker       pHybOutImagDry = hybOutputImagDry[row];
648*e5436536SAndroid Build Coastguard Worker 
649*e5436536SAndroid Build Coastguard Worker       if (toolsDisabled) {
650*e5436536SAndroid Build Coastguard Worker         pHybOutRealWet = hybOutputRealDry[row];
651*e5436536SAndroid Build Coastguard Worker         pHybOutImagWet = hybOutputImagDry[row];
652*e5436536SAndroid Build Coastguard Worker       } else {
653*e5436536SAndroid Build Coastguard Worker         pHybOutRealWet = hybOutputRealWet[row];
654*e5436536SAndroid Build Coastguard Worker         pHybOutImagWet = hybOutputImagWet[row];
655*e5436536SAndroid Build Coastguard Worker       }
656*e5436536SAndroid Build Coastguard Worker 
657*e5436536SAndroid Build Coastguard Worker       for (col = 0; col < self->numDirektSignals; col++) {
658*e5436536SAndroid Build Coastguard Worker         if (self->pActivM2ParamBands ==
659*e5436536SAndroid Build Coastguard Worker             0) { /* default setting, calculate all rows and columns */
660*e5436536SAndroid Build Coastguard Worker           activParamBands = 1;
661*e5436536SAndroid Build Coastguard Worker         } else {
662*e5436536SAndroid Build Coastguard Worker           if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
663*e5436536SAndroid Build Coastguard Worker                                        col]) /* table with activ and inactiv
664*e5436536SAndroid Build Coastguard Worker                                                 bands exists for current
665*e5436536SAndroid Build Coastguard Worker                                                 configuration */
666*e5436536SAndroid Build Coastguard Worker             activParamBands = 1;
667*e5436536SAndroid Build Coastguard Worker           else
668*e5436536SAndroid Build Coastguard Worker             activParamBands = 0;
669*e5436536SAndroid Build Coastguard Worker         }
670*e5436536SAndroid Build Coastguard Worker         if (activParamBands) {
671*e5436536SAndroid Build Coastguard Worker           pWReal = wReal[col];
672*e5436536SAndroid Build Coastguard Worker           pWImag = wImag[col];
673*e5436536SAndroid Build Coastguard Worker 
674*e5436536SAndroid Build Coastguard Worker           M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
675*e5436536SAndroid Build Coastguard Worker                               self->M2RealPrev__FDK[row][col],
676*e5436536SAndroid Build Coastguard Worker                               self->kernels_width, alpha,
677*e5436536SAndroid Build Coastguard Worker                               self->numParameterBands);
678*e5436536SAndroid Build Coastguard Worker 
679*e5436536SAndroid Build Coastguard Worker           if (1 && (self->phaseCoding != 3)) {
680*e5436536SAndroid Build Coastguard Worker             /* direct signals */
681*e5436536SAndroid Build Coastguard Worker             {
682*e5436536SAndroid Build Coastguard Worker               /* only one sample will be assigned to each row, hence
683*e5436536SAndroid Build Coastguard Worker                * accumulation is not neccessary; that is valid for all
684*e5436536SAndroid Build Coastguard Worker                * configurations */
685*e5436536SAndroid Build Coastguard Worker               for (qs = 0; qs < complexHybBands; qs++) {
686*e5436536SAndroid Build Coastguard Worker                 pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]);
687*e5436536SAndroid Build Coastguard Worker                 pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]);
688*e5436536SAndroid Build Coastguard Worker               }
689*e5436536SAndroid Build Coastguard Worker             }
690*e5436536SAndroid Build Coastguard Worker           } else { /*  isBinauralMode(self->upmixType)  */
691*e5436536SAndroid Build Coastguard Worker 
692*e5436536SAndroid Build Coastguard Worker             for (qs = 0; qs < complexHybBands; qs++) {
693*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
694*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
695*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
696*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
697*e5436536SAndroid Build Coastguard Worker             }
698*e5436536SAndroid Build Coastguard Worker 
699*e5436536SAndroid Build Coastguard Worker             M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
700*e5436536SAndroid Build Coastguard Worker                                 self->M2ImagPrev__FDK[row][col],
701*e5436536SAndroid Build Coastguard Worker                                 self->kernels_width, alpha, complexParBands);
702*e5436536SAndroid Build Coastguard Worker 
703*e5436536SAndroid Build Coastguard Worker             /* direct signals sign is -1 for qs = 0,2 */
704*e5436536SAndroid Build Coastguard Worker             pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
705*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
706*e5436536SAndroid Build Coastguard Worker             pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
707*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
708*e5436536SAndroid Build Coastguard Worker 
709*e5436536SAndroid Build Coastguard Worker             pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
710*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
711*e5436536SAndroid Build Coastguard Worker             pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
712*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
713*e5436536SAndroid Build Coastguard Worker 
714*e5436536SAndroid Build Coastguard Worker             /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */
715*e5436536SAndroid Build Coastguard Worker             pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
716*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
717*e5436536SAndroid Build Coastguard Worker             pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
718*e5436536SAndroid Build Coastguard Worker                 fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
719*e5436536SAndroid Build Coastguard Worker 
720*e5436536SAndroid Build Coastguard Worker             for (qs = 3; qs < complexHybBands; qs++) {
721*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
722*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
723*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
724*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
725*e5436536SAndroid Build Coastguard Worker             }
726*e5436536SAndroid Build Coastguard Worker           } /* self->upmixType */
727*e5436536SAndroid Build Coastguard Worker         }   /* if (activParamBands) */
728*e5436536SAndroid Build Coastguard Worker       }     /* self->numDirektSignals */
729*e5436536SAndroid Build Coastguard Worker 
730*e5436536SAndroid Build Coastguard Worker       for (; col < self->numVChannels; col++) {
731*e5436536SAndroid Build Coastguard Worker         if (self->pActivM2ParamBands ==
732*e5436536SAndroid Build Coastguard Worker             0) { /* default setting, calculate all rows and columns */
733*e5436536SAndroid Build Coastguard Worker           activParamBands = 1;
734*e5436536SAndroid Build Coastguard Worker         } else {
735*e5436536SAndroid Build Coastguard Worker           if (self->pActivM2ParamBands[MAX_M2_INPUT * row +
736*e5436536SAndroid Build Coastguard Worker                                        col]) /* table with activ and inactiv
737*e5436536SAndroid Build Coastguard Worker                                                 bands exists for current
738*e5436536SAndroid Build Coastguard Worker                                                 configuration */
739*e5436536SAndroid Build Coastguard Worker             activParamBands = 1;
740*e5436536SAndroid Build Coastguard Worker           else
741*e5436536SAndroid Build Coastguard Worker             activParamBands = 0;
742*e5436536SAndroid Build Coastguard Worker         }
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker         if (activParamBands) {
745*e5436536SAndroid Build Coastguard Worker           int resBandIndex;
746*e5436536SAndroid Build Coastguard Worker           int resHybIndex;
747*e5436536SAndroid Build Coastguard Worker 
748*e5436536SAndroid Build Coastguard Worker           resBandIndex =
749*e5436536SAndroid Build Coastguard Worker               self->residualBands[SpatialDecGetResidualIndex(self, col)];
750*e5436536SAndroid Build Coastguard Worker           resHybIndex = self->param2hyb[resBandIndex];
751*e5436536SAndroid Build Coastguard Worker 
752*e5436536SAndroid Build Coastguard Worker           pWReal = wReal[col];
753*e5436536SAndroid Build Coastguard Worker           pWImag = wImag[col];
754*e5436536SAndroid Build Coastguard Worker 
755*e5436536SAndroid Build Coastguard Worker           M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col],
756*e5436536SAndroid Build Coastguard Worker                               self->M2RealPrev__FDK[row][col],
757*e5436536SAndroid Build Coastguard Worker                               self->kernels_width, alpha,
758*e5436536SAndroid Build Coastguard Worker                               self->numParameterBands);
759*e5436536SAndroid Build Coastguard Worker 
760*e5436536SAndroid Build Coastguard Worker           if (1 && (self->phaseCoding != 3)) {
761*e5436536SAndroid Build Coastguard Worker             /* residual signals */
762*e5436536SAndroid Build Coastguard Worker             for (qs = 0; qs < resHybIndex; qs++) {
763*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]);
764*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]);
765*e5436536SAndroid Build Coastguard Worker             }
766*e5436536SAndroid Build Coastguard Worker             /* decor signals */
767*e5436536SAndroid Build Coastguard Worker             for (; qs < complexHybBands; qs++) {
768*e5436536SAndroid Build Coastguard Worker               pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]);
769*e5436536SAndroid Build Coastguard Worker               pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]);
770*e5436536SAndroid Build Coastguard Worker             }
771*e5436536SAndroid Build Coastguard Worker           } else { /* self->upmixType */
772*e5436536SAndroid Build Coastguard Worker             /* residual signals */
773*e5436536SAndroid Build Coastguard Worker             FIXP_DBL *RESTRICT pHybOutReal;
774*e5436536SAndroid Build Coastguard Worker             FIXP_DBL *RESTRICT pHybOutImag;
775*e5436536SAndroid Build Coastguard Worker 
776*e5436536SAndroid Build Coastguard Worker             for (qs = 0; qs < resHybIndex; qs++) {
777*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[qs] += SAC_DEC_APPLY_M2_SCALE(
778*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
779*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
780*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
781*e5436536SAndroid Build Coastguard Worker             }
782*e5436536SAndroid Build Coastguard Worker             /* decor signals */
783*e5436536SAndroid Build Coastguard Worker             for (; qs < complexHybBands; qs++) {
784*e5436536SAndroid Build Coastguard Worker               pHybOutRealWet[qs] += SAC_DEC_APPLY_M2_SCALE(
785*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
786*e5436536SAndroid Build Coastguard Worker               pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
787*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
788*e5436536SAndroid Build Coastguard Worker             }
789*e5436536SAndroid Build Coastguard Worker 
790*e5436536SAndroid Build Coastguard Worker             M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col],
791*e5436536SAndroid Build Coastguard Worker                                 self->M2ImagPrev__FDK[row][col],
792*e5436536SAndroid Build Coastguard Worker                                 self->kernels_width, alpha, complexParBands);
793*e5436536SAndroid Build Coastguard Worker 
794*e5436536SAndroid Build Coastguard Worker             /* direct signals sign is -1 for qs = 0,2 */
795*e5436536SAndroid Build Coastguard Worker             /* direct signals sign is +1 for qs = 1,3.. */
796*e5436536SAndroid Build Coastguard Worker             if (toolsDisabled) {
797*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[0] += SAC_DEC_APPLY_M2_SCALE(
798*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
799*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[0] -= SAC_DEC_APPLY_M2_SCALE(
800*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
801*e5436536SAndroid Build Coastguard Worker 
802*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[1] -= SAC_DEC_APPLY_M2_SCALE(
803*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
804*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[1] += SAC_DEC_APPLY_M2_SCALE(
805*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
806*e5436536SAndroid Build Coastguard Worker 
807*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[2] += SAC_DEC_APPLY_M2_SCALE(
808*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
809*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[2] -= SAC_DEC_APPLY_M2_SCALE(
810*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
811*e5436536SAndroid Build Coastguard Worker             } else {
812*e5436536SAndroid Build Coastguard Worker               pHybOutReal = &pHybOutRealDry[0];
813*e5436536SAndroid Build Coastguard Worker               pHybOutImag = &pHybOutImagDry[0];
814*e5436536SAndroid Build Coastguard Worker               if (0 == resHybIndex) {
815*e5436536SAndroid Build Coastguard Worker                 pHybOutReal = &pHybOutRealWet[0];
816*e5436536SAndroid Build Coastguard Worker                 pHybOutImag = &pHybOutImagWet[0];
817*e5436536SAndroid Build Coastguard Worker               }
818*e5436536SAndroid Build Coastguard Worker               pHybOutReal[0] += SAC_DEC_APPLY_M2_SCALE(
819*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[0], pKernel[0]), scale_param_m2);
820*e5436536SAndroid Build Coastguard Worker               pHybOutImag[0] -= SAC_DEC_APPLY_M2_SCALE(
821*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[0], pKernel[0]), scale_param_m2);
822*e5436536SAndroid Build Coastguard Worker 
823*e5436536SAndroid Build Coastguard Worker               if (1 == resHybIndex) {
824*e5436536SAndroid Build Coastguard Worker                 pHybOutReal = &pHybOutRealWet[0];
825*e5436536SAndroid Build Coastguard Worker                 pHybOutImag = &pHybOutImagWet[0];
826*e5436536SAndroid Build Coastguard Worker               }
827*e5436536SAndroid Build Coastguard Worker               pHybOutReal[1] -= SAC_DEC_APPLY_M2_SCALE(
828*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[1], pKernel[1]), scale_param_m2);
829*e5436536SAndroid Build Coastguard Worker               pHybOutImag[1] += SAC_DEC_APPLY_M2_SCALE(
830*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[1], pKernel[1]), scale_param_m2);
831*e5436536SAndroid Build Coastguard Worker 
832*e5436536SAndroid Build Coastguard Worker               if (2 == resHybIndex) {
833*e5436536SAndroid Build Coastguard Worker                 pHybOutReal = &pHybOutRealWet[0];
834*e5436536SAndroid Build Coastguard Worker                 pHybOutImag = &pHybOutImagWet[0];
835*e5436536SAndroid Build Coastguard Worker               }
836*e5436536SAndroid Build Coastguard Worker               pHybOutReal[2] += SAC_DEC_APPLY_M2_SCALE(
837*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[2], pKernel[2]), scale_param_m2);
838*e5436536SAndroid Build Coastguard Worker               pHybOutImag[2] -= SAC_DEC_APPLY_M2_SCALE(
839*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[2], pKernel[2]), scale_param_m2);
840*e5436536SAndroid Build Coastguard Worker             }
841*e5436536SAndroid Build Coastguard Worker 
842*e5436536SAndroid Build Coastguard Worker             for (qs = 3; qs < resHybIndex; qs++) {
843*e5436536SAndroid Build Coastguard Worker               pHybOutRealDry[qs] -= SAC_DEC_APPLY_M2_SCALE(
844*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
845*e5436536SAndroid Build Coastguard Worker               pHybOutImagDry[qs] += SAC_DEC_APPLY_M2_SCALE(
846*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
847*e5436536SAndroid Build Coastguard Worker             }
848*e5436536SAndroid Build Coastguard Worker             /* decor signals */
849*e5436536SAndroid Build Coastguard Worker             for (; qs < complexHybBands; qs++) {
850*e5436536SAndroid Build Coastguard Worker               pHybOutRealWet[qs] -= SAC_DEC_APPLY_M2_SCALE(
851*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWImag[qs], pKernel[qs]), scale_param_m2);
852*e5436536SAndroid Build Coastguard Worker               pHybOutImagWet[qs] += SAC_DEC_APPLY_M2_SCALE(
853*e5436536SAndroid Build Coastguard Worker                   fMultDiv2(pWReal[qs], pKernel[qs]), scale_param_m2);
854*e5436536SAndroid Build Coastguard Worker             }
855*e5436536SAndroid Build Coastguard Worker           } /* self->upmixType */
856*e5436536SAndroid Build Coastguard Worker         }   /* if (activParamBands) { */
857*e5436536SAndroid Build Coastguard Worker       }     /*  self->numVChannels */
858*e5436536SAndroid Build Coastguard Worker 
859*e5436536SAndroid Build Coastguard Worker       if (self->phaseCoding == 3) {
860*e5436536SAndroid Build Coastguard Worker         scaleValuesSaturate(pHybOutRealDry, complexHybBands,
861*e5436536SAndroid Build Coastguard Worker                             SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
862*e5436536SAndroid Build Coastguard Worker         scaleValuesSaturate(pHybOutImagDry, complexHybBands,
863*e5436536SAndroid Build Coastguard Worker                             SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
864*e5436536SAndroid Build Coastguard Worker 
865*e5436536SAndroid Build Coastguard Worker         if (!toolsDisabled) {
866*e5436536SAndroid Build Coastguard Worker           scaleValuesSaturate(pHybOutRealWet, complexHybBands,
867*e5436536SAndroid Build Coastguard Worker                               SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
868*e5436536SAndroid Build Coastguard Worker           scaleValuesSaturate(pHybOutImagWet, complexHybBands,
869*e5436536SAndroid Build Coastguard Worker                               SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2_PC);
870*e5436536SAndroid Build Coastguard Worker         }
871*e5436536SAndroid Build Coastguard Worker       }
872*e5436536SAndroid Build Coastguard Worker     }
873*e5436536SAndroid Build Coastguard Worker 
874*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS);
875*e5436536SAndroid Build Coastguard Worker   }
876*e5436536SAndroid Build Coastguard Worker 
877*e5436536SAndroid Build Coastguard Worker   return err;
878*e5436536SAndroid Build Coastguard Worker }
879*e5436536SAndroid Build Coastguard Worker 
SpatialDecSynthesis(spatialDec * self,const INT ts,FIXP_DBL ** hybOutputReal,FIXP_DBL ** hybOutputImag,PCM_MPS * timeOut,const INT numInputChannels,const FDK_channelMapDescr * const mapDescr)880*e5436536SAndroid Build Coastguard Worker SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts,
881*e5436536SAndroid Build Coastguard Worker                                  FIXP_DBL **hybOutputReal,
882*e5436536SAndroid Build Coastguard Worker                                  FIXP_DBL **hybOutputImag, PCM_MPS *timeOut,
883*e5436536SAndroid Build Coastguard Worker                                  const INT numInputChannels,
884*e5436536SAndroid Build Coastguard Worker                                  const FDK_channelMapDescr *const mapDescr) {
885*e5436536SAndroid Build Coastguard Worker   SACDEC_ERROR err = MPS_OK;
886*e5436536SAndroid Build Coastguard Worker 
887*e5436536SAndroid Build Coastguard Worker   int ch;
888*e5436536SAndroid Build Coastguard Worker   int stride, offset;
889*e5436536SAndroid Build Coastguard Worker 
890*e5436536SAndroid Build Coastguard Worker   stride = self->numOutputChannelsAT;
891*e5436536SAndroid Build Coastguard Worker   offset = 1;
892*e5436536SAndroid Build Coastguard Worker 
893*e5436536SAndroid Build Coastguard Worker   PCM_MPS *pTimeOut__FDK =
894*e5436536SAndroid Build Coastguard Worker       &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts];
895*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
896*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
897*e5436536SAndroid Build Coastguard Worker 
898*e5436536SAndroid Build Coastguard Worker   for (ch = 0; ch < self->numOutputChannelsAT; ch++) {
899*e5436536SAndroid Build Coastguard Worker     if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) {
900*e5436536SAndroid Build Coastguard Worker       int k;
901*e5436536SAndroid Build Coastguard Worker       /* No hybrid filtering. Just copy the QMF data. */
902*e5436536SAndroid Build Coastguard Worker       for (k = 0; k < self->hybridBands; k += 1) {
903*e5436536SAndroid Build Coastguard Worker         pQmfReal[k] = hybOutputReal[ch][k];
904*e5436536SAndroid Build Coastguard Worker         pQmfImag[k] = hybOutputImag[ch][k];
905*e5436536SAndroid Build Coastguard Worker       }
906*e5436536SAndroid Build Coastguard Worker     } else {
907*e5436536SAndroid Build Coastguard Worker       FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch],
908*e5436536SAndroid Build Coastguard Worker                               hybOutputImag[ch], pQmfReal, pQmfImag);
909*e5436536SAndroid Build Coastguard Worker     }
910*e5436536SAndroid Build Coastguard Worker 
911*e5436536SAndroid Build Coastguard Worker     /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[]
912*e5436536SAndroid Build Coastguard Worker      */
913*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(self->numOutputChannelsAT <= 6);
914*e5436536SAndroid Build Coastguard Worker     int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch),
915*e5436536SAndroid Build Coastguard Worker                                            self->numOutputChannelsAT);
916*e5436536SAndroid Build Coastguard Worker 
917*e5436536SAndroid Build Coastguard Worker     {
918*e5436536SAndroid Build Coastguard Worker       if (self->stereoConfigIndex == 3) {
919*e5436536SAndroid Build Coastguard Worker         /* MPS -> SBR */
920*e5436536SAndroid Build Coastguard Worker         int i;
921*e5436536SAndroid Build Coastguard Worker         FIXP_DBL *pWorkBufReal, *pWorkBufImag;
922*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m ==
923*e5436536SAndroid Build Coastguard Worker                     (FIXP_DBL)0x80000000) &&
924*e5436536SAndroid Build Coastguard Worker                    (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0));
925*e5436536SAndroid Build Coastguard Worker         FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts,
926*e5436536SAndroid Build Coastguard Worker                                     &pWorkBufReal, &pWorkBufImag);
927*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(self->qmfBands <=
928*e5436536SAndroid Build Coastguard Worker                    self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands);
929*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < self->qmfBands; i++) {
930*e5436536SAndroid Build Coastguard Worker           pWorkBufReal[i] = pQmfReal[i];
931*e5436536SAndroid Build Coastguard Worker           pWorkBufImag[i] = pQmfImag[i];
932*e5436536SAndroid Build Coastguard Worker         }
933*e5436536SAndroid Build Coastguard Worker         self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale =
934*e5436536SAndroid Build Coastguard Worker             -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/
935*e5436536SAndroid Build Coastguard Worker         self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
936*e5436536SAndroid Build Coastguard Worker             self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale;
937*e5436536SAndroid Build Coastguard Worker         self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -=
938*e5436536SAndroid Build Coastguard Worker             self->clipProtectGainSF__FDK;
939*e5436536SAndroid Build Coastguard Worker 
940*e5436536SAndroid Build Coastguard Worker         self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= (1);
941*e5436536SAndroid Build Coastguard Worker       } else {
942*e5436536SAndroid Build Coastguard Worker         /* Call the QMF synthesis for dry. */
943*e5436536SAndroid Build Coastguard Worker         err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh],
944*e5436536SAndroid Build Coastguard Worker                                          pQmfReal, pQmfImag, stride,
945*e5436536SAndroid Build Coastguard Worker                                          pTimeOut__FDK + (offset * outCh));
946*e5436536SAndroid Build Coastguard Worker       }
947*e5436536SAndroid Build Coastguard Worker       if (err != MPS_OK) goto bail;
948*e5436536SAndroid Build Coastguard Worker     }
949*e5436536SAndroid Build Coastguard Worker   } /* ch loop */
950*e5436536SAndroid Build Coastguard Worker 
951*e5436536SAndroid Build Coastguard Worker bail:
952*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
953*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS);
954*e5436536SAndroid Build Coastguard Worker 
955*e5436536SAndroid Build Coastguard Worker   return err;
956*e5436536SAndroid Build Coastguard Worker }
957*e5436536SAndroid Build Coastguard Worker 
SpatialDecBufferMatrices(spatialDec * self)958*e5436536SAndroid Build Coastguard Worker void SpatialDecBufferMatrices(spatialDec *self) {
959*e5436536SAndroid Build Coastguard Worker   int row, col;
960*e5436536SAndroid Build Coastguard Worker   int complexParBands;
961*e5436536SAndroid Build Coastguard Worker   complexParBands = self->numParameterBands;
962*e5436536SAndroid Build Coastguard Worker 
963*e5436536SAndroid Build Coastguard Worker   /*
964*e5436536SAndroid Build Coastguard Worker     buffer matrices M2
965*e5436536SAndroid Build Coastguard Worker   */
966*e5436536SAndroid Build Coastguard Worker   for (row = 0; row < self->numM2rows; row++) {
967*e5436536SAndroid Build Coastguard Worker     for (col = 0; col < self->numVChannels; col++) {
968*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col],
969*e5436536SAndroid Build Coastguard Worker                 self->numParameterBands * sizeof(FIXP_DBL));
970*e5436536SAndroid Build Coastguard Worker       if (0 || (self->phaseCoding == 3)) {
971*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col],
972*e5436536SAndroid Build Coastguard Worker                   complexParBands * sizeof(FIXP_DBL));
973*e5436536SAndroid Build Coastguard Worker       }
974*e5436536SAndroid Build Coastguard Worker     }
975*e5436536SAndroid Build Coastguard Worker   }
976*e5436536SAndroid Build Coastguard Worker 
977*e5436536SAndroid Build Coastguard Worker   /* buffer phase */
978*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK,
979*e5436536SAndroid Build Coastguard Worker             self->numParameterBands * sizeof(FIXP_DBL));
980*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK,
981*e5436536SAndroid Build Coastguard Worker             self->numParameterBands * sizeof(FIXP_DBL));
982*e5436536SAndroid Build Coastguard Worker }
983*e5436536SAndroid Build Coastguard Worker 
984*e5436536SAndroid Build Coastguard Worker #define PHASE_SCALE 2
985*e5436536SAndroid Build Coastguard Worker 
986*e5436536SAndroid Build Coastguard Worker #ifndef P_PI
987*e5436536SAndroid Build Coastguard Worker #define P_PI 3.1415926535897932
988*e5436536SAndroid Build Coastguard Worker #endif
989*e5436536SAndroid Build Coastguard Worker 
990*e5436536SAndroid Build Coastguard Worker /* For better precision, PI (pi_x2) is already doubled */
interp_angle__FDK(FIXP_DBL angle1,FIXP_DBL angle2,FIXP_SGL alpha,FIXP_DBL pi_x2)991*e5436536SAndroid Build Coastguard Worker static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2,
992*e5436536SAndroid Build Coastguard Worker                                   FIXP_SGL alpha, FIXP_DBL pi_x2) {
993*e5436536SAndroid Build Coastguard Worker   if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2;
994*e5436536SAndroid Build Coastguard Worker 
995*e5436536SAndroid Build Coastguard Worker   if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2;
996*e5436536SAndroid Build Coastguard Worker 
997*e5436536SAndroid Build Coastguard Worker   return interpolateParameter(alpha, angle2, angle1);
998*e5436536SAndroid Build Coastguard Worker }
999*e5436536SAndroid Build Coastguard Worker 
1000*e5436536SAndroid Build Coastguard Worker /*
1001*e5436536SAndroid Build Coastguard Worker  *
1002*e5436536SAndroid Build Coastguard Worker  */
SpatialDecApplyPhase(spatialDec * self,FIXP_SGL alpha__FDK,int lastSlotOfParamSet)1003*e5436536SAndroid Build Coastguard Worker void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK,
1004*e5436536SAndroid Build Coastguard Worker                           int lastSlotOfParamSet) {
1005*e5436536SAndroid Build Coastguard Worker   int pb, qs;
1006*e5436536SAndroid Build Coastguard Worker   FIXP_DBL ppb[MAX_PARAMETER_BANDS *
1007*e5436536SAndroid Build Coastguard Worker                4]; /* left real, imag - right real, imag interleaved */
1008*e5436536SAndroid Build Coastguard Worker 
1009*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL pi_x2 = PIx2__IPD;
1010*e5436536SAndroid Build Coastguard Worker   for (pb = 0; pb < self->numParameterBands; pb++) {
1011*e5436536SAndroid Build Coastguard Worker     FIXP_DBL pl, pr;
1012*e5436536SAndroid Build Coastguard Worker 
1013*e5436536SAndroid Build Coastguard Worker     pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb],
1014*e5436536SAndroid Build Coastguard Worker                            self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2);
1015*e5436536SAndroid Build Coastguard Worker     pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb],
1016*e5436536SAndroid Build Coastguard Worker                            self->PhaseRight__FDK[pb], alpha__FDK, pi_x2);
1017*e5436536SAndroid Build Coastguard Worker 
1018*e5436536SAndroid Build Coastguard Worker     inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]);
1019*e5436536SAndroid Build Coastguard Worker   }
1020*e5436536SAndroid Build Coastguard Worker 
1021*e5436536SAndroid Build Coastguard Worker   /* sign is -1 for qs = 0,2 and +1 for qs = 1 */
1022*e5436536SAndroid Build Coastguard Worker 
1023*e5436536SAndroid Build Coastguard Worker   const SCHAR *kernels = &self->kernels[0];
1024*e5436536SAndroid Build Coastguard Worker 
1025*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0];
1026*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0];
1027*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0];
1028*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0];
1029*e5436536SAndroid Build Coastguard Worker 
1030*e5436536SAndroid Build Coastguard Worker   for (qs = 2; qs >= 0; qs--) {
1031*e5436536SAndroid Build Coastguard Worker     FIXP_DBL out_re, out_im;
1032*e5436536SAndroid Build Coastguard Worker 
1033*e5436536SAndroid Build Coastguard Worker     pb = *kernels++;
1034*e5436536SAndroid Build Coastguard Worker     if (qs == 1) /* sign[qs] >= 0 */
1035*e5436536SAndroid Build Coastguard Worker     {
1036*e5436536SAndroid Build Coastguard Worker       cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1037*e5436536SAndroid Build Coastguard Worker                    ppb[4 * pb + 1]);
1038*e5436536SAndroid Build Coastguard Worker       out_re <<= PHASE_SCALE - 1;
1039*e5436536SAndroid Build Coastguard Worker       out_im <<= PHASE_SCALE - 1;
1040*e5436536SAndroid Build Coastguard Worker       *Dry_real0++ = out_re;
1041*e5436536SAndroid Build Coastguard Worker       *Dry_imag0++ = out_im;
1042*e5436536SAndroid Build Coastguard Worker 
1043*e5436536SAndroid Build Coastguard Worker       cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1044*e5436536SAndroid Build Coastguard Worker                    ppb[4 * pb + 3]);
1045*e5436536SAndroid Build Coastguard Worker       out_re <<= PHASE_SCALE - 1;
1046*e5436536SAndroid Build Coastguard Worker       out_im <<= PHASE_SCALE - 1;
1047*e5436536SAndroid Build Coastguard Worker       *Dry_real1++ = out_re;
1048*e5436536SAndroid Build Coastguard Worker       *Dry_imag1++ = out_im;
1049*e5436536SAndroid Build Coastguard Worker     } else {
1050*e5436536SAndroid Build Coastguard Worker       cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1051*e5436536SAndroid Build Coastguard Worker                    -ppb[4 * pb + 1]);
1052*e5436536SAndroid Build Coastguard Worker       out_re <<= PHASE_SCALE - 1;
1053*e5436536SAndroid Build Coastguard Worker       out_im <<= PHASE_SCALE - 1;
1054*e5436536SAndroid Build Coastguard Worker       *Dry_real0++ = out_re;
1055*e5436536SAndroid Build Coastguard Worker       *Dry_imag0++ = out_im;
1056*e5436536SAndroid Build Coastguard Worker 
1057*e5436536SAndroid Build Coastguard Worker       cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1058*e5436536SAndroid Build Coastguard Worker                    -ppb[4 * pb + 3]);
1059*e5436536SAndroid Build Coastguard Worker       out_re <<= PHASE_SCALE - 1;
1060*e5436536SAndroid Build Coastguard Worker       out_im <<= PHASE_SCALE - 1;
1061*e5436536SAndroid Build Coastguard Worker       *Dry_real1++ = out_re;
1062*e5436536SAndroid Build Coastguard Worker       *Dry_imag1++ = out_im;
1063*e5436536SAndroid Build Coastguard Worker     }
1064*e5436536SAndroid Build Coastguard Worker   }
1065*e5436536SAndroid Build Coastguard Worker 
1066*e5436536SAndroid Build Coastguard Worker   /* sign is +1 for qs >=3 */
1067*e5436536SAndroid Build Coastguard Worker   for (qs = self->hybridBands - 3; qs--;) {
1068*e5436536SAndroid Build Coastguard Worker     FIXP_DBL out_re, out_im;
1069*e5436536SAndroid Build Coastguard Worker 
1070*e5436536SAndroid Build Coastguard Worker     pb = *kernels++;
1071*e5436536SAndroid Build Coastguard Worker     cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0],
1072*e5436536SAndroid Build Coastguard Worker                  ppb[4 * pb + 1]);
1073*e5436536SAndroid Build Coastguard Worker     out_re <<= PHASE_SCALE - 1;
1074*e5436536SAndroid Build Coastguard Worker     out_im <<= PHASE_SCALE - 1;
1075*e5436536SAndroid Build Coastguard Worker     *Dry_real0++ = out_re;
1076*e5436536SAndroid Build Coastguard Worker     *Dry_imag0++ = out_im;
1077*e5436536SAndroid Build Coastguard Worker 
1078*e5436536SAndroid Build Coastguard Worker     cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2],
1079*e5436536SAndroid Build Coastguard Worker                  ppb[4 * pb + 3]);
1080*e5436536SAndroid Build Coastguard Worker     out_re <<= PHASE_SCALE - 1;
1081*e5436536SAndroid Build Coastguard Worker     out_im <<= PHASE_SCALE - 1;
1082*e5436536SAndroid Build Coastguard Worker     *Dry_real1++ = out_re;
1083*e5436536SAndroid Build Coastguard Worker     *Dry_imag1++ = out_im;
1084*e5436536SAndroid Build Coastguard Worker   }
1085*e5436536SAndroid Build Coastguard Worker }
1086