1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Josef Hoepfl
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: joint stereo processing
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "stereo.h"
104*e5436536SAndroid Build Coastguard Worker
105*e5436536SAndroid Build Coastguard Worker #include "aac_rom.h"
106*e5436536SAndroid Build Coastguard Worker #include "FDK_bitstream.h"
107*e5436536SAndroid Build Coastguard Worker #include "channelinfo.h"
108*e5436536SAndroid Build Coastguard Worker #include "FDK_audio.h"
109*e5436536SAndroid Build Coastguard Worker
110*e5436536SAndroid Build Coastguard Worker enum { L = 0, R = 1 };
111*e5436536SAndroid Build Coastguard Worker
112*e5436536SAndroid Build Coastguard Worker #include "block.h"
113*e5436536SAndroid Build Coastguard Worker
CJointStereo_Read(HANDLE_FDK_BITSTREAM bs,CJointStereoData * pJointStereoData,const int windowGroups,const int scaleFactorBandsTransmitted,const int max_sfb_ste_clear,CJointStereoPersistentData * pJointStereoPersistentData,CCplxPredictionData * cplxPredictionData,int cplxPredictionActiv,int scaleFactorBandsTotal,int windowSequence,const UINT flags)114*e5436536SAndroid Build Coastguard Worker int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs,
115*e5436536SAndroid Build Coastguard Worker CJointStereoData *pJointStereoData,
116*e5436536SAndroid Build Coastguard Worker const int windowGroups,
117*e5436536SAndroid Build Coastguard Worker const int scaleFactorBandsTransmitted,
118*e5436536SAndroid Build Coastguard Worker const int max_sfb_ste_clear,
119*e5436536SAndroid Build Coastguard Worker CJointStereoPersistentData *pJointStereoPersistentData,
120*e5436536SAndroid Build Coastguard Worker CCplxPredictionData *cplxPredictionData,
121*e5436536SAndroid Build Coastguard Worker int cplxPredictionActiv, int scaleFactorBandsTotal,
122*e5436536SAndroid Build Coastguard Worker int windowSequence, const UINT flags) {
123*e5436536SAndroid Build Coastguard Worker int group, band;
124*e5436536SAndroid Build Coastguard Worker
125*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsMaskPresent = (UCHAR)FDKreadBits(bs, 2);
126*e5436536SAndroid Build Coastguard Worker
127*e5436536SAndroid Build Coastguard Worker FDKmemclear(pJointStereoData->MsUsed,
128*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTransmitted * sizeof(UCHAR));
129*e5436536SAndroid Build Coastguard Worker
130*e5436536SAndroid Build Coastguard Worker pJointStereoData->cplx_pred_flag = 0;
131*e5436536SAndroid Build Coastguard Worker if (cplxPredictionActiv) {
132*e5436536SAndroid Build Coastguard Worker cplxPredictionData->pred_dir = 0;
133*e5436536SAndroid Build Coastguard Worker cplxPredictionData->complex_coef = 0;
134*e5436536SAndroid Build Coastguard Worker cplxPredictionData->use_prev_frame = 0;
135*e5436536SAndroid Build Coastguard Worker cplxPredictionData->igf_pred_dir = 0;
136*e5436536SAndroid Build Coastguard Worker }
137*e5436536SAndroid Build Coastguard Worker
138*e5436536SAndroid Build Coastguard Worker switch (pJointStereoData->MsMaskPresent) {
139*e5436536SAndroid Build Coastguard Worker case 0: /* no M/S */
140*e5436536SAndroid Build Coastguard Worker /* all flags are already cleared */
141*e5436536SAndroid Build Coastguard Worker break;
142*e5436536SAndroid Build Coastguard Worker
143*e5436536SAndroid Build Coastguard Worker case 1: /* read ms_used */
144*e5436536SAndroid Build Coastguard Worker for (group = 0; group < windowGroups; group++) {
145*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted; band++) {
146*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
147*e5436536SAndroid Build Coastguard Worker }
148*e5436536SAndroid Build Coastguard Worker }
149*e5436536SAndroid Build Coastguard Worker break;
150*e5436536SAndroid Build Coastguard Worker
151*e5436536SAndroid Build Coastguard Worker case 2: /* full spectrum M/S */
152*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted; band++) {
153*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsUsed[band] = 255; /* set all flags to 1 */
154*e5436536SAndroid Build Coastguard Worker }
155*e5436536SAndroid Build Coastguard Worker break;
156*e5436536SAndroid Build Coastguard Worker
157*e5436536SAndroid Build Coastguard Worker case 3:
158*e5436536SAndroid Build Coastguard Worker /* M/S coding is disabled, complex stereo prediction is enabled */
159*e5436536SAndroid Build Coastguard Worker if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) {
160*e5436536SAndroid Build Coastguard Worker if (cplxPredictionActiv) { /* 'if (stereoConfigIndex == 0)' */
161*e5436536SAndroid Build Coastguard Worker
162*e5436536SAndroid Build Coastguard Worker pJointStereoData->cplx_pred_flag = 1;
163*e5436536SAndroid Build Coastguard Worker
164*e5436536SAndroid Build Coastguard Worker /* cplx_pred_data() cp. ISO/IEC FDIS 23003-3:2011(E) Table 26 */
165*e5436536SAndroid Build Coastguard Worker int cplx_pred_all = 0; /* local use only */
166*e5436536SAndroid Build Coastguard Worker cplx_pred_all = FDKreadBits(bs, 1);
167*e5436536SAndroid Build Coastguard Worker
168*e5436536SAndroid Build Coastguard Worker if (cplx_pred_all) {
169*e5436536SAndroid Build Coastguard Worker for (group = 0; group < windowGroups; group++) {
170*e5436536SAndroid Build Coastguard Worker UCHAR groupmask = ((UCHAR)1 << group);
171*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted; band++) {
172*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsUsed[band] |= groupmask;
173*e5436536SAndroid Build Coastguard Worker }
174*e5436536SAndroid Build Coastguard Worker }
175*e5436536SAndroid Build Coastguard Worker } else {
176*e5436536SAndroid Build Coastguard Worker for (group = 0; group < windowGroups; group++) {
177*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted;
178*e5436536SAndroid Build Coastguard Worker band += SFB_PER_PRED_BAND) {
179*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group);
180*e5436536SAndroid Build Coastguard Worker if ((band + 1) < scaleFactorBandsTotal) {
181*e5436536SAndroid Build Coastguard Worker pJointStereoData->MsUsed[band + 1] |=
182*e5436536SAndroid Build Coastguard Worker (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group));
183*e5436536SAndroid Build Coastguard Worker }
184*e5436536SAndroid Build Coastguard Worker }
185*e5436536SAndroid Build Coastguard Worker }
186*e5436536SAndroid Build Coastguard Worker }
187*e5436536SAndroid Build Coastguard Worker } else {
188*e5436536SAndroid Build Coastguard Worker return -1;
189*e5436536SAndroid Build Coastguard Worker }
190*e5436536SAndroid Build Coastguard Worker }
191*e5436536SAndroid Build Coastguard Worker break;
192*e5436536SAndroid Build Coastguard Worker }
193*e5436536SAndroid Build Coastguard Worker
194*e5436536SAndroid Build Coastguard Worker if (cplxPredictionActiv) {
195*e5436536SAndroid Build Coastguard Worker /* If all sfb are MS-ed then no complex prediction */
196*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsMaskPresent == 3) {
197*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->cplx_pred_flag) {
198*e5436536SAndroid Build Coastguard Worker int delta_code_time = 0;
199*e5436536SAndroid Build Coastguard Worker
200*e5436536SAndroid Build Coastguard Worker /* set pointer to Huffman codebooks */
201*e5436536SAndroid Build Coastguard Worker const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL];
202*e5436536SAndroid Build Coastguard Worker /* set predictors to zero in case of a transition from long to short
203*e5436536SAndroid Build Coastguard Worker * window sequences and vice versa */
204*e5436536SAndroid Build Coastguard Worker if (((windowSequence == BLOCK_SHORT) &&
205*e5436536SAndroid Build Coastguard Worker (pJointStereoPersistentData->winSeqPrev != BLOCK_SHORT)) ||
206*e5436536SAndroid Build Coastguard Worker ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) &&
207*e5436536SAndroid Build Coastguard Worker (windowSequence != BLOCK_SHORT))) {
208*e5436536SAndroid Build Coastguard Worker FDKmemclear(pJointStereoPersistentData->alpha_q_re_prev,
209*e5436536SAndroid Build Coastguard Worker JointStereoMaximumGroups * JointStereoMaximumBands *
210*e5436536SAndroid Build Coastguard Worker sizeof(SHORT));
211*e5436536SAndroid Build Coastguard Worker FDKmemclear(pJointStereoPersistentData->alpha_q_im_prev,
212*e5436536SAndroid Build Coastguard Worker JointStereoMaximumGroups * JointStereoMaximumBands *
213*e5436536SAndroid Build Coastguard Worker sizeof(SHORT));
214*e5436536SAndroid Build Coastguard Worker }
215*e5436536SAndroid Build Coastguard Worker {
216*e5436536SAndroid Build Coastguard Worker FDKmemclear(cplxPredictionData->alpha_q_re,
217*e5436536SAndroid Build Coastguard Worker JointStereoMaximumGroups * JointStereoMaximumBands *
218*e5436536SAndroid Build Coastguard Worker sizeof(SHORT));
219*e5436536SAndroid Build Coastguard Worker FDKmemclear(cplxPredictionData->alpha_q_im,
220*e5436536SAndroid Build Coastguard Worker JointStereoMaximumGroups * JointStereoMaximumBands *
221*e5436536SAndroid Build Coastguard Worker sizeof(SHORT));
222*e5436536SAndroid Build Coastguard Worker }
223*e5436536SAndroid Build Coastguard Worker
224*e5436536SAndroid Build Coastguard Worker /* 0 = mid->side prediction, 1 = side->mid prediction */
225*e5436536SAndroid Build Coastguard Worker cplxPredictionData->pred_dir = FDKreadBits(bs, 1);
226*e5436536SAndroid Build Coastguard Worker cplxPredictionData->complex_coef = FDKreadBits(bs, 1);
227*e5436536SAndroid Build Coastguard Worker
228*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->complex_coef) {
229*e5436536SAndroid Build Coastguard Worker if (flags & AC_INDEP) {
230*e5436536SAndroid Build Coastguard Worker cplxPredictionData->use_prev_frame = 0;
231*e5436536SAndroid Build Coastguard Worker } else {
232*e5436536SAndroid Build Coastguard Worker cplxPredictionData->use_prev_frame = FDKreadBits(bs, 1);
233*e5436536SAndroid Build Coastguard Worker }
234*e5436536SAndroid Build Coastguard Worker }
235*e5436536SAndroid Build Coastguard Worker
236*e5436536SAndroid Build Coastguard Worker if (flags & AC_INDEP) {
237*e5436536SAndroid Build Coastguard Worker delta_code_time = 0;
238*e5436536SAndroid Build Coastguard Worker } else {
239*e5436536SAndroid Build Coastguard Worker delta_code_time = FDKreadBits(bs, 1);
240*e5436536SAndroid Build Coastguard Worker }
241*e5436536SAndroid Build Coastguard Worker
242*e5436536SAndroid Build Coastguard Worker {
243*e5436536SAndroid Build Coastguard Worker int last_alpha_q_re = 0, last_alpha_q_im = 0;
244*e5436536SAndroid Build Coastguard Worker
245*e5436536SAndroid Build Coastguard Worker for (group = 0; group < windowGroups; group++) {
246*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted;
247*e5436536SAndroid Build Coastguard Worker band += SFB_PER_PRED_BAND) {
248*e5436536SAndroid Build Coastguard Worker if (delta_code_time == 1) {
249*e5436536SAndroid Build Coastguard Worker if (group > 0) {
250*e5436536SAndroid Build Coastguard Worker last_alpha_q_re =
251*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group - 1][band];
252*e5436536SAndroid Build Coastguard Worker last_alpha_q_im =
253*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group - 1][band];
254*e5436536SAndroid Build Coastguard Worker } else if ((windowSequence == BLOCK_SHORT) &&
255*e5436536SAndroid Build Coastguard Worker (pJointStereoPersistentData->winSeqPrev ==
256*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT)) {
257*e5436536SAndroid Build Coastguard Worker /* Included for error-robustness */
258*e5436536SAndroid Build Coastguard Worker if (pJointStereoPersistentData->winGroupsPrev == 0) return -1;
259*e5436536SAndroid Build Coastguard Worker
260*e5436536SAndroid Build Coastguard Worker last_alpha_q_re =
261*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_re_prev
262*e5436536SAndroid Build Coastguard Worker [pJointStereoPersistentData->winGroupsPrev - 1][band];
263*e5436536SAndroid Build Coastguard Worker last_alpha_q_im =
264*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_im_prev
265*e5436536SAndroid Build Coastguard Worker [pJointStereoPersistentData->winGroupsPrev - 1][band];
266*e5436536SAndroid Build Coastguard Worker } else {
267*e5436536SAndroid Build Coastguard Worker last_alpha_q_re =
268*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_re_prev[group][band];
269*e5436536SAndroid Build Coastguard Worker last_alpha_q_im =
270*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_im_prev[group][band];
271*e5436536SAndroid Build Coastguard Worker }
272*e5436536SAndroid Build Coastguard Worker
273*e5436536SAndroid Build Coastguard Worker } else {
274*e5436536SAndroid Build Coastguard Worker if (band > 0) {
275*e5436536SAndroid Build Coastguard Worker last_alpha_q_re =
276*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band - 1];
277*e5436536SAndroid Build Coastguard Worker last_alpha_q_im =
278*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band - 1];
279*e5436536SAndroid Build Coastguard Worker } else {
280*e5436536SAndroid Build Coastguard Worker last_alpha_q_re = 0;
281*e5436536SAndroid Build Coastguard Worker last_alpha_q_im = 0;
282*e5436536SAndroid Build Coastguard Worker }
283*e5436536SAndroid Build Coastguard Worker
284*e5436536SAndroid Build Coastguard Worker } /* if (delta_code_time == 1) */
285*e5436536SAndroid Build Coastguard Worker
286*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) {
287*e5436536SAndroid Build Coastguard Worker int dpcm_alpha_re, dpcm_alpha_im;
288*e5436536SAndroid Build Coastguard Worker
289*e5436536SAndroid Build Coastguard Worker dpcm_alpha_re = CBlock_DecodeHuffmanWord(bs, hcb);
290*e5436536SAndroid Build Coastguard Worker dpcm_alpha_re -= 60;
291*e5436536SAndroid Build Coastguard Worker dpcm_alpha_re *= -1;
292*e5436536SAndroid Build Coastguard Worker
293*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band] =
294*e5436536SAndroid Build Coastguard Worker dpcm_alpha_re + last_alpha_q_re;
295*e5436536SAndroid Build Coastguard Worker
296*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->complex_coef) {
297*e5436536SAndroid Build Coastguard Worker dpcm_alpha_im = CBlock_DecodeHuffmanWord(bs, hcb);
298*e5436536SAndroid Build Coastguard Worker dpcm_alpha_im -= 60;
299*e5436536SAndroid Build Coastguard Worker dpcm_alpha_im *= -1;
300*e5436536SAndroid Build Coastguard Worker
301*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band] =
302*e5436536SAndroid Build Coastguard Worker dpcm_alpha_im + last_alpha_q_im;
303*e5436536SAndroid Build Coastguard Worker } else {
304*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band] = 0;
305*e5436536SAndroid Build Coastguard Worker }
306*e5436536SAndroid Build Coastguard Worker
307*e5436536SAndroid Build Coastguard Worker } else {
308*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band] = 0;
309*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band] = 0;
310*e5436536SAndroid Build Coastguard Worker } /* if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) */
311*e5436536SAndroid Build Coastguard Worker
312*e5436536SAndroid Build Coastguard Worker if ((band + 1) <
313*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTransmitted) { /* <= this should be the
314*e5436536SAndroid Build Coastguard Worker correct way (cp.
315*e5436536SAndroid Build Coastguard Worker ISO_IEC_FDIS_23003-0(E) */
316*e5436536SAndroid Build Coastguard Worker /* 7.7.2.3.2 Decoding of prediction coefficients) */
317*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band + 1] =
318*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band];
319*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band + 1] =
320*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band];
321*e5436536SAndroid Build Coastguard Worker } /* if ((band+1)<scaleFactorBandsTotal) */
322*e5436536SAndroid Build Coastguard Worker
323*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_re_prev[group][band] =
324*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band];
325*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_im_prev[group][band] =
326*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band];
327*e5436536SAndroid Build Coastguard Worker }
328*e5436536SAndroid Build Coastguard Worker
329*e5436536SAndroid Build Coastguard Worker for (band = scaleFactorBandsTransmitted; band < max_sfb_ste_clear;
330*e5436536SAndroid Build Coastguard Worker band++) {
331*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_re[group][band] = 0;
332*e5436536SAndroid Build Coastguard Worker cplxPredictionData->alpha_q_im[group][band] = 0;
333*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
334*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
335*e5436536SAndroid Build Coastguard Worker }
336*e5436536SAndroid Build Coastguard Worker }
337*e5436536SAndroid Build Coastguard Worker }
338*e5436536SAndroid Build Coastguard Worker }
339*e5436536SAndroid Build Coastguard Worker } else {
340*e5436536SAndroid Build Coastguard Worker for (group = 0; group < windowGroups; group++) {
341*e5436536SAndroid Build Coastguard Worker for (band = 0; band < max_sfb_ste_clear; band++) {
342*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0;
343*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0;
344*e5436536SAndroid Build Coastguard Worker }
345*e5436536SAndroid Build Coastguard Worker }
346*e5436536SAndroid Build Coastguard Worker }
347*e5436536SAndroid Build Coastguard Worker
348*e5436536SAndroid Build Coastguard Worker pJointStereoPersistentData->winGroupsPrev = windowGroups;
349*e5436536SAndroid Build Coastguard Worker }
350*e5436536SAndroid Build Coastguard Worker
351*e5436536SAndroid Build Coastguard Worker return 0;
352*e5436536SAndroid Build Coastguard Worker }
353*e5436536SAndroid Build Coastguard Worker
CJointStereo_filterAndAdd(FIXP_DBL * in,int len,int windowLen,const FIXP_FILT * coeff,FIXP_DBL * out,UCHAR isCurrent)354*e5436536SAndroid Build Coastguard Worker static void CJointStereo_filterAndAdd(
355*e5436536SAndroid Build Coastguard Worker FIXP_DBL *in, int len, int windowLen, const FIXP_FILT *coeff, FIXP_DBL *out,
356*e5436536SAndroid Build Coastguard Worker UCHAR isCurrent /* output values with even index get a
357*e5436536SAndroid Build Coastguard Worker positve addon (=1) or a negative addon
358*e5436536SAndroid Build Coastguard Worker (=0) */
359*e5436536SAndroid Build Coastguard Worker ) {
360*e5436536SAndroid Build Coastguard Worker int i, j;
361*e5436536SAndroid Build Coastguard Worker
362*e5436536SAndroid Build Coastguard Worker int indices_1[] = {2, 1, 0, 1, 2, 3};
363*e5436536SAndroid Build Coastguard Worker int indices_2[] = {1, 0, 0, 2, 3, 4};
364*e5436536SAndroid Build Coastguard Worker int indices_3[] = {0, 0, 1, 3, 4, 5};
365*e5436536SAndroid Build Coastguard Worker
366*e5436536SAndroid Build Coastguard Worker int subtr_1[] = {6, 5, 4, 2, 1, 1};
367*e5436536SAndroid Build Coastguard Worker int subtr_2[] = {5, 4, 3, 1, 1, 2};
368*e5436536SAndroid Build Coastguard Worker int subtr_3[] = {4, 3, 2, 1, 2, 3};
369*e5436536SAndroid Build Coastguard Worker
370*e5436536SAndroid Build Coastguard Worker if (isCurrent == 1) {
371*e5436536SAndroid Build Coastguard Worker /* exploit the symmetry of the table: coeff[6] = - coeff[0],
372*e5436536SAndroid Build Coastguard Worker coeff[5] = - coeff[1],
373*e5436536SAndroid Build Coastguard Worker coeff[4] = - coeff[2],
374*e5436536SAndroid Build Coastguard Worker coeff[3] = 0
375*e5436536SAndroid Build Coastguard Worker */
376*e5436536SAndroid Build Coastguard Worker
377*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
378*e5436536SAndroid Build Coastguard Worker out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]]) >> SR_FNA_OUT;
379*e5436536SAndroid Build Coastguard Worker out[0] +=
380*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]]) >> SR_FNA_OUT;
381*e5436536SAndroid Build Coastguard Worker }
382*e5436536SAndroid Build Coastguard Worker
383*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
384*e5436536SAndroid Build Coastguard Worker out[1] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]]) >> SR_FNA_OUT;
385*e5436536SAndroid Build Coastguard Worker out[1] +=
386*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]]) >> SR_FNA_OUT;
387*e5436536SAndroid Build Coastguard Worker }
388*e5436536SAndroid Build Coastguard Worker
389*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
390*e5436536SAndroid Build Coastguard Worker out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]]) >> SR_FNA_OUT;
391*e5436536SAndroid Build Coastguard Worker out[2] +=
392*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]]) >> SR_FNA_OUT;
393*e5436536SAndroid Build Coastguard Worker }
394*e5436536SAndroid Build Coastguard Worker
395*e5436536SAndroid Build Coastguard Worker for (j = 3; j < (len - 3); j++) {
396*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
397*e5436536SAndroid Build Coastguard Worker out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i]) >> SR_FNA_OUT;
398*e5436536SAndroid Build Coastguard Worker out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i]) >> SR_FNA_OUT;
399*e5436536SAndroid Build Coastguard Worker }
400*e5436536SAndroid Build Coastguard Worker }
401*e5436536SAndroid Build Coastguard Worker
402*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
403*e5436536SAndroid Build Coastguard Worker out[len - 3] -=
404*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]]) >> SR_FNA_OUT;
405*e5436536SAndroid Build Coastguard Worker out[len - 3] +=
406*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]]) >> SR_FNA_OUT;
407*e5436536SAndroid Build Coastguard Worker }
408*e5436536SAndroid Build Coastguard Worker
409*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
410*e5436536SAndroid Build Coastguard Worker out[len - 2] -=
411*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]]) >> SR_FNA_OUT;
412*e5436536SAndroid Build Coastguard Worker out[len - 2] +=
413*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]]) >> SR_FNA_OUT;
414*e5436536SAndroid Build Coastguard Worker }
415*e5436536SAndroid Build Coastguard Worker
416*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
417*e5436536SAndroid Build Coastguard Worker out[len - 1] -=
418*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]]) >> SR_FNA_OUT;
419*e5436536SAndroid Build Coastguard Worker out[len - 1] +=
420*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]]) >> SR_FNA_OUT;
421*e5436536SAndroid Build Coastguard Worker }
422*e5436536SAndroid Build Coastguard Worker
423*e5436536SAndroid Build Coastguard Worker } else {
424*e5436536SAndroid Build Coastguard Worker /* exploit the symmetry of the table: coeff[6] = coeff[0],
425*e5436536SAndroid Build Coastguard Worker coeff[5] = coeff[1],
426*e5436536SAndroid Build Coastguard Worker coeff[4] = coeff[2]
427*e5436536SAndroid Build Coastguard Worker */
428*e5436536SAndroid Build Coastguard Worker
429*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
430*e5436536SAndroid Build Coastguard Worker out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]] >> SR_FNA_OUT);
431*e5436536SAndroid Build Coastguard Worker out[0] -=
432*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]] >> SR_FNA_OUT);
433*e5436536SAndroid Build Coastguard Worker }
434*e5436536SAndroid Build Coastguard Worker out[0] -= (FIXP_DBL)fMultDiv2(coeff[3], in[0] >> SR_FNA_OUT);
435*e5436536SAndroid Build Coastguard Worker
436*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
437*e5436536SAndroid Build Coastguard Worker out[1] += (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]] >> SR_FNA_OUT);
438*e5436536SAndroid Build Coastguard Worker out[1] +=
439*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]] >> SR_FNA_OUT);
440*e5436536SAndroid Build Coastguard Worker }
441*e5436536SAndroid Build Coastguard Worker out[1] += (FIXP_DBL)fMultDiv2(coeff[3], in[1] >> SR_FNA_OUT);
442*e5436536SAndroid Build Coastguard Worker
443*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
444*e5436536SAndroid Build Coastguard Worker out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]] >> SR_FNA_OUT);
445*e5436536SAndroid Build Coastguard Worker out[2] -=
446*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]] >> SR_FNA_OUT);
447*e5436536SAndroid Build Coastguard Worker }
448*e5436536SAndroid Build Coastguard Worker out[2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[2] >> SR_FNA_OUT);
449*e5436536SAndroid Build Coastguard Worker
450*e5436536SAndroid Build Coastguard Worker for (j = 3; j < (len - 4); j++) {
451*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
452*e5436536SAndroid Build Coastguard Worker out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
453*e5436536SAndroid Build Coastguard Worker out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
454*e5436536SAndroid Build Coastguard Worker }
455*e5436536SAndroid Build Coastguard Worker out[j] += (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
456*e5436536SAndroid Build Coastguard Worker
457*e5436536SAndroid Build Coastguard Worker j++;
458*e5436536SAndroid Build Coastguard Worker
459*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
460*e5436536SAndroid Build Coastguard Worker out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT);
461*e5436536SAndroid Build Coastguard Worker out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT);
462*e5436536SAndroid Build Coastguard Worker }
463*e5436536SAndroid Build Coastguard Worker out[j] -= (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT);
464*e5436536SAndroid Build Coastguard Worker }
465*e5436536SAndroid Build Coastguard Worker
466*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
467*e5436536SAndroid Build Coastguard Worker out[len - 3] +=
468*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]] >> SR_FNA_OUT);
469*e5436536SAndroid Build Coastguard Worker out[len - 3] +=
470*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]] >> SR_FNA_OUT);
471*e5436536SAndroid Build Coastguard Worker }
472*e5436536SAndroid Build Coastguard Worker out[len - 3] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 3] >> SR_FNA_OUT);
473*e5436536SAndroid Build Coastguard Worker
474*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
475*e5436536SAndroid Build Coastguard Worker out[len - 2] -=
476*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]] >> SR_FNA_OUT);
477*e5436536SAndroid Build Coastguard Worker out[len - 2] -=
478*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]] >> SR_FNA_OUT);
479*e5436536SAndroid Build Coastguard Worker }
480*e5436536SAndroid Build Coastguard Worker out[len - 2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[len - 2] >> SR_FNA_OUT);
481*e5436536SAndroid Build Coastguard Worker
482*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
483*e5436536SAndroid Build Coastguard Worker out[len - 1] +=
484*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]] >> SR_FNA_OUT);
485*e5436536SAndroid Build Coastguard Worker out[len - 1] +=
486*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]] >> SR_FNA_OUT);
487*e5436536SAndroid Build Coastguard Worker }
488*e5436536SAndroid Build Coastguard Worker out[len - 1] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 1] >> SR_FNA_OUT);
489*e5436536SAndroid Build Coastguard Worker }
490*e5436536SAndroid Build Coastguard Worker }
491*e5436536SAndroid Build Coastguard Worker
CJointStereo_GenerateMSOutput(FIXP_DBL * pSpecLCurrBand,FIXP_DBL * pSpecRCurrBand,UINT leftScale,UINT rightScale,UINT nSfbBands)492*e5436536SAndroid Build Coastguard Worker static inline void CJointStereo_GenerateMSOutput(FIXP_DBL *pSpecLCurrBand,
493*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpecRCurrBand,
494*e5436536SAndroid Build Coastguard Worker UINT leftScale,
495*e5436536SAndroid Build Coastguard Worker UINT rightScale,
496*e5436536SAndroid Build Coastguard Worker UINT nSfbBands) {
497*e5436536SAndroid Build Coastguard Worker unsigned int i;
498*e5436536SAndroid Build Coastguard Worker
499*e5436536SAndroid Build Coastguard Worker FIXP_DBL leftCoefficient0;
500*e5436536SAndroid Build Coastguard Worker FIXP_DBL leftCoefficient1;
501*e5436536SAndroid Build Coastguard Worker FIXP_DBL leftCoefficient2;
502*e5436536SAndroid Build Coastguard Worker FIXP_DBL leftCoefficient3;
503*e5436536SAndroid Build Coastguard Worker
504*e5436536SAndroid Build Coastguard Worker FIXP_DBL rightCoefficient0;
505*e5436536SAndroid Build Coastguard Worker FIXP_DBL rightCoefficient1;
506*e5436536SAndroid Build Coastguard Worker FIXP_DBL rightCoefficient2;
507*e5436536SAndroid Build Coastguard Worker FIXP_DBL rightCoefficient3;
508*e5436536SAndroid Build Coastguard Worker
509*e5436536SAndroid Build Coastguard Worker for (i = nSfbBands; i > 0; i -= 4) {
510*e5436536SAndroid Build Coastguard Worker leftCoefficient0 = pSpecLCurrBand[i - 4];
511*e5436536SAndroid Build Coastguard Worker leftCoefficient1 = pSpecLCurrBand[i - 3];
512*e5436536SAndroid Build Coastguard Worker leftCoefficient2 = pSpecLCurrBand[i - 2];
513*e5436536SAndroid Build Coastguard Worker leftCoefficient3 = pSpecLCurrBand[i - 1];
514*e5436536SAndroid Build Coastguard Worker
515*e5436536SAndroid Build Coastguard Worker rightCoefficient0 = pSpecRCurrBand[i - 4];
516*e5436536SAndroid Build Coastguard Worker rightCoefficient1 = pSpecRCurrBand[i - 3];
517*e5436536SAndroid Build Coastguard Worker rightCoefficient2 = pSpecRCurrBand[i - 2];
518*e5436536SAndroid Build Coastguard Worker rightCoefficient3 = pSpecRCurrBand[i - 1];
519*e5436536SAndroid Build Coastguard Worker
520*e5436536SAndroid Build Coastguard Worker /* MS output generation */
521*e5436536SAndroid Build Coastguard Worker leftCoefficient0 >>= leftScale;
522*e5436536SAndroid Build Coastguard Worker leftCoefficient1 >>= leftScale;
523*e5436536SAndroid Build Coastguard Worker leftCoefficient2 >>= leftScale;
524*e5436536SAndroid Build Coastguard Worker leftCoefficient3 >>= leftScale;
525*e5436536SAndroid Build Coastguard Worker
526*e5436536SAndroid Build Coastguard Worker rightCoefficient0 >>= rightScale;
527*e5436536SAndroid Build Coastguard Worker rightCoefficient1 >>= rightScale;
528*e5436536SAndroid Build Coastguard Worker rightCoefficient2 >>= rightScale;
529*e5436536SAndroid Build Coastguard Worker rightCoefficient3 >>= rightScale;
530*e5436536SAndroid Build Coastguard Worker
531*e5436536SAndroid Build Coastguard Worker pSpecLCurrBand[i - 4] = leftCoefficient0 + rightCoefficient0;
532*e5436536SAndroid Build Coastguard Worker pSpecLCurrBand[i - 3] = leftCoefficient1 + rightCoefficient1;
533*e5436536SAndroid Build Coastguard Worker pSpecLCurrBand[i - 2] = leftCoefficient2 + rightCoefficient2;
534*e5436536SAndroid Build Coastguard Worker pSpecLCurrBand[i - 1] = leftCoefficient3 + rightCoefficient3;
535*e5436536SAndroid Build Coastguard Worker
536*e5436536SAndroid Build Coastguard Worker pSpecRCurrBand[i - 4] = leftCoefficient0 - rightCoefficient0;
537*e5436536SAndroid Build Coastguard Worker pSpecRCurrBand[i - 3] = leftCoefficient1 - rightCoefficient1;
538*e5436536SAndroid Build Coastguard Worker pSpecRCurrBand[i - 2] = leftCoefficient2 - rightCoefficient2;
539*e5436536SAndroid Build Coastguard Worker pSpecRCurrBand[i - 1] = leftCoefficient3 - rightCoefficient3;
540*e5436536SAndroid Build Coastguard Worker }
541*e5436536SAndroid Build Coastguard Worker }
542*e5436536SAndroid Build Coastguard Worker
CJointStereo_ApplyMS(CAacDecoderChannelInfo * pAacDecoderChannelInfo[2],CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo[2],FIXP_DBL * spectrumL,FIXP_DBL * spectrumR,SHORT * SFBleftScale,SHORT * SFBrightScale,SHORT * specScaleL,SHORT * specScaleR,const SHORT * pScaleFactorBandOffsets,const UCHAR * pWindowGroupLength,const int windowGroups,const int max_sfb_ste_outside,const int scaleFactorBandsTransmittedL,const int scaleFactorBandsTransmittedR,FIXP_DBL * store_dmx_re_prev,SHORT * store_dmx_re_prev_e,const int mainband_flag)543*e5436536SAndroid Build Coastguard Worker void CJointStereo_ApplyMS(
544*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
545*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
546*e5436536SAndroid Build Coastguard Worker FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale,
547*e5436536SAndroid Build Coastguard Worker SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR,
548*e5436536SAndroid Build Coastguard Worker const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength,
549*e5436536SAndroid Build Coastguard Worker const int windowGroups, const int max_sfb_ste_outside,
550*e5436536SAndroid Build Coastguard Worker const int scaleFactorBandsTransmittedL,
551*e5436536SAndroid Build Coastguard Worker const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev,
552*e5436536SAndroid Build Coastguard Worker SHORT *store_dmx_re_prev_e, const int mainband_flag) {
553*e5436536SAndroid Build Coastguard Worker int window, group, band;
554*e5436536SAndroid Build Coastguard Worker UCHAR groupMask;
555*e5436536SAndroid Build Coastguard Worker CJointStereoData *pJointStereoData =
556*e5436536SAndroid Build Coastguard Worker &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
557*e5436536SAndroid Build Coastguard Worker CCplxPredictionData *cplxPredictionData =
558*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo[L]->pComStaticData->cplxPredictionData;
559*e5436536SAndroid Build Coastguard Worker
560*e5436536SAndroid Build Coastguard Worker int max_sfb_ste =
561*e5436536SAndroid Build Coastguard Worker fMax(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
562*e5436536SAndroid Build Coastguard Worker int min_sfb_ste =
563*e5436536SAndroid Build Coastguard Worker fMin(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR);
564*e5436536SAndroid Build Coastguard Worker int scaleFactorBandsTransmitted = min_sfb_ste;
565*e5436536SAndroid Build Coastguard Worker
566*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->cplx_pred_flag) {
567*e5436536SAndroid Build Coastguard Worker int windowLen, groupwin, frameMaxScale;
568*e5436536SAndroid Build Coastguard Worker CJointStereoPersistentData *pJointStereoPersistentData =
569*e5436536SAndroid Build Coastguard Worker &pAacDecoderStaticChannelInfo[L]
570*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData;
571*e5436536SAndroid Build Coastguard Worker FIXP_DBL *const staticSpectralCoeffsL =
572*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
573*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[L];
574*e5436536SAndroid Build Coastguard Worker FIXP_DBL *const staticSpectralCoeffsR =
575*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
576*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[R];
577*e5436536SAndroid Build Coastguard Worker SHORT *const staticSpecScaleL =
578*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
579*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.specScale[L];
580*e5436536SAndroid Build Coastguard Worker SHORT *const staticSpecScaleR =
581*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
582*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.specScale[R];
583*e5436536SAndroid Build Coastguard Worker
584*e5436536SAndroid Build Coastguard Worker FIXP_DBL *dmx_re =
585*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
586*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.scratchBuffer;
587*e5436536SAndroid Build Coastguard Worker FIXP_DBL *dmx_re_prev =
588*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo[L]
589*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData.scratchBuffer +
590*e5436536SAndroid Build Coastguard Worker 1024;
591*e5436536SAndroid Build Coastguard Worker
592*e5436536SAndroid Build Coastguard Worker /* When MS is applied over the main band this value gets computed. Otherwise
593*e5436536SAndroid Build Coastguard Worker * (for the tiles) it uses the assigned value */
594*e5436536SAndroid Build Coastguard Worker SHORT dmx_re_prev_e = *store_dmx_re_prev_e;
595*e5436536SAndroid Build Coastguard Worker
596*e5436536SAndroid Build Coastguard Worker const FIXP_FILT *pCoeff;
597*e5436536SAndroid Build Coastguard Worker const FIXP_FILT *pCoeffPrev;
598*e5436536SAndroid Build Coastguard Worker int coeffPointerOffset;
599*e5436536SAndroid Build Coastguard Worker
600*e5436536SAndroid Build Coastguard Worker int previousShape = (int)pJointStereoPersistentData->winShapePrev;
601*e5436536SAndroid Build Coastguard Worker int currentShape = (int)pAacDecoderChannelInfo[L]->icsInfo.WindowShape;
602*e5436536SAndroid Build Coastguard Worker
603*e5436536SAndroid Build Coastguard Worker /* complex stereo prediction */
604*e5436536SAndroid Build Coastguard Worker
605*e5436536SAndroid Build Coastguard Worker /* 0. preparations */
606*e5436536SAndroid Build Coastguard Worker
607*e5436536SAndroid Build Coastguard Worker /* 0.0. get scratch buffer for downmix MDST */
608*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_START(dmx_im, FIXP_DBL, 1024);
609*e5436536SAndroid Build Coastguard Worker
610*e5436536SAndroid Build Coastguard Worker /* 0.1. window lengths */
611*e5436536SAndroid Build Coastguard Worker
612*e5436536SAndroid Build Coastguard Worker /* get length of short window for current configuration */
613*e5436536SAndroid Build Coastguard Worker windowLen =
614*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo[L]->granuleLength; /* framelength 768 => 96,
615*e5436536SAndroid Build Coastguard Worker framelength 1024 => 128 */
616*e5436536SAndroid Build Coastguard Worker
617*e5436536SAndroid Build Coastguard Worker /* if this is no short-block set length for long-block */
618*e5436536SAndroid Build Coastguard Worker if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != BLOCK_SHORT) {
619*e5436536SAndroid Build Coastguard Worker windowLen *= 8;
620*e5436536SAndroid Build Coastguard Worker }
621*e5436536SAndroid Build Coastguard Worker
622*e5436536SAndroid Build Coastguard Worker /* 0.2. set pointer to filter-coefficients for MDST excitation including
623*e5436536SAndroid Build Coastguard Worker * previous frame portions */
624*e5436536SAndroid Build Coastguard Worker /* cp. ISO/IEC FDIS 23003-3:2011(E) table 125 */
625*e5436536SAndroid Build Coastguard Worker
626*e5436536SAndroid Build Coastguard Worker /* set pointer to default-position */
627*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[previousShape];
628*e5436536SAndroid Build Coastguard Worker
629*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->complex_coef == 1) {
630*e5436536SAndroid Build Coastguard Worker switch (pAacDecoderChannelInfo[L]
631*e5436536SAndroid Build Coastguard Worker ->icsInfo.WindowSequence) { /* current window sequence */
632*e5436536SAndroid Build Coastguard Worker case BLOCK_SHORT:
633*e5436536SAndroid Build Coastguard Worker case BLOCK_LONG:
634*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[previousShape];
635*e5436536SAndroid Build Coastguard Worker break;
636*e5436536SAndroid Build Coastguard Worker
637*e5436536SAndroid Build Coastguard Worker case BLOCK_START:
638*e5436536SAndroid Build Coastguard Worker if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
639*e5436536SAndroid Build Coastguard Worker (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
640*e5436536SAndroid Build Coastguard Worker /* a stop-start-sequence can only follow on an eight-short-sequence
641*e5436536SAndroid Build Coastguard Worker * or a start-sequence */
642*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
643*e5436536SAndroid Build Coastguard Worker } else {
644*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[previousShape];
645*e5436536SAndroid Build Coastguard Worker }
646*e5436536SAndroid Build Coastguard Worker break;
647*e5436536SAndroid Build Coastguard Worker
648*e5436536SAndroid Build Coastguard Worker case BLOCK_STOP:
649*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[2 + previousShape];
650*e5436536SAndroid Build Coastguard Worker break;
651*e5436536SAndroid Build Coastguard Worker
652*e5436536SAndroid Build Coastguard Worker default:
653*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[previousShape];
654*e5436536SAndroid Build Coastguard Worker break;
655*e5436536SAndroid Build Coastguard Worker }
656*e5436536SAndroid Build Coastguard Worker }
657*e5436536SAndroid Build Coastguard Worker
658*e5436536SAndroid Build Coastguard Worker /* 0.3. set pointer to filter-coefficients for MDST excitation */
659*e5436536SAndroid Build Coastguard Worker
660*e5436536SAndroid Build Coastguard Worker /* define offset of pointer to filter-coefficients for MDST exitation
661*e5436536SAndroid Build Coastguard Worker * employing only the current frame */
662*e5436536SAndroid Build Coastguard Worker if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_SINE)) {
663*e5436536SAndroid Build Coastguard Worker coeffPointerOffset = 0;
664*e5436536SAndroid Build Coastguard Worker } else if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_KBD)) {
665*e5436536SAndroid Build Coastguard Worker coeffPointerOffset = 2;
666*e5436536SAndroid Build Coastguard Worker } else if ((previousShape == SHAPE_KBD) && (currentShape == SHAPE_KBD)) {
667*e5436536SAndroid Build Coastguard Worker coeffPointerOffset = 1;
668*e5436536SAndroid Build Coastguard Worker } else /* if ( (previousShape == SHAPE_KBD) && (currentShape == SHAPE_SINE)
669*e5436536SAndroid Build Coastguard Worker ) */
670*e5436536SAndroid Build Coastguard Worker {
671*e5436536SAndroid Build Coastguard Worker coeffPointerOffset = 3;
672*e5436536SAndroid Build Coastguard Worker }
673*e5436536SAndroid Build Coastguard Worker
674*e5436536SAndroid Build Coastguard Worker /* set pointer to filter-coefficient table cp. ISO/IEC FDIS 23003-3:2011(E)
675*e5436536SAndroid Build Coastguard Worker * table 124 */
676*e5436536SAndroid Build Coastguard Worker switch (pAacDecoderChannelInfo[L]
677*e5436536SAndroid Build Coastguard Worker ->icsInfo.WindowSequence) { /* current window sequence */
678*e5436536SAndroid Build Coastguard Worker case BLOCK_SHORT:
679*e5436536SAndroid Build Coastguard Worker case BLOCK_LONG:
680*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
681*e5436536SAndroid Build Coastguard Worker break;
682*e5436536SAndroid Build Coastguard Worker
683*e5436536SAndroid Build Coastguard Worker case BLOCK_START:
684*e5436536SAndroid Build Coastguard Worker if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) ||
685*e5436536SAndroid Build Coastguard Worker (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) {
686*e5436536SAndroid Build Coastguard Worker /* a stop-start-sequence can only follow on an eight-short-sequence or
687*e5436536SAndroid Build Coastguard Worker * a start-sequence */
688*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[12 + coeffPointerOffset];
689*e5436536SAndroid Build Coastguard Worker } else {
690*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[4 + coeffPointerOffset];
691*e5436536SAndroid Build Coastguard Worker }
692*e5436536SAndroid Build Coastguard Worker break;
693*e5436536SAndroid Build Coastguard Worker
694*e5436536SAndroid Build Coastguard Worker case BLOCK_STOP:
695*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[8 + coeffPointerOffset];
696*e5436536SAndroid Build Coastguard Worker break;
697*e5436536SAndroid Build Coastguard Worker
698*e5436536SAndroid Build Coastguard Worker default:
699*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[coeffPointerOffset];
700*e5436536SAndroid Build Coastguard Worker }
701*e5436536SAndroid Build Coastguard Worker
702*e5436536SAndroid Build Coastguard Worker /* 0.4. find maximum common (l/r) band-scaling-factor for whole sequence
703*e5436536SAndroid Build Coastguard Worker * (all windows) */
704*e5436536SAndroid Build Coastguard Worker frameMaxScale = 0;
705*e5436536SAndroid Build Coastguard Worker for (window = 0, group = 0; group < windowGroups; group++) {
706*e5436536SAndroid Build Coastguard Worker for (groupwin = 0; groupwin < pWindowGroupLength[group];
707*e5436536SAndroid Build Coastguard Worker groupwin++, window++) {
708*e5436536SAndroid Build Coastguard Worker SHORT *leftScale = &SFBleftScale[window * 16];
709*e5436536SAndroid Build Coastguard Worker SHORT *rightScale = &SFBrightScale[window * 16];
710*e5436536SAndroid Build Coastguard Worker int windowMaxScale = 0;
711*e5436536SAndroid Build Coastguard Worker
712*e5436536SAndroid Build Coastguard Worker /* find maximum scaling factor of all bands in this window */
713*e5436536SAndroid Build Coastguard Worker for (band = 0; band < min_sfb_ste; band++) {
714*e5436536SAndroid Build Coastguard Worker int lScale = leftScale[band];
715*e5436536SAndroid Build Coastguard Worker int rScale = rightScale[band];
716*e5436536SAndroid Build Coastguard Worker int commonScale = ((lScale > rScale) ? lScale : rScale);
717*e5436536SAndroid Build Coastguard Worker windowMaxScale =
718*e5436536SAndroid Build Coastguard Worker (windowMaxScale < commonScale) ? commonScale : windowMaxScale;
719*e5436536SAndroid Build Coastguard Worker }
720*e5436536SAndroid Build Coastguard Worker if (scaleFactorBandsTransmittedL >
721*e5436536SAndroid Build Coastguard Worker min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedL == max_sfb_ste
722*e5436536SAndroid Build Coastguard Worker */
723*e5436536SAndroid Build Coastguard Worker for (; band < max_sfb_ste; band++) {
724*e5436536SAndroid Build Coastguard Worker int lScale = leftScale[band];
725*e5436536SAndroid Build Coastguard Worker windowMaxScale =
726*e5436536SAndroid Build Coastguard Worker (windowMaxScale < lScale) ? lScale : windowMaxScale;
727*e5436536SAndroid Build Coastguard Worker }
728*e5436536SAndroid Build Coastguard Worker } else {
729*e5436536SAndroid Build Coastguard Worker if (scaleFactorBandsTransmittedR >
730*e5436536SAndroid Build Coastguard Worker min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedR == max_sfb_ste
731*e5436536SAndroid Build Coastguard Worker */
732*e5436536SAndroid Build Coastguard Worker for (; band < max_sfb_ste; band++) {
733*e5436536SAndroid Build Coastguard Worker int rScale = rightScale[band];
734*e5436536SAndroid Build Coastguard Worker windowMaxScale =
735*e5436536SAndroid Build Coastguard Worker (windowMaxScale < rScale) ? rScale : windowMaxScale;
736*e5436536SAndroid Build Coastguard Worker }
737*e5436536SAndroid Build Coastguard Worker }
738*e5436536SAndroid Build Coastguard Worker }
739*e5436536SAndroid Build Coastguard Worker
740*e5436536SAndroid Build Coastguard Worker /* find maximum common SF of all windows */
741*e5436536SAndroid Build Coastguard Worker frameMaxScale =
742*e5436536SAndroid Build Coastguard Worker (frameMaxScale < windowMaxScale) ? windowMaxScale : frameMaxScale;
743*e5436536SAndroid Build Coastguard Worker }
744*e5436536SAndroid Build Coastguard Worker }
745*e5436536SAndroid Build Coastguard Worker
746*e5436536SAndroid Build Coastguard Worker /* add some headroom for overflow protection during filter and add operation
747*e5436536SAndroid Build Coastguard Worker */
748*e5436536SAndroid Build Coastguard Worker frameMaxScale += 2;
749*e5436536SAndroid Build Coastguard Worker
750*e5436536SAndroid Build Coastguard Worker /* process on window-basis (i.e. iterate over all groups and corresponding
751*e5436536SAndroid Build Coastguard Worker * windows) */
752*e5436536SAndroid Build Coastguard Worker for (window = 0, group = 0; group < windowGroups; group++) {
753*e5436536SAndroid Build Coastguard Worker groupMask = 1 << group;
754*e5436536SAndroid Build Coastguard Worker
755*e5436536SAndroid Build Coastguard Worker for (groupwin = 0; groupwin < pWindowGroupLength[group];
756*e5436536SAndroid Build Coastguard Worker groupwin++, window++) {
757*e5436536SAndroid Build Coastguard Worker /* initialize the MDST with zeros */
758*e5436536SAndroid Build Coastguard Worker FDKmemclear(&dmx_im[windowLen * window], windowLen * sizeof(FIXP_DBL));
759*e5436536SAndroid Build Coastguard Worker
760*e5436536SAndroid Build Coastguard Worker /* 1. calculate the previous downmix MDCT. We do this once just for the
761*e5436536SAndroid Build Coastguard Worker * Main band. */
762*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->complex_coef == 1) {
763*e5436536SAndroid Build Coastguard Worker if ((cplxPredictionData->use_prev_frame == 1) && (mainband_flag)) {
764*e5436536SAndroid Build Coastguard Worker /* if this is a long-block or the first window of a short-block
765*e5436536SAndroid Build Coastguard Worker calculate the downmix MDCT of the previous frame.
766*e5436536SAndroid Build Coastguard Worker use_prev_frame is assumed not to change during a frame!
767*e5436536SAndroid Build Coastguard Worker */
768*e5436536SAndroid Build Coastguard Worker
769*e5436536SAndroid Build Coastguard Worker /* first determine shiftfactors to scale left and right channel */
770*e5436536SAndroid Build Coastguard Worker if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
771*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) ||
772*e5436536SAndroid Build Coastguard Worker (window == 0)) {
773*e5436536SAndroid Build Coastguard Worker int index_offset = 0;
774*e5436536SAndroid Build Coastguard Worker int srLeftChan = 0;
775*e5436536SAndroid Build Coastguard Worker int srRightChan = 0;
776*e5436536SAndroid Build Coastguard Worker if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
777*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) {
778*e5436536SAndroid Build Coastguard Worker /* use the last window of the previous frame for MDCT
779*e5436536SAndroid Build Coastguard Worker * calculation if this is a short-block. */
780*e5436536SAndroid Build Coastguard Worker index_offset = windowLen * 7;
781*e5436536SAndroid Build Coastguard Worker if (staticSpecScaleL[7] > staticSpecScaleR[7]) {
782*e5436536SAndroid Build Coastguard Worker srRightChan = staticSpecScaleL[7] - staticSpecScaleR[7];
783*e5436536SAndroid Build Coastguard Worker dmx_re_prev_e = staticSpecScaleL[7];
784*e5436536SAndroid Build Coastguard Worker } else {
785*e5436536SAndroid Build Coastguard Worker srLeftChan = staticSpecScaleR[7] - staticSpecScaleL[7];
786*e5436536SAndroid Build Coastguard Worker dmx_re_prev_e = staticSpecScaleR[7];
787*e5436536SAndroid Build Coastguard Worker }
788*e5436536SAndroid Build Coastguard Worker } else {
789*e5436536SAndroid Build Coastguard Worker if (staticSpecScaleL[0] > staticSpecScaleR[0]) {
790*e5436536SAndroid Build Coastguard Worker srRightChan = staticSpecScaleL[0] - staticSpecScaleR[0];
791*e5436536SAndroid Build Coastguard Worker dmx_re_prev_e = staticSpecScaleL[0];
792*e5436536SAndroid Build Coastguard Worker } else {
793*e5436536SAndroid Build Coastguard Worker srLeftChan = staticSpecScaleR[0] - staticSpecScaleL[0];
794*e5436536SAndroid Build Coastguard Worker dmx_re_prev_e = staticSpecScaleR[0];
795*e5436536SAndroid Build Coastguard Worker }
796*e5436536SAndroid Build Coastguard Worker }
797*e5436536SAndroid Build Coastguard Worker
798*e5436536SAndroid Build Coastguard Worker /* now scale channels and determine downmix MDCT of previous frame
799*e5436536SAndroid Build Coastguard Worker */
800*e5436536SAndroid Build Coastguard Worker if (pAacDecoderStaticChannelInfo[L]
801*e5436536SAndroid Build Coastguard Worker ->pCpeStaticData->jointStereoPersistentData
802*e5436536SAndroid Build Coastguard Worker .clearSpectralCoeffs == 1) {
803*e5436536SAndroid Build Coastguard Worker FDKmemclear(dmx_re_prev, windowLen * sizeof(FIXP_DBL));
804*e5436536SAndroid Build Coastguard Worker dmx_re_prev_e = 0;
805*e5436536SAndroid Build Coastguard Worker } else {
806*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->pred_dir == 0) {
807*e5436536SAndroid Build Coastguard Worker for (int i = 0; i < windowLen; i++) {
808*e5436536SAndroid Build Coastguard Worker dmx_re_prev[i] =
809*e5436536SAndroid Build Coastguard Worker ((staticSpectralCoeffsL[index_offset + i] >>
810*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, srLeftChan + 1)) +
811*e5436536SAndroid Build Coastguard Worker (staticSpectralCoeffsR[index_offset + i] >>
812*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, srRightChan + 1)));
813*e5436536SAndroid Build Coastguard Worker }
814*e5436536SAndroid Build Coastguard Worker } else {
815*e5436536SAndroid Build Coastguard Worker for (int i = 0; i < windowLen; i++) {
816*e5436536SAndroid Build Coastguard Worker dmx_re_prev[i] =
817*e5436536SAndroid Build Coastguard Worker ((staticSpectralCoeffsL[index_offset + i] >>
818*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, srLeftChan + 1)) -
819*e5436536SAndroid Build Coastguard Worker (staticSpectralCoeffsR[index_offset + i] >>
820*e5436536SAndroid Build Coastguard Worker fMin(DFRACT_BITS - 1, srRightChan + 1)));
821*e5436536SAndroid Build Coastguard Worker }
822*e5436536SAndroid Build Coastguard Worker }
823*e5436536SAndroid Build Coastguard Worker }
824*e5436536SAndroid Build Coastguard Worker
825*e5436536SAndroid Build Coastguard Worker /* In case that we use INF we have to preserve the state of the
826*e5436536SAndroid Build Coastguard Worker "dmx_re_prev" (original or computed). This is necessary because we
827*e5436536SAndroid Build Coastguard Worker have to apply MS over the separate IGF tiles. */
828*e5436536SAndroid Build Coastguard Worker FDKmemcpy(store_dmx_re_prev, &dmx_re_prev[0],
829*e5436536SAndroid Build Coastguard Worker windowLen * sizeof(FIXP_DBL));
830*e5436536SAndroid Build Coastguard Worker
831*e5436536SAndroid Build Coastguard Worker /* Particular exponent of the computed/original "dmx_re_prev" must
832*e5436536SAndroid Build Coastguard Worker * be kept for the tile MS calculations if necessary.*/
833*e5436536SAndroid Build Coastguard Worker *store_dmx_re_prev_e = dmx_re_prev_e;
834*e5436536SAndroid Build Coastguard Worker
835*e5436536SAndroid Build Coastguard Worker } /* if ( (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence !=
836*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) || (window == 0) ) */
837*e5436536SAndroid Build Coastguard Worker
838*e5436536SAndroid Build Coastguard Worker } /* if ( pJointStereoData->use_prev_frame == 1 ) */
839*e5436536SAndroid Build Coastguard Worker
840*e5436536SAndroid Build Coastguard Worker } /* if ( pJointStereoData->complex_coef == 1 ) */
841*e5436536SAndroid Build Coastguard Worker
842*e5436536SAndroid Build Coastguard Worker /* 2. calculate downmix MDCT of current frame */
843*e5436536SAndroid Build Coastguard Worker
844*e5436536SAndroid Build Coastguard Worker /* set pointer to scale-factor-bands of current window */
845*e5436536SAndroid Build Coastguard Worker SHORT *leftScale = &SFBleftScale[window * 16];
846*e5436536SAndroid Build Coastguard Worker SHORT *rightScale = &SFBrightScale[window * 16];
847*e5436536SAndroid Build Coastguard Worker
848*e5436536SAndroid Build Coastguard Worker specScaleL[window] = specScaleR[window] = frameMaxScale;
849*e5436536SAndroid Build Coastguard Worker
850*e5436536SAndroid Build Coastguard Worker /* adapt scaling-factors to previous frame */
851*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->use_prev_frame == 1) {
852*e5436536SAndroid Build Coastguard Worker if (window == 0) {
853*e5436536SAndroid Build Coastguard Worker if (dmx_re_prev_e < frameMaxScale) {
854*e5436536SAndroid Build Coastguard Worker if (mainband_flag == 0) {
855*e5436536SAndroid Build Coastguard Worker scaleValues(
856*e5436536SAndroid Build Coastguard Worker dmx_re_prev, store_dmx_re_prev, windowLen,
857*e5436536SAndroid Build Coastguard Worker -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
858*e5436536SAndroid Build Coastguard Worker } else {
859*e5436536SAndroid Build Coastguard Worker scaleValues(
860*e5436536SAndroid Build Coastguard Worker dmx_re_prev, windowLen,
861*e5436536SAndroid Build Coastguard Worker -fMin(DFRACT_BITS - 1, (frameMaxScale - dmx_re_prev_e)));
862*e5436536SAndroid Build Coastguard Worker }
863*e5436536SAndroid Build Coastguard Worker } else {
864*e5436536SAndroid Build Coastguard Worker if (mainband_flag == 0) {
865*e5436536SAndroid Build Coastguard Worker FDKmemcpy(dmx_re_prev, store_dmx_re_prev,
866*e5436536SAndroid Build Coastguard Worker windowLen * sizeof(FIXP_DBL));
867*e5436536SAndroid Build Coastguard Worker }
868*e5436536SAndroid Build Coastguard Worker specScaleL[0] = dmx_re_prev_e;
869*e5436536SAndroid Build Coastguard Worker specScaleR[0] = dmx_re_prev_e;
870*e5436536SAndroid Build Coastguard Worker }
871*e5436536SAndroid Build Coastguard Worker } else { /* window != 0 */
872*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
873*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT);
874*e5436536SAndroid Build Coastguard Worker if (specScaleL[window - 1] < frameMaxScale) {
875*e5436536SAndroid Build Coastguard Worker scaleValues(&dmx_re[windowLen * (window - 1)], windowLen,
876*e5436536SAndroid Build Coastguard Worker -fMin(DFRACT_BITS - 1,
877*e5436536SAndroid Build Coastguard Worker (frameMaxScale - specScaleL[window - 1])));
878*e5436536SAndroid Build Coastguard Worker } else {
879*e5436536SAndroid Build Coastguard Worker specScaleL[window] = specScaleL[window - 1];
880*e5436536SAndroid Build Coastguard Worker specScaleR[window] = specScaleR[window - 1];
881*e5436536SAndroid Build Coastguard Worker }
882*e5436536SAndroid Build Coastguard Worker }
883*e5436536SAndroid Build Coastguard Worker } /* if ( pJointStereoData->use_prev_frame == 1 ) */
884*e5436536SAndroid Build Coastguard Worker
885*e5436536SAndroid Build Coastguard Worker /* scaling factors of both channels ought to be equal now */
886*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(specScaleL[window] == specScaleR[window]);
887*e5436536SAndroid Build Coastguard Worker
888*e5436536SAndroid Build Coastguard Worker /* rescale signal and calculate downmix MDCT */
889*e5436536SAndroid Build Coastguard Worker for (band = 0; band < max_sfb_ste; band++) {
890*e5436536SAndroid Build Coastguard Worker /* first adapt scaling of current band to scaling of current window =>
891*e5436536SAndroid Build Coastguard Worker * shift signal right */
892*e5436536SAndroid Build Coastguard Worker int lScale = leftScale[band];
893*e5436536SAndroid Build Coastguard Worker int rScale = rightScale[band];
894*e5436536SAndroid Build Coastguard Worker
895*e5436536SAndroid Build Coastguard Worker lScale = fMin(DFRACT_BITS - 1, specScaleL[window] - lScale);
896*e5436536SAndroid Build Coastguard Worker rScale = fMin(DFRACT_BITS - 1,
897*e5436536SAndroid Build Coastguard Worker specScaleL[window] - rScale); /* L or R doesn't
898*e5436536SAndroid Build Coastguard Worker matter,
899*e5436536SAndroid Build Coastguard Worker specScales are
900*e5436536SAndroid Build Coastguard Worker equal at this
901*e5436536SAndroid Build Coastguard Worker point */
902*e5436536SAndroid Build Coastguard Worker
903*e5436536SAndroid Build Coastguard Worker /* Write back to sfb scale to cover the case when max_sfb_ste <
904*e5436536SAndroid Build Coastguard Worker * max_sfb */
905*e5436536SAndroid Build Coastguard Worker leftScale[band] = rightScale[band] = specScaleL[window];
906*e5436536SAndroid Build Coastguard Worker
907*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[band];
908*e5436536SAndroid Build Coastguard Worker i < pScaleFactorBandOffsets[band + 1]; i++) {
909*e5436536SAndroid Build Coastguard Worker spectrumL[windowLen * window + i] >>= lScale;
910*e5436536SAndroid Build Coastguard Worker spectrumR[windowLen * window + i] >>= rScale;
911*e5436536SAndroid Build Coastguard Worker }
912*e5436536SAndroid Build Coastguard Worker
913*e5436536SAndroid Build Coastguard Worker /* now calculate downmix MDCT */
914*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
915*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[band];
916*e5436536SAndroid Build Coastguard Worker i < pScaleFactorBandOffsets[band + 1]; i++) {
917*e5436536SAndroid Build Coastguard Worker dmx_re[windowLen * window + i] =
918*e5436536SAndroid Build Coastguard Worker spectrumL[windowLen * window + i];
919*e5436536SAndroid Build Coastguard Worker }
920*e5436536SAndroid Build Coastguard Worker } else {
921*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->pred_dir == 0) {
922*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[band];
923*e5436536SAndroid Build Coastguard Worker i < pScaleFactorBandOffsets[band + 1]; i++) {
924*e5436536SAndroid Build Coastguard Worker dmx_re[windowLen * window + i] =
925*e5436536SAndroid Build Coastguard Worker (spectrumL[windowLen * window + i] +
926*e5436536SAndroid Build Coastguard Worker spectrumR[windowLen * window + i]) >>
927*e5436536SAndroid Build Coastguard Worker 1;
928*e5436536SAndroid Build Coastguard Worker }
929*e5436536SAndroid Build Coastguard Worker } else {
930*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[band];
931*e5436536SAndroid Build Coastguard Worker i < pScaleFactorBandOffsets[band + 1]; i++) {
932*e5436536SAndroid Build Coastguard Worker dmx_re[windowLen * window + i] =
933*e5436536SAndroid Build Coastguard Worker (spectrumL[windowLen * window + i] -
934*e5436536SAndroid Build Coastguard Worker spectrumR[windowLen * window + i]) >>
935*e5436536SAndroid Build Coastguard Worker 1;
936*e5436536SAndroid Build Coastguard Worker }
937*e5436536SAndroid Build Coastguard Worker }
938*e5436536SAndroid Build Coastguard Worker }
939*e5436536SAndroid Build Coastguard Worker
940*e5436536SAndroid Build Coastguard Worker } /* for ( band=0; band<max_sfb_ste; band++ ) */
941*e5436536SAndroid Build Coastguard Worker /* Clean until the end */
942*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[max_sfb_ste_outside];
943*e5436536SAndroid Build Coastguard Worker i < windowLen; i++) {
944*e5436536SAndroid Build Coastguard Worker dmx_re[windowLen * window + i] = (FIXP_DBL)0;
945*e5436536SAndroid Build Coastguard Worker }
946*e5436536SAndroid Build Coastguard Worker
947*e5436536SAndroid Build Coastguard Worker /* 3. calculate MDST-portion corresponding to the current frame. */
948*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->complex_coef == 1) {
949*e5436536SAndroid Build Coastguard Worker {
950*e5436536SAndroid Build Coastguard Worker /* 3.1 move pointer in filter-coefficient table in case of short
951*e5436536SAndroid Build Coastguard Worker * window sequence */
952*e5436536SAndroid Build Coastguard Worker /* (other coefficients are utilized for the last 7 short
953*e5436536SAndroid Build Coastguard Worker * windows) */
954*e5436536SAndroid Build Coastguard Worker if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
955*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) &&
956*e5436536SAndroid Build Coastguard Worker (window != 0)) {
957*e5436536SAndroid Build Coastguard Worker pCoeff = mdst_filt_coef_curr[currentShape];
958*e5436536SAndroid Build Coastguard Worker pCoeffPrev = mdst_filt_coef_prev[currentShape];
959*e5436536SAndroid Build Coastguard Worker }
960*e5436536SAndroid Build Coastguard Worker
961*e5436536SAndroid Build Coastguard Worker /* The length of the filter processing must be extended because of
962*e5436536SAndroid Build Coastguard Worker * filter boundary problems */
963*e5436536SAndroid Build Coastguard Worker int extended_band = fMin(
964*e5436536SAndroid Build Coastguard Worker pScaleFactorBandOffsets[max_sfb_ste_outside] + 7, windowLen);
965*e5436536SAndroid Build Coastguard Worker
966*e5436536SAndroid Build Coastguard Worker /* 3.2. estimate downmix MDST from current frame downmix MDCT */
967*e5436536SAndroid Build Coastguard Worker if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence ==
968*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) &&
969*e5436536SAndroid Build Coastguard Worker (window != 0)) {
970*e5436536SAndroid Build Coastguard Worker CJointStereo_filterAndAdd(&dmx_re[windowLen * window],
971*e5436536SAndroid Build Coastguard Worker extended_band, windowLen, pCoeff,
972*e5436536SAndroid Build Coastguard Worker &dmx_im[windowLen * window], 1);
973*e5436536SAndroid Build Coastguard Worker
974*e5436536SAndroid Build Coastguard Worker CJointStereo_filterAndAdd(&dmx_re[windowLen * (window - 1)],
975*e5436536SAndroid Build Coastguard Worker extended_band, windowLen, pCoeffPrev,
976*e5436536SAndroid Build Coastguard Worker &dmx_im[windowLen * window], 0);
977*e5436536SAndroid Build Coastguard Worker } else {
978*e5436536SAndroid Build Coastguard Worker CJointStereo_filterAndAdd(dmx_re, extended_band, windowLen,
979*e5436536SAndroid Build Coastguard Worker pCoeff, dmx_im, 1);
980*e5436536SAndroid Build Coastguard Worker
981*e5436536SAndroid Build Coastguard Worker if (cplxPredictionData->use_prev_frame == 1) {
982*e5436536SAndroid Build Coastguard Worker CJointStereo_filterAndAdd(dmx_re_prev, extended_band, windowLen,
983*e5436536SAndroid Build Coastguard Worker pCoeffPrev,
984*e5436536SAndroid Build Coastguard Worker &dmx_im[windowLen * window], 0);
985*e5436536SAndroid Build Coastguard Worker }
986*e5436536SAndroid Build Coastguard Worker }
987*e5436536SAndroid Build Coastguard Worker
988*e5436536SAndroid Build Coastguard Worker } /* if(pAacDecoderChannelInfo[L]->transform_splitting_active) */
989*e5436536SAndroid Build Coastguard Worker } /* if ( pJointStereoData->complex_coef == 1 ) */
990*e5436536SAndroid Build Coastguard Worker
991*e5436536SAndroid Build Coastguard Worker /* 4. upmix process */
992*e5436536SAndroid Build Coastguard Worker LONG pred_dir = cplxPredictionData->pred_dir ? -1 : 1;
993*e5436536SAndroid Build Coastguard Worker /* 0.1 in Q-3.34 */
994*e5436536SAndroid Build Coastguard Worker const FIXP_DBL pointOne = 0x66666666; /* 0.8 */
995*e5436536SAndroid Build Coastguard Worker /* Shift value for the downmix */
996*e5436536SAndroid Build Coastguard Worker const INT shift_dmx = SF_FNA_COEFFS + 1;
997*e5436536SAndroid Build Coastguard Worker
998*e5436536SAndroid Build Coastguard Worker for (band = 0; band < max_sfb_ste_outside; band++) {
999*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
1000*e5436536SAndroid Build Coastguard Worker FIXP_SGL tempRe =
1001*e5436536SAndroid Build Coastguard Worker (FIXP_SGL)cplxPredictionData->alpha_q_re[group][band];
1002*e5436536SAndroid Build Coastguard Worker FIXP_SGL tempIm =
1003*e5436536SAndroid Build Coastguard Worker (FIXP_SGL)cplxPredictionData->alpha_q_im[group][band];
1004*e5436536SAndroid Build Coastguard Worker
1005*e5436536SAndroid Build Coastguard Worker /* Find the minimum common headroom for alpha_re and alpha_im */
1006*e5436536SAndroid Build Coastguard Worker int alpha_re_headroom = CountLeadingBits((INT)tempRe) - 16;
1007*e5436536SAndroid Build Coastguard Worker if (tempRe == (FIXP_SGL)0) alpha_re_headroom = 15;
1008*e5436536SAndroid Build Coastguard Worker int alpha_im_headroom = CountLeadingBits((INT)tempIm) - 16;
1009*e5436536SAndroid Build Coastguard Worker if (tempIm == (FIXP_SGL)0) alpha_im_headroom = 15;
1010*e5436536SAndroid Build Coastguard Worker int val = fMin(alpha_re_headroom, alpha_im_headroom);
1011*e5436536SAndroid Build Coastguard Worker
1012*e5436536SAndroid Build Coastguard Worker /* Multiply alpha by 0.1 with maximum precision */
1013*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(val >= 0);
1014*e5436536SAndroid Build Coastguard Worker FIXP_DBL alpha_re_tmp = fMult((FIXP_SGL)(tempRe << val), pointOne);
1015*e5436536SAndroid Build Coastguard Worker FIXP_DBL alpha_im_tmp = fMult((FIXP_SGL)(tempIm << val), pointOne);
1016*e5436536SAndroid Build Coastguard Worker
1017*e5436536SAndroid Build Coastguard Worker /* Calculate alpha exponent */
1018*e5436536SAndroid Build Coastguard Worker /* (Q-3.34 * Q15.0) shifted left by "val" */
1019*e5436536SAndroid Build Coastguard Worker int alpha_re_exp = -3 + 15 - val;
1020*e5436536SAndroid Build Coastguard Worker
1021*e5436536SAndroid Build Coastguard Worker int help3_shift = alpha_re_exp + 1;
1022*e5436536SAndroid Build Coastguard Worker
1023*e5436536SAndroid Build Coastguard Worker FIXP_DBL *p2CoeffL = &(
1024*e5436536SAndroid Build Coastguard Worker spectrumL[windowLen * window + pScaleFactorBandOffsets[band]]);
1025*e5436536SAndroid Build Coastguard Worker FIXP_DBL *p2CoeffR = &(
1026*e5436536SAndroid Build Coastguard Worker spectrumR[windowLen * window + pScaleFactorBandOffsets[band]]);
1027*e5436536SAndroid Build Coastguard Worker FIXP_DBL *p2dmxIm =
1028*e5436536SAndroid Build Coastguard Worker &(dmx_im[windowLen * window + pScaleFactorBandOffsets[band]]);
1029*e5436536SAndroid Build Coastguard Worker FIXP_DBL *p2dmxRe =
1030*e5436536SAndroid Build Coastguard Worker &(dmx_re[windowLen * window + pScaleFactorBandOffsets[band]]);
1031*e5436536SAndroid Build Coastguard Worker
1032*e5436536SAndroid Build Coastguard Worker for (int i = pScaleFactorBandOffsets[band];
1033*e5436536SAndroid Build Coastguard Worker i < pScaleFactorBandOffsets[band + 1]; i++) {
1034*e5436536SAndroid Build Coastguard Worker /* Calculating helper term:
1035*e5436536SAndroid Build Coastguard Worker side = specR[i] - alpha_re[i] * dmx_re[i] - alpha_im[i] *
1036*e5436536SAndroid Build Coastguard Worker dmx_im[i];
1037*e5436536SAndroid Build Coastguard Worker
1038*e5436536SAndroid Build Coastguard Worker Here "dmx_re" may be the same as "specL" or alternatively keep
1039*e5436536SAndroid Build Coastguard Worker the downmix. "dmx_re" and "specL" are two different pointers
1040*e5436536SAndroid Build Coastguard Worker pointing to separate arrays, which may or may not contain the
1041*e5436536SAndroid Build Coastguard Worker same data (with different scaling).
1042*e5436536SAndroid Build Coastguard Worker
1043*e5436536SAndroid Build Coastguard Worker specL[i] = + (specL[i] + side);
1044*e5436536SAndroid Build Coastguard Worker specR[i] = -/+ (specL[i] - side);
1045*e5436536SAndroid Build Coastguard Worker */
1046*e5436536SAndroid Build Coastguard Worker FIXP_DBL side, left, right;
1047*e5436536SAndroid Build Coastguard Worker
1048*e5436536SAndroid Build Coastguard Worker side = fMultAddDiv2(fMultDiv2(alpha_re_tmp, *p2dmxRe++),
1049*e5436536SAndroid Build Coastguard Worker alpha_im_tmp, (*p2dmxIm++) << shift_dmx);
1050*e5436536SAndroid Build Coastguard Worker side = ((*p2CoeffR) >> 2) -
1051*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)SATURATE_SHIFT(side, -(help3_shift - 2),
1052*e5436536SAndroid Build Coastguard Worker DFRACT_BITS - 2);
1053*e5436536SAndroid Build Coastguard Worker
1054*e5436536SAndroid Build Coastguard Worker left = ((*p2CoeffL) >> 2) + side;
1055*e5436536SAndroid Build Coastguard Worker right = ((*p2CoeffL) >> 2) - side;
1056*e5436536SAndroid Build Coastguard Worker right = (FIXP_DBL)((LONG)right * pred_dir);
1057*e5436536SAndroid Build Coastguard Worker
1058*e5436536SAndroid Build Coastguard Worker *p2CoeffL++ = SATURATE_LEFT_SHIFT_ALT(left, 2, DFRACT_BITS);
1059*e5436536SAndroid Build Coastguard Worker *p2CoeffR++ = SATURATE_LEFT_SHIFT_ALT(right, 2, DFRACT_BITS);
1060*e5436536SAndroid Build Coastguard Worker }
1061*e5436536SAndroid Build Coastguard Worker }
1062*e5436536SAndroid Build Coastguard Worker
1063*e5436536SAndroid Build Coastguard Worker } /* for ( band=0; band < max_sfb_ste; band++ ) */
1064*e5436536SAndroid Build Coastguard Worker } /* for ( groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++,
1065*e5436536SAndroid Build Coastguard Worker window++ ) */
1066*e5436536SAndroid Build Coastguard Worker
1067*e5436536SAndroid Build Coastguard Worker } /* for ( window = 0, group = 0; group < windowGroups; group++ ) */
1068*e5436536SAndroid Build Coastguard Worker
1069*e5436536SAndroid Build Coastguard Worker /* free scratch buffer */
1070*e5436536SAndroid Build Coastguard Worker C_AALLOC_SCRATCH_END(dmx_im, FIXP_DBL, 1024);
1071*e5436536SAndroid Build Coastguard Worker
1072*e5436536SAndroid Build Coastguard Worker } else {
1073*e5436536SAndroid Build Coastguard Worker /* MS stereo */
1074*e5436536SAndroid Build Coastguard Worker
1075*e5436536SAndroid Build Coastguard Worker for (window = 0, group = 0; group < windowGroups; group++) {
1076*e5436536SAndroid Build Coastguard Worker groupMask = 1 << group;
1077*e5436536SAndroid Build Coastguard Worker
1078*e5436536SAndroid Build Coastguard Worker for (int groupwin = 0; groupwin < pWindowGroupLength[group];
1079*e5436536SAndroid Build Coastguard Worker groupwin++, window++) {
1080*e5436536SAndroid Build Coastguard Worker FIXP_DBL *leftSpectrum, *rightSpectrum;
1081*e5436536SAndroid Build Coastguard Worker SHORT *leftScale = &SFBleftScale[window * 16];
1082*e5436536SAndroid Build Coastguard Worker SHORT *rightScale = &SFBrightScale[window * 16];
1083*e5436536SAndroid Build Coastguard Worker
1084*e5436536SAndroid Build Coastguard Worker leftSpectrum =
1085*e5436536SAndroid Build Coastguard Worker SPEC(spectrumL, window, pAacDecoderChannelInfo[L]->granuleLength);
1086*e5436536SAndroid Build Coastguard Worker rightSpectrum =
1087*e5436536SAndroid Build Coastguard Worker SPEC(spectrumR, window, pAacDecoderChannelInfo[R]->granuleLength);
1088*e5436536SAndroid Build Coastguard Worker
1089*e5436536SAndroid Build Coastguard Worker for (band = 0; band < max_sfb_ste_outside; band++) {
1090*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
1091*e5436536SAndroid Build Coastguard Worker int lScale = leftScale[band];
1092*e5436536SAndroid Build Coastguard Worker int rScale = rightScale[band];
1093*e5436536SAndroid Build Coastguard Worker int commonScale = lScale > rScale ? lScale : rScale;
1094*e5436536SAndroid Build Coastguard Worker unsigned int offsetCurrBand, offsetNextBand;
1095*e5436536SAndroid Build Coastguard Worker
1096*e5436536SAndroid Build Coastguard Worker /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 :
1097*e5436536SAndroid Build Coastguard Worker M/S joint channel coding can only be used if common_window is 1.
1098*e5436536SAndroid Build Coastguard Worker */
1099*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
1100*e5436536SAndroid Build Coastguard Worker GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
1101*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
1102*e5436536SAndroid Build Coastguard Worker GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
1103*e5436536SAndroid Build Coastguard Worker
1104*e5436536SAndroid Build Coastguard Worker commonScale++;
1105*e5436536SAndroid Build Coastguard Worker leftScale[band] = commonScale;
1106*e5436536SAndroid Build Coastguard Worker rightScale[band] = commonScale;
1107*e5436536SAndroid Build Coastguard Worker
1108*e5436536SAndroid Build Coastguard Worker lScale = fMin(DFRACT_BITS - 1, commonScale - lScale);
1109*e5436536SAndroid Build Coastguard Worker rScale = fMin(DFRACT_BITS - 1, commonScale - rScale);
1110*e5436536SAndroid Build Coastguard Worker
1111*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(lScale >= 0 && rScale >= 0);
1112*e5436536SAndroid Build Coastguard Worker
1113*e5436536SAndroid Build Coastguard Worker offsetCurrBand = pScaleFactorBandOffsets[band];
1114*e5436536SAndroid Build Coastguard Worker offsetNextBand = pScaleFactorBandOffsets[band + 1];
1115*e5436536SAndroid Build Coastguard Worker
1116*e5436536SAndroid Build Coastguard Worker CJointStereo_GenerateMSOutput(&(leftSpectrum[offsetCurrBand]),
1117*e5436536SAndroid Build Coastguard Worker &(rightSpectrum[offsetCurrBand]),
1118*e5436536SAndroid Build Coastguard Worker lScale, rScale,
1119*e5436536SAndroid Build Coastguard Worker offsetNextBand - offsetCurrBand);
1120*e5436536SAndroid Build Coastguard Worker }
1121*e5436536SAndroid Build Coastguard Worker }
1122*e5436536SAndroid Build Coastguard Worker if (scaleFactorBandsTransmittedL > scaleFactorBandsTransmitted) {
1123*e5436536SAndroid Build Coastguard Worker for (; band < scaleFactorBandsTransmittedL; band++) {
1124*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
1125*e5436536SAndroid Build Coastguard Worker rightScale[band] = leftScale[band];
1126*e5436536SAndroid Build Coastguard Worker
1127*e5436536SAndroid Build Coastguard Worker for (int index = pScaleFactorBandOffsets[band];
1128*e5436536SAndroid Build Coastguard Worker index < pScaleFactorBandOffsets[band + 1]; index++) {
1129*e5436536SAndroid Build Coastguard Worker FIXP_DBL leftCoefficient = leftSpectrum[index];
1130*e5436536SAndroid Build Coastguard Worker /* FIXP_DBL rightCoefficient = (FIXP_DBL)0; */
1131*e5436536SAndroid Build Coastguard Worker rightSpectrum[index] = leftCoefficient;
1132*e5436536SAndroid Build Coastguard Worker }
1133*e5436536SAndroid Build Coastguard Worker }
1134*e5436536SAndroid Build Coastguard Worker }
1135*e5436536SAndroid Build Coastguard Worker } else if (scaleFactorBandsTransmittedR > scaleFactorBandsTransmitted) {
1136*e5436536SAndroid Build Coastguard Worker for (; band < scaleFactorBandsTransmittedR; band++) {
1137*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
1138*e5436536SAndroid Build Coastguard Worker leftScale[band] = rightScale[band];
1139*e5436536SAndroid Build Coastguard Worker
1140*e5436536SAndroid Build Coastguard Worker for (int index = pScaleFactorBandOffsets[band];
1141*e5436536SAndroid Build Coastguard Worker index < pScaleFactorBandOffsets[band + 1]; index++) {
1142*e5436536SAndroid Build Coastguard Worker /* FIXP_DBL leftCoefficient = (FIXP_DBL)0; */
1143*e5436536SAndroid Build Coastguard Worker FIXP_DBL rightCoefficient = rightSpectrum[index];
1144*e5436536SAndroid Build Coastguard Worker
1145*e5436536SAndroid Build Coastguard Worker leftSpectrum[index] = rightCoefficient;
1146*e5436536SAndroid Build Coastguard Worker rightSpectrum[index] = -rightCoefficient;
1147*e5436536SAndroid Build Coastguard Worker }
1148*e5436536SAndroid Build Coastguard Worker }
1149*e5436536SAndroid Build Coastguard Worker }
1150*e5436536SAndroid Build Coastguard Worker }
1151*e5436536SAndroid Build Coastguard Worker }
1152*e5436536SAndroid Build Coastguard Worker }
1153*e5436536SAndroid Build Coastguard Worker
1154*e5436536SAndroid Build Coastguard Worker /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary
1155*e5436536SAndroid Build Coastguard Worker for intensity coding. PNS correlation signalling was mapped before
1156*e5436536SAndroid Build Coastguard Worker calling CJointStereo_ApplyMS(). */
1157*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsMaskPresent == 2) {
1158*e5436536SAndroid Build Coastguard Worker FDKmemclear(pJointStereoData->MsUsed,
1159*e5436536SAndroid Build Coastguard Worker JointStereoMaximumBands * sizeof(UCHAR));
1160*e5436536SAndroid Build Coastguard Worker }
1161*e5436536SAndroid Build Coastguard Worker }
1162*e5436536SAndroid Build Coastguard Worker }
1163*e5436536SAndroid Build Coastguard Worker
CJointStereo_ApplyIS(CAacDecoderChannelInfo * pAacDecoderChannelInfo[2],const SHORT * pScaleFactorBandOffsets,const UCHAR * pWindowGroupLength,const int windowGroups,const int scaleFactorBandsTransmitted)1164*e5436536SAndroid Build Coastguard Worker void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
1165*e5436536SAndroid Build Coastguard Worker const SHORT *pScaleFactorBandOffsets,
1166*e5436536SAndroid Build Coastguard Worker const UCHAR *pWindowGroupLength,
1167*e5436536SAndroid Build Coastguard Worker const int windowGroups,
1168*e5436536SAndroid Build Coastguard Worker const int scaleFactorBandsTransmitted) {
1169*e5436536SAndroid Build Coastguard Worker CJointStereoData *pJointStereoData =
1170*e5436536SAndroid Build Coastguard Worker &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
1171*e5436536SAndroid Build Coastguard Worker
1172*e5436536SAndroid Build Coastguard Worker for (int window = 0, group = 0; group < windowGroups; group++) {
1173*e5436536SAndroid Build Coastguard Worker UCHAR *CodeBook;
1174*e5436536SAndroid Build Coastguard Worker SHORT *ScaleFactor;
1175*e5436536SAndroid Build Coastguard Worker UCHAR groupMask = 1 << group;
1176*e5436536SAndroid Build Coastguard Worker
1177*e5436536SAndroid Build Coastguard Worker CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group * 16];
1178*e5436536SAndroid Build Coastguard Worker ScaleFactor =
1179*e5436536SAndroid Build Coastguard Worker &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group * 16];
1180*e5436536SAndroid Build Coastguard Worker
1181*e5436536SAndroid Build Coastguard Worker for (int groupwin = 0; groupwin < pWindowGroupLength[group];
1182*e5436536SAndroid Build Coastguard Worker groupwin++, window++) {
1183*e5436536SAndroid Build Coastguard Worker FIXP_DBL *leftSpectrum, *rightSpectrum;
1184*e5436536SAndroid Build Coastguard Worker SHORT *leftScale =
1185*e5436536SAndroid Build Coastguard Worker &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window * 16];
1186*e5436536SAndroid Build Coastguard Worker SHORT *rightScale =
1187*e5436536SAndroid Build Coastguard Worker &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window * 16];
1188*e5436536SAndroid Build Coastguard Worker int band;
1189*e5436536SAndroid Build Coastguard Worker
1190*e5436536SAndroid Build Coastguard Worker leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient,
1191*e5436536SAndroid Build Coastguard Worker window, pAacDecoderChannelInfo[L]->granuleLength);
1192*e5436536SAndroid Build Coastguard Worker rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient,
1193*e5436536SAndroid Build Coastguard Worker window, pAacDecoderChannelInfo[R]->granuleLength);
1194*e5436536SAndroid Build Coastguard Worker
1195*e5436536SAndroid Build Coastguard Worker for (band = 0; band < scaleFactorBandsTransmitted; band++) {
1196*e5436536SAndroid Build Coastguard Worker if ((CodeBook[band] == INTENSITY_HCB) ||
1197*e5436536SAndroid Build Coastguard Worker (CodeBook[band] == INTENSITY_HCB2)) {
1198*e5436536SAndroid Build Coastguard Worker int bandScale = -(ScaleFactor[band] + 100);
1199*e5436536SAndroid Build Coastguard Worker
1200*e5436536SAndroid Build Coastguard Worker int msb = bandScale >> 2;
1201*e5436536SAndroid Build Coastguard Worker int lsb = bandScale & 0x03;
1202*e5436536SAndroid Build Coastguard Worker
1203*e5436536SAndroid Build Coastguard Worker /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */
1204*e5436536SAndroid Build Coastguard Worker FIXP_DBL scale = MantissaTable[lsb][0];
1205*e5436536SAndroid Build Coastguard Worker
1206*e5436536SAndroid Build Coastguard Worker /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 :
1207*e5436536SAndroid Build Coastguard Worker The use of intensity stereo coding is signaled by the use of the
1208*e5436536SAndroid Build Coastguard Worker pseudo codebooks INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only
1209*e5436536SAndroid Build Coastguard Worker in the right channel of a channel_pair_element() having a common
1210*e5436536SAndroid Build Coastguard Worker ics_info() (common_window == 1). */
1211*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) ==
1212*e5436536SAndroid Build Coastguard Worker GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
1213*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) ==
1214*e5436536SAndroid Build Coastguard Worker GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
1215*e5436536SAndroid Build Coastguard Worker
1216*e5436536SAndroid Build Coastguard Worker rightScale[band] = leftScale[band] + msb + 1;
1217*e5436536SAndroid Build Coastguard Worker
1218*e5436536SAndroid Build Coastguard Worker if (pJointStereoData->MsUsed[band] & groupMask) {
1219*e5436536SAndroid Build Coastguard Worker if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */
1220*e5436536SAndroid Build Coastguard Worker {
1221*e5436536SAndroid Build Coastguard Worker scale = -scale;
1222*e5436536SAndroid Build Coastguard Worker }
1223*e5436536SAndroid Build Coastguard Worker } else {
1224*e5436536SAndroid Build Coastguard Worker if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */
1225*e5436536SAndroid Build Coastguard Worker {
1226*e5436536SAndroid Build Coastguard Worker scale = -scale;
1227*e5436536SAndroid Build Coastguard Worker }
1228*e5436536SAndroid Build Coastguard Worker }
1229*e5436536SAndroid Build Coastguard Worker
1230*e5436536SAndroid Build Coastguard Worker for (int index = pScaleFactorBandOffsets[band];
1231*e5436536SAndroid Build Coastguard Worker index < pScaleFactorBandOffsets[band + 1]; index++) {
1232*e5436536SAndroid Build Coastguard Worker rightSpectrum[index] = fMult(leftSpectrum[index], scale);
1233*e5436536SAndroid Build Coastguard Worker }
1234*e5436536SAndroid Build Coastguard Worker }
1235*e5436536SAndroid Build Coastguard Worker }
1236*e5436536SAndroid Build Coastguard Worker }
1237*e5436536SAndroid Build Coastguard Worker }
1238*e5436536SAndroid Build Coastguard Worker }
1239