xref: /aosp_15_r20/external/aac/libAACdec/src/usacdec_lpd.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker 
7*e5436536SAndroid Build Coastguard Worker  1.    INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker 
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker 
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker 
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker 
34*e5436536SAndroid Build Coastguard Worker 2.    COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker 
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker 
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker 
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker 
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker 
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker 
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker 3.    NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker 
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker 
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker 
71*e5436536SAndroid Build Coastguard Worker 4.    DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker 
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker 
84*e5436536SAndroid Build Coastguard Worker 5.    CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker 
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker 
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker 
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   Manuel Jander
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: USAC Linear Prediction Domain coding
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "usacdec_lpd.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker #include "usacdec_rom.h"
106*e5436536SAndroid Build Coastguard Worker #include "usacdec_fac.h"
107*e5436536SAndroid Build Coastguard Worker #include "usacdec_lpc.h"
108*e5436536SAndroid Build Coastguard Worker #include "FDK_tools_rom.h"
109*e5436536SAndroid Build Coastguard Worker #include "fft.h"
110*e5436536SAndroid Build Coastguard Worker #include "mdct.h"
111*e5436536SAndroid Build Coastguard Worker #include "usacdec_acelp.h"
112*e5436536SAndroid Build Coastguard Worker #include "overlapadd.h"
113*e5436536SAndroid Build Coastguard Worker 
114*e5436536SAndroid Build Coastguard Worker #include "conceal.h"
115*e5436536SAndroid Build Coastguard Worker 
116*e5436536SAndroid Build Coastguard Worker #include "block.h"
117*e5436536SAndroid Build Coastguard Worker 
118*e5436536SAndroid Build Coastguard Worker #define SF_PITCH_TRACK 6
119*e5436536SAndroid Build Coastguard Worker #define SF_GAIN 3
120*e5436536SAndroid Build Coastguard Worker #define MIN_VAL FL2FXCONST_DBL(0.0f)
121*e5436536SAndroid Build Coastguard Worker #define MAX_VAL (FIXP_DBL) MAXVAL_DBL
122*e5436536SAndroid Build Coastguard Worker 
123*e5436536SAndroid Build Coastguard Worker #include "ac_arith_coder.h"
124*e5436536SAndroid Build Coastguard Worker 
filtLP(const FIXP_DBL * syn,PCM_DEC * syn_out,FIXP_DBL * noise,const FIXP_SGL * filt,const INT aacOutDataHeadroom,INT stop,int len)125*e5436536SAndroid Build Coastguard Worker void filtLP(const FIXP_DBL *syn, PCM_DEC *syn_out, FIXP_DBL *noise,
126*e5436536SAndroid Build Coastguard Worker             const FIXP_SGL *filt, const INT aacOutDataHeadroom, INT stop,
127*e5436536SAndroid Build Coastguard Worker             int len) {
128*e5436536SAndroid Build Coastguard Worker   INT i, j;
129*e5436536SAndroid Build Coastguard Worker   FIXP_DBL tmp;
130*e5436536SAndroid Build Coastguard Worker 
131*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((aacOutDataHeadroom - 1) >= -(MDCT_OUTPUT_SCALE));
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < stop; i++) {
134*e5436536SAndroid Build Coastguard Worker     tmp = fMultDiv2(noise[i], filt[0]);  // Filt in Q-1.16
135*e5436536SAndroid Build Coastguard Worker     for (j = 1; j <= len; j++) {
136*e5436536SAndroid Build Coastguard Worker       tmp += fMult((noise[i - j] >> 1) + (noise[i + j] >> 1), filt[j]);
137*e5436536SAndroid Build Coastguard Worker     }
138*e5436536SAndroid Build Coastguard Worker     syn_out[i] = (PCM_DEC)(
139*e5436536SAndroid Build Coastguard Worker         IMDCT_SCALE((syn[i] >> 1) - (tmp >> 1), aacOutDataHeadroom - 1));
140*e5436536SAndroid Build Coastguard Worker   }
141*e5436536SAndroid Build Coastguard Worker }
142*e5436536SAndroid Build Coastguard Worker 
bass_pf_1sf_delay(FIXP_DBL * syn,const INT * T_sf,FIXP_DBL * pit_gain,const int frame_length,const INT l_frame,const INT l_next,PCM_DEC * synth_out,const INT aacOutDataHeadroom,FIXP_DBL mem_bpf[])143*e5436536SAndroid Build Coastguard Worker void bass_pf_1sf_delay(
144*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *syn,   /* (i) : 12.8kHz synthesis to postfilter              */
145*e5436536SAndroid Build Coastguard Worker     const INT *T_sf, /* (i) : Pitch period for all subframes (T_sf[16])    */
146*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *pit_gain,
147*e5436536SAndroid Build Coastguard Worker     const int frame_length, /* (i) : frame length (should be 768|1024) */
148*e5436536SAndroid Build Coastguard Worker     const INT l_frame,
149*e5436536SAndroid Build Coastguard Worker     const INT l_next,   /* (i) : look ahead for symmetric filtering           */
150*e5436536SAndroid Build Coastguard Worker     PCM_DEC *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr)   */
151*e5436536SAndroid Build Coastguard Worker     const INT aacOutDataHeadroom, /* (i) : headroom of the output time signal to
152*e5436536SAndroid Build Coastguard Worker                                      prevent clipping */
153*e5436536SAndroid Build Coastguard Worker     FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR]                */
154*e5436536SAndroid Build Coastguard Worker {
155*e5436536SAndroid Build Coastguard Worker   INT i, sf, i_subfr, T, T2, lg;
156*e5436536SAndroid Build Coastguard Worker 
157*e5436536SAndroid Build Coastguard Worker   FIXP_DBL tmp, ener, corr, gain;
158*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *noise, *noise_in;
159*e5436536SAndroid Build Coastguard Worker   FIXP_DBL
160*e5436536SAndroid Build Coastguard Worker   noise_buf[L_FILT + (2 * L_SUBFR)];  // L_FILT = 12, L_SUBFR = 64 => 140
161*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL *x, *y;
162*e5436536SAndroid Build Coastguard Worker 
163*e5436536SAndroid Build Coastguard Worker   {
164*e5436536SAndroid Build Coastguard Worker     noise = noise_buf + L_FILT;  // L_FILT = 12 delay of upsampling filter
165*e5436536SAndroid Build Coastguard Worker     noise_in = noise_buf + L_FILT + L_SUBFR;
166*e5436536SAndroid Build Coastguard Worker     /* Input scaling of the BPF memory */
167*e5436536SAndroid Build Coastguard Worker     scaleValues(mem_bpf, (L_FILT + L_SUBFR), 1);
168*e5436536SAndroid Build Coastguard Worker   }
169*e5436536SAndroid Build Coastguard Worker 
170*e5436536SAndroid Build Coastguard Worker   int gain_exp = 17;
171*e5436536SAndroid Build Coastguard Worker 
172*e5436536SAndroid Build Coastguard Worker   sf = 0;
173*e5436536SAndroid Build Coastguard Worker   for (i_subfr = 0; i_subfr < l_frame; i_subfr += L_SUBFR, sf++) {
174*e5436536SAndroid Build Coastguard Worker     T = T_sf[sf];
175*e5436536SAndroid Build Coastguard Worker     gain = pit_gain[sf];
176*e5436536SAndroid Build Coastguard Worker 
177*e5436536SAndroid Build Coastguard Worker     /* Gain is in Q17.14 */
178*e5436536SAndroid Build Coastguard Worker     /* If gain > 1 set to 1 */
179*e5436536SAndroid Build Coastguard Worker     if (gain > (FIXP_DBL)(1 << 14)) gain = (FIXP_DBL)(1 << 14);
180*e5436536SAndroid Build Coastguard Worker 
181*e5436536SAndroid Build Coastguard Worker     /* If gain < 0 set to 0 */
182*e5436536SAndroid Build Coastguard Worker     if (gain < (FIXP_DBL)0) gain = (FIXP_DBL)0;
183*e5436536SAndroid Build Coastguard Worker 
184*e5436536SAndroid Build Coastguard Worker     if (gain > (FIXP_DBL)0) {
185*e5436536SAndroid Build Coastguard Worker       /* pitch tracker: test pitch/2 to avoid continuous pitch doubling */
186*e5436536SAndroid Build Coastguard Worker       /* Note: pitch is limited to PIT_MIN (34 = 376Hz) at the encoder  */
187*e5436536SAndroid Build Coastguard Worker       T2 = T >> 1;
188*e5436536SAndroid Build Coastguard Worker       x = &syn[i_subfr - L_EXTRA];
189*e5436536SAndroid Build Coastguard Worker       y = &syn[i_subfr - T2 - L_EXTRA];
190*e5436536SAndroid Build Coastguard Worker 
191*e5436536SAndroid Build Coastguard Worker       ener = (FIXP_DBL)0;
192*e5436536SAndroid Build Coastguard Worker       corr = (FIXP_DBL)0;
193*e5436536SAndroid Build Coastguard Worker       tmp = (FIXP_DBL)0;
194*e5436536SAndroid Build Coastguard Worker 
195*e5436536SAndroid Build Coastguard Worker       int headroom_x = getScalefactor(x, L_SUBFR + L_EXTRA);
196*e5436536SAndroid Build Coastguard Worker       int headroom_y = getScalefactor(y, L_SUBFR + L_EXTRA);
197*e5436536SAndroid Build Coastguard Worker 
198*e5436536SAndroid Build Coastguard Worker       int width_shift = 7;
199*e5436536SAndroid Build Coastguard Worker 
200*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < (L_SUBFR + L_EXTRA); i++) {
201*e5436536SAndroid Build Coastguard Worker         ener += fPow2Div2((x[i] << headroom_x)) >> width_shift;
202*e5436536SAndroid Build Coastguard Worker         corr += fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >>
203*e5436536SAndroid Build Coastguard Worker                 width_shift;
204*e5436536SAndroid Build Coastguard Worker         tmp += fPow2Div2((y[i] << headroom_y)) >> width_shift;
205*e5436536SAndroid Build Coastguard Worker       }
206*e5436536SAndroid Build Coastguard Worker 
207*e5436536SAndroid Build Coastguard Worker       int exp_ener = ((17 - headroom_x) << 1) + width_shift + 1;
208*e5436536SAndroid Build Coastguard Worker       int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1;
209*e5436536SAndroid Build Coastguard Worker       int exp_tmp = ((17 - headroom_y) << 1) + width_shift + 1;
210*e5436536SAndroid Build Coastguard Worker 
211*e5436536SAndroid Build Coastguard Worker       /* Add 0.01 to "ener". Adjust exponents */
212*e5436536SAndroid Build Coastguard Worker       FIXP_DBL point_zero_one = (FIXP_DBL)0x51eb851f; /* In Q-6.37 */
213*e5436536SAndroid Build Coastguard Worker       int diff;
214*e5436536SAndroid Build Coastguard Worker       ener = fAddNorm(ener, exp_ener, point_zero_one, -6, &exp_ener);
215*e5436536SAndroid Build Coastguard Worker       corr = fAddNorm(corr, exp_corr, point_zero_one, -6, &exp_corr);
216*e5436536SAndroid Build Coastguard Worker       tmp = fAddNorm(tmp, exp_tmp, point_zero_one, -6, &exp_tmp);
217*e5436536SAndroid Build Coastguard Worker 
218*e5436536SAndroid Build Coastguard Worker       /* use T2 if normalized correlation > 0.95 */
219*e5436536SAndroid Build Coastguard Worker       INT s1, s2;
220*e5436536SAndroid Build Coastguard Worker       s1 = CntLeadingZeros(ener) - 1;
221*e5436536SAndroid Build Coastguard Worker       s2 = CntLeadingZeros(tmp) - 1;
222*e5436536SAndroid Build Coastguard Worker 
223*e5436536SAndroid Build Coastguard Worker       FIXP_DBL ener_by_tmp = fMultDiv2(ener << s1, tmp << s2);
224*e5436536SAndroid Build Coastguard Worker       int ener_by_tmp_exp = (exp_ener - s1) + (exp_tmp - s2) + 1;
225*e5436536SAndroid Build Coastguard Worker 
226*e5436536SAndroid Build Coastguard Worker       if (ener_by_tmp_exp & 1) {
227*e5436536SAndroid Build Coastguard Worker         ener_by_tmp <<= 1;
228*e5436536SAndroid Build Coastguard Worker         ener_by_tmp_exp -= 1;
229*e5436536SAndroid Build Coastguard Worker       }
230*e5436536SAndroid Build Coastguard Worker 
231*e5436536SAndroid Build Coastguard Worker       int temp_exp = 0;
232*e5436536SAndroid Build Coastguard Worker 
233*e5436536SAndroid Build Coastguard Worker       FIXP_DBL temp1 = invSqrtNorm2(ener_by_tmp, &temp_exp);
234*e5436536SAndroid Build Coastguard Worker 
235*e5436536SAndroid Build Coastguard Worker       int temp1_exp = temp_exp - (ener_by_tmp_exp >> 1);
236*e5436536SAndroid Build Coastguard Worker 
237*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp_result = fMult(corr, temp1);
238*e5436536SAndroid Build Coastguard Worker 
239*e5436536SAndroid Build Coastguard Worker       int tmp_result_exp = exp_corr + temp1_exp;
240*e5436536SAndroid Build Coastguard Worker 
241*e5436536SAndroid Build Coastguard Worker       diff = tmp_result_exp - 0;
242*e5436536SAndroid Build Coastguard Worker       FIXP_DBL point95 = FL2FXCONST_DBL(0.95f);
243*e5436536SAndroid Build Coastguard Worker       if (diff >= 0) {
244*e5436536SAndroid Build Coastguard Worker         diff = fMin(diff, 31);
245*e5436536SAndroid Build Coastguard Worker         point95 = FL2FXCONST_DBL(0.95f) >> diff;
246*e5436536SAndroid Build Coastguard Worker       } else {
247*e5436536SAndroid Build Coastguard Worker         diff = fMax(diff, -31);
248*e5436536SAndroid Build Coastguard Worker         tmp_result >>= (-diff);
249*e5436536SAndroid Build Coastguard Worker       }
250*e5436536SAndroid Build Coastguard Worker 
251*e5436536SAndroid Build Coastguard Worker       if (tmp_result > point95) T = T2;
252*e5436536SAndroid Build Coastguard Worker 
253*e5436536SAndroid Build Coastguard Worker       /* prevent that noise calculation below reaches into not defined signal
254*e5436536SAndroid Build Coastguard Worker          parts at the end of the synth_buf or in other words restrict the below
255*e5436536SAndroid Build Coastguard Worker          used index (i+i_subfr+T) < l_frame + l_next
256*e5436536SAndroid Build Coastguard Worker       */
257*e5436536SAndroid Build Coastguard Worker       lg = l_frame + l_next - T - i_subfr;
258*e5436536SAndroid Build Coastguard Worker 
259*e5436536SAndroid Build Coastguard Worker       if (lg > L_SUBFR)
260*e5436536SAndroid Build Coastguard Worker         lg = L_SUBFR;
261*e5436536SAndroid Build Coastguard Worker       else if (lg < 0)
262*e5436536SAndroid Build Coastguard Worker         lg = 0;
263*e5436536SAndroid Build Coastguard Worker 
264*e5436536SAndroid Build Coastguard Worker       /* limit gain to avoid problem on burst */
265*e5436536SAndroid Build Coastguard Worker       if (lg > 0) {
266*e5436536SAndroid Build Coastguard Worker         FIXP_DBL tmp1;
267*e5436536SAndroid Build Coastguard Worker 
268*e5436536SAndroid Build Coastguard Worker         /* max(lg) = 64 => scale with 6 bits minus 1 (fPow2Div2) */
269*e5436536SAndroid Build Coastguard Worker 
270*e5436536SAndroid Build Coastguard Worker         s1 = getScalefactor(&syn[i_subfr], lg);
271*e5436536SAndroid Build Coastguard Worker         s2 = getScalefactor(&syn[i_subfr + T], lg);
272*e5436536SAndroid Build Coastguard Worker         INT s = fixMin(s1, s2);
273*e5436536SAndroid Build Coastguard Worker 
274*e5436536SAndroid Build Coastguard Worker         tmp = (FIXP_DBL)0;
275*e5436536SAndroid Build Coastguard Worker         ener = (FIXP_DBL)0;
276*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < lg; i++) {
277*e5436536SAndroid Build Coastguard Worker           tmp += fPow2Div2(syn[i + i_subfr] << s1) >> (SF_PITCH_TRACK);
278*e5436536SAndroid Build Coastguard Worker           ener += fPow2Div2(syn[i + i_subfr + T] << s2) >> (SF_PITCH_TRACK);
279*e5436536SAndroid Build Coastguard Worker         }
280*e5436536SAndroid Build Coastguard Worker         tmp = tmp >> fMin(DFRACT_BITS - 1, (2 * (s1 - s)));
281*e5436536SAndroid Build Coastguard Worker         ener = ener >> fMin(DFRACT_BITS - 1, (2 * (s2 - s)));
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker         /* error robustness: for the specific case syn[...] == -1.0f for all 64
284*e5436536SAndroid Build Coastguard Worker            samples ener or tmp might overflow and become negative. For all sane
285*e5436536SAndroid Build Coastguard Worker            cases we have enough headroom.
286*e5436536SAndroid Build Coastguard Worker         */
287*e5436536SAndroid Build Coastguard Worker         if (ener <= (FIXP_DBL)0) {
288*e5436536SAndroid Build Coastguard Worker           ener = (FIXP_DBL)1;
289*e5436536SAndroid Build Coastguard Worker         }
290*e5436536SAndroid Build Coastguard Worker         if (tmp <= (FIXP_DBL)0) {
291*e5436536SAndroid Build Coastguard Worker           tmp = (FIXP_DBL)1;
292*e5436536SAndroid Build Coastguard Worker         }
293*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(ener > (FIXP_DBL)0);
294*e5436536SAndroid Build Coastguard Worker 
295*e5436536SAndroid Build Coastguard Worker         /* tmp = sqrt(tmp/ener) */
296*e5436536SAndroid Build Coastguard Worker         int result_e = 0;
297*e5436536SAndroid Build Coastguard Worker         tmp1 = fDivNorm(tmp, ener, &result_e);
298*e5436536SAndroid Build Coastguard Worker         if (result_e & 1) {
299*e5436536SAndroid Build Coastguard Worker           tmp1 >>= 1;
300*e5436536SAndroid Build Coastguard Worker           result_e += 1;
301*e5436536SAndroid Build Coastguard Worker         }
302*e5436536SAndroid Build Coastguard Worker         tmp = sqrtFixp(tmp1);
303*e5436536SAndroid Build Coastguard Worker         result_e >>= 1;
304*e5436536SAndroid Build Coastguard Worker 
305*e5436536SAndroid Build Coastguard Worker         gain_exp = 17;
306*e5436536SAndroid Build Coastguard Worker 
307*e5436536SAndroid Build Coastguard Worker         diff = result_e - gain_exp;
308*e5436536SAndroid Build Coastguard Worker 
309*e5436536SAndroid Build Coastguard Worker         FIXP_DBL gain1 = gain;
310*e5436536SAndroid Build Coastguard Worker 
311*e5436536SAndroid Build Coastguard Worker         if (diff >= 0) {
312*e5436536SAndroid Build Coastguard Worker           diff = fMin(diff, 31);
313*e5436536SAndroid Build Coastguard Worker           gain1 >>= diff;
314*e5436536SAndroid Build Coastguard Worker         } else {
315*e5436536SAndroid Build Coastguard Worker           result_e += (-diff);
316*e5436536SAndroid Build Coastguard Worker           diff = fMax(diff, -31);
317*e5436536SAndroid Build Coastguard Worker           tmp >>= (-diff);
318*e5436536SAndroid Build Coastguard Worker         }
319*e5436536SAndroid Build Coastguard Worker 
320*e5436536SAndroid Build Coastguard Worker         if (tmp < gain1) {
321*e5436536SAndroid Build Coastguard Worker           gain = tmp;
322*e5436536SAndroid Build Coastguard Worker           gain_exp = result_e;
323*e5436536SAndroid Build Coastguard Worker         }
324*e5436536SAndroid Build Coastguard Worker       }
325*e5436536SAndroid Build Coastguard Worker 
326*e5436536SAndroid Build Coastguard Worker       /* calculate noise based on voiced pitch */
327*e5436536SAndroid Build Coastguard Worker       /* fMultDiv2() replaces weighting of gain with 0.5 */
328*e5436536SAndroid Build Coastguard Worker       diff = gain_exp - 17;
329*e5436536SAndroid Build Coastguard Worker       if (diff >= 0) {
330*e5436536SAndroid Build Coastguard Worker         gain <<= diff;
331*e5436536SAndroid Build Coastguard Worker       } else {
332*e5436536SAndroid Build Coastguard Worker         gain >>= (-diff);
333*e5436536SAndroid Build Coastguard Worker       }
334*e5436536SAndroid Build Coastguard Worker 
335*e5436536SAndroid Build Coastguard Worker       s1 = CntLeadingZeros(gain) - 1;
336*e5436536SAndroid Build Coastguard Worker       s1 -= 16; /* Leading bits for SGL */
337*e5436536SAndroid Build Coastguard Worker 
338*e5436536SAndroid Build Coastguard Worker       FIXP_SGL gainSGL = FX_DBL2FX_SGL(gain << 16);
339*e5436536SAndroid Build Coastguard Worker 
340*e5436536SAndroid Build Coastguard Worker       gainSGL = gainSGL << s1;
341*e5436536SAndroid Build Coastguard Worker 
342*e5436536SAndroid Build Coastguard Worker       {
343*e5436536SAndroid Build Coastguard Worker         for (i = 0; i < lg; i++) {
344*e5436536SAndroid Build Coastguard Worker           /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2:
345*e5436536SAndroid Build Coastguard Worker            * one additional shift of syn values + fMult => fMultDiv2 */
346*e5436536SAndroid Build Coastguard Worker           noise_in[i] =
347*e5436536SAndroid Build Coastguard Worker               scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) -
348*e5436536SAndroid Build Coastguard Worker                                                 (syn[i + i_subfr - T] >> 2) -
349*e5436536SAndroid Build Coastguard Worker                                                 (syn[i + i_subfr + T] >> 2)),
350*e5436536SAndroid Build Coastguard Worker                          2 - s1);
351*e5436536SAndroid Build Coastguard Worker         }
352*e5436536SAndroid Build Coastguard Worker 
353*e5436536SAndroid Build Coastguard Worker         for (i = lg; i < L_SUBFR; i++) {
354*e5436536SAndroid Build Coastguard Worker           /* scaled with SF_SYNTH + gain_sf + 1; composition of scalefactor 2:
355*e5436536SAndroid Build Coastguard Worker            * one additional shift of syn values + fMult => fMultDiv2 */
356*e5436536SAndroid Build Coastguard Worker           noise_in[i] =
357*e5436536SAndroid Build Coastguard Worker               scaleValue(fMultDiv2(gainSGL, (syn[i + i_subfr] >> 1) -
358*e5436536SAndroid Build Coastguard Worker                                                 (syn[i + i_subfr - T] >> 1)),
359*e5436536SAndroid Build Coastguard Worker                          2 - s1);
360*e5436536SAndroid Build Coastguard Worker         }
361*e5436536SAndroid Build Coastguard Worker       }
362*e5436536SAndroid Build Coastguard Worker     } else {
363*e5436536SAndroid Build Coastguard Worker       FDKmemset(noise_in, (FIXP_DBL)0, L_SUBFR * sizeof(FIXP_DBL));
364*e5436536SAndroid Build Coastguard Worker     }
365*e5436536SAndroid Build Coastguard Worker 
366*e5436536SAndroid Build Coastguard Worker     {
367*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(noise_buf, mem_bpf, (L_FILT + L_SUBFR) * sizeof(FIXP_DBL));
368*e5436536SAndroid Build Coastguard Worker 
369*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(mem_bpf, noise_buf + L_SUBFR,
370*e5436536SAndroid Build Coastguard Worker                 (L_FILT + L_SUBFR) * sizeof(FIXP_DBL));
371*e5436536SAndroid Build Coastguard Worker     }
372*e5436536SAndroid Build Coastguard Worker 
373*e5436536SAndroid Build Coastguard Worker     /* substract from voiced speech low-pass filtered noise */
374*e5436536SAndroid Build Coastguard Worker     /* filter coefficients are scaled with factor SF_FILT_LP (1) */
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker     {
377*e5436536SAndroid Build Coastguard Worker       filtLP(&syn[i_subfr - L_SUBFR], &synth_out[i_subfr], noise,
378*e5436536SAndroid Build Coastguard Worker              fdk_dec_filt_lp, aacOutDataHeadroom, L_SUBFR, L_FILT);
379*e5436536SAndroid Build Coastguard Worker     }
380*e5436536SAndroid Build Coastguard Worker   }
381*e5436536SAndroid Build Coastguard Worker 
382*e5436536SAndroid Build Coastguard Worker   {
383*e5436536SAndroid Build Coastguard Worker 
384*e5436536SAndroid Build Coastguard Worker   }
385*e5436536SAndroid Build Coastguard Worker 
386*e5436536SAndroid Build Coastguard Worker   // To be determined (info from Ben)
387*e5436536SAndroid Build Coastguard Worker   {
388*e5436536SAndroid Build Coastguard Worker     /* Output scaling of the BPF memory */
389*e5436536SAndroid Build Coastguard Worker     scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1);
390*e5436536SAndroid Build Coastguard Worker     /* Copy the rest of the signal (after the fac) */
391*e5436536SAndroid Build Coastguard Worker     scaleValuesSaturate(
392*e5436536SAndroid Build Coastguard Worker         (PCM_DEC *)&synth_out[l_frame], (FIXP_DBL *)&syn[l_frame - L_SUBFR],
393*e5436536SAndroid Build Coastguard Worker         (frame_length - l_frame), MDCT_OUT_HEADROOM - aacOutDataHeadroom);
394*e5436536SAndroid Build Coastguard Worker   }
395*e5436536SAndroid Build Coastguard Worker 
396*e5436536SAndroid Build Coastguard Worker   return;
397*e5436536SAndroid Build Coastguard Worker }
398*e5436536SAndroid Build Coastguard Worker 
399*e5436536SAndroid Build Coastguard Worker /*
400*e5436536SAndroid Build Coastguard Worker  * Frequency Domain Noise Shaping
401*e5436536SAndroid Build Coastguard Worker  */
402*e5436536SAndroid Build Coastguard Worker 
403*e5436536SAndroid Build Coastguard Worker /**
404*e5436536SAndroid Build Coastguard Worker  * \brief Adaptive Low Frequencies Deemphasis of spectral coefficients.
405*e5436536SAndroid Build Coastguard Worker  *
406*e5436536SAndroid Build Coastguard Worker  * Ensure quantization of low frequencies in case where the
407*e5436536SAndroid Build Coastguard Worker  * signal dynamic is higher than the LPC noise shaping.
408*e5436536SAndroid Build Coastguard Worker  * This is the inverse operation of adap_low_freq_emph().
409*e5436536SAndroid Build Coastguard Worker  * Output gain of all blocks.
410*e5436536SAndroid Build Coastguard Worker  *
411*e5436536SAndroid Build Coastguard Worker  * \param x pointer to the spectral coefficients, requires 1 bit headroom.
412*e5436536SAndroid Build Coastguard Worker  * \param lg length of x.
413*e5436536SAndroid Build Coastguard Worker  * \param bUseNewAlfe if set, apply ALFD for fullband lpd.
414*e5436536SAndroid Build Coastguard Worker  * \param gainLpc1 pointer to gain based on old input LPC coefficients.
415*e5436536SAndroid Build Coastguard Worker  * \param gainLpc2 pointer to gain based on new input LPC coefficients.
416*e5436536SAndroid Build Coastguard Worker  * \param alfd_gains pointer to output gains.
417*e5436536SAndroid Build Coastguard Worker  * \param s current scale shift factor of x.
418*e5436536SAndroid Build Coastguard Worker  */
419*e5436536SAndroid Build Coastguard Worker #define ALFDPOW2_SCALE 3
420*e5436536SAndroid Build Coastguard Worker /*static*/
CLpd_AdaptLowFreqDeemph(FIXP_DBL x[],int lg,FIXP_DBL alfd_gains[],INT s)421*e5436536SAndroid Build Coastguard Worker void CLpd_AdaptLowFreqDeemph(FIXP_DBL x[], int lg, FIXP_DBL alfd_gains[],
422*e5436536SAndroid Build Coastguard Worker                              INT s) {
423*e5436536SAndroid Build Coastguard Worker   {
424*e5436536SAndroid Build Coastguard Worker     int i, j, k, i_max;
425*e5436536SAndroid Build Coastguard Worker     FIXP_DBL max, fac;
426*e5436536SAndroid Build Coastguard Worker     /* Note: This stack array saves temporary accumulation results to be used in
427*e5436536SAndroid Build Coastguard Worker      * a second run */
428*e5436536SAndroid Build Coastguard Worker     /*       The size should be limited to (1024/4)/8=32 */
429*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp_pow2[32];
430*e5436536SAndroid Build Coastguard Worker 
431*e5436536SAndroid Build Coastguard Worker     s = s * 2 + ALFDPOW2_SCALE;
432*e5436536SAndroid Build Coastguard Worker     s = fMin(31, s);
433*e5436536SAndroid Build Coastguard Worker 
434*e5436536SAndroid Build Coastguard Worker     k = 8;
435*e5436536SAndroid Build Coastguard Worker     i_max = lg / 4; /* ALFD range = 1600Hz (lg = 6400Hz) */
436*e5436536SAndroid Build Coastguard Worker 
437*e5436536SAndroid Build Coastguard Worker     /* find spectral peak */
438*e5436536SAndroid Build Coastguard Worker     max = FL2FX_DBL(0.01f) >> s;
439*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < i_max; i += k) {
440*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp;
441*e5436536SAndroid Build Coastguard Worker 
442*e5436536SAndroid Build Coastguard Worker       tmp = FIXP_DBL(0);
443*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pX = &x[i];
444*e5436536SAndroid Build Coastguard Worker 
445*e5436536SAndroid Build Coastguard Worker       j = 8;
446*e5436536SAndroid Build Coastguard Worker       do {
447*e5436536SAndroid Build Coastguard Worker         FIXP_DBL x0 = *pX++;
448*e5436536SAndroid Build Coastguard Worker         FIXP_DBL x1 = *pX++;
449*e5436536SAndroid Build Coastguard Worker         x0 = fPow2Div2(x0);
450*e5436536SAndroid Build Coastguard Worker         x1 = fPow2Div2(x1);
451*e5436536SAndroid Build Coastguard Worker         tmp = tmp + (x0 >> (ALFDPOW2_SCALE - 1));
452*e5436536SAndroid Build Coastguard Worker         tmp = tmp + (x1 >> (ALFDPOW2_SCALE - 1));
453*e5436536SAndroid Build Coastguard Worker       } while ((j = j - 2) != 0);
454*e5436536SAndroid Build Coastguard Worker       tmp = fMax(tmp, (FL2FX_DBL(0.01f) >> s));
455*e5436536SAndroid Build Coastguard Worker       tmp_pow2[i >> 3] = tmp;
456*e5436536SAndroid Build Coastguard Worker       if (tmp > max) {
457*e5436536SAndroid Build Coastguard Worker         max = tmp;
458*e5436536SAndroid Build Coastguard Worker       }
459*e5436536SAndroid Build Coastguard Worker     }
460*e5436536SAndroid Build Coastguard Worker 
461*e5436536SAndroid Build Coastguard Worker     /* deemphasis of all blocks below the peak */
462*e5436536SAndroid Build Coastguard Worker     fac = FL2FX_DBL(0.1f) >> 1;
463*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < i_max; i += k) {
464*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp;
465*e5436536SAndroid Build Coastguard Worker       INT shifti;
466*e5436536SAndroid Build Coastguard Worker 
467*e5436536SAndroid Build Coastguard Worker       tmp = tmp_pow2[i >> 3];
468*e5436536SAndroid Build Coastguard Worker 
469*e5436536SAndroid Build Coastguard Worker       /* tmp = (float)sqrt(tmp/max); */
470*e5436536SAndroid Build Coastguard Worker 
471*e5436536SAndroid Build Coastguard Worker       /* value of tmp is between 8/2*max^2 and max^2 / 2. */
472*e5436536SAndroid Build Coastguard Worker       /* required shift factor of division can grow up to 27
473*e5436536SAndroid Build Coastguard Worker          (grows exponentially for values toward zero)
474*e5436536SAndroid Build Coastguard Worker          thus using normalized division to assure valid result. */
475*e5436536SAndroid Build Coastguard Worker       {
476*e5436536SAndroid Build Coastguard Worker         INT sd;
477*e5436536SAndroid Build Coastguard Worker 
478*e5436536SAndroid Build Coastguard Worker         if (tmp != (FIXP_DBL)0) {
479*e5436536SAndroid Build Coastguard Worker           tmp = fDivNorm(max, tmp, &sd);
480*e5436536SAndroid Build Coastguard Worker           if (sd & 1) {
481*e5436536SAndroid Build Coastguard Worker             sd++;
482*e5436536SAndroid Build Coastguard Worker             tmp >>= 1;
483*e5436536SAndroid Build Coastguard Worker           }
484*e5436536SAndroid Build Coastguard Worker         } else {
485*e5436536SAndroid Build Coastguard Worker           tmp = (FIXP_DBL)MAXVAL_DBL;
486*e5436536SAndroid Build Coastguard Worker           sd = 0;
487*e5436536SAndroid Build Coastguard Worker         }
488*e5436536SAndroid Build Coastguard Worker         tmp = invSqrtNorm2(tmp, &shifti);
489*e5436536SAndroid Build Coastguard Worker         tmp = scaleValue(tmp, shifti - 1 - (sd / 2));
490*e5436536SAndroid Build Coastguard Worker       }
491*e5436536SAndroid Build Coastguard Worker       if (tmp > fac) {
492*e5436536SAndroid Build Coastguard Worker         fac = tmp;
493*e5436536SAndroid Build Coastguard Worker       }
494*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *pX = &x[i];
495*e5436536SAndroid Build Coastguard Worker 
496*e5436536SAndroid Build Coastguard Worker       j = 8;
497*e5436536SAndroid Build Coastguard Worker       do {
498*e5436536SAndroid Build Coastguard Worker         FIXP_DBL x0 = pX[0];
499*e5436536SAndroid Build Coastguard Worker         FIXP_DBL x1 = pX[1];
500*e5436536SAndroid Build Coastguard Worker         x0 = fMultDiv2(x0, fac);
501*e5436536SAndroid Build Coastguard Worker         x1 = fMultDiv2(x1, fac);
502*e5436536SAndroid Build Coastguard Worker         x0 = x0 << 2;
503*e5436536SAndroid Build Coastguard Worker         x1 = x1 << 2;
504*e5436536SAndroid Build Coastguard Worker         *pX++ = x0;
505*e5436536SAndroid Build Coastguard Worker         *pX++ = x1;
506*e5436536SAndroid Build Coastguard Worker 
507*e5436536SAndroid Build Coastguard Worker       } while ((j = j - 2) != 0);
508*e5436536SAndroid Build Coastguard Worker       /* Store gains for FAC */
509*e5436536SAndroid Build Coastguard Worker       *alfd_gains++ = fac;
510*e5436536SAndroid Build Coastguard Worker     }
511*e5436536SAndroid Build Coastguard Worker   }
512*e5436536SAndroid Build Coastguard Worker }
513*e5436536SAndroid Build Coastguard Worker 
514*e5436536SAndroid Build Coastguard Worker /**
515*e5436536SAndroid Build Coastguard Worker  * \brief Interpolated Noise Shaping for mdct coefficients.
516*e5436536SAndroid Build Coastguard Worker  * This algorithm shapes temporally the spectral noise between
517*e5436536SAndroid Build Coastguard Worker  * the two spectral noise represention (FDNS_NPTS of resolution).
518*e5436536SAndroid Build Coastguard Worker  * The noise is shaped monotonically between the two points
519*e5436536SAndroid Build Coastguard Worker  * using a curved shape to favor the lower gain in mid-frame.
520*e5436536SAndroid Build Coastguard Worker  * ODFT and amplitud calculation are applied to the 2 LPC coefficients first.
521*e5436536SAndroid Build Coastguard Worker  *
522*e5436536SAndroid Build Coastguard Worker  * \param r pointer to spectrum data.
523*e5436536SAndroid Build Coastguard Worker  * \param rms RMS of output spectrum.
524*e5436536SAndroid Build Coastguard Worker  * \param lg length of r.
525*e5436536SAndroid Build Coastguard Worker  * \param A1 pointer to old input LPC coefficients of length M_LP_FILTER_ORDER
526*e5436536SAndroid Build Coastguard Worker  * scaled by SF_A_COEFFS.
527*e5436536SAndroid Build Coastguard Worker  * \param A2 pointer to new input LPC coefficients of length M_LP_FILTER_ORDER
528*e5436536SAndroid Build Coastguard Worker  * scaled by SF_A_COEFFS.
529*e5436536SAndroid Build Coastguard Worker  * \param bLpc2Mdct flags control lpc2mdct conversion and noise shaping.
530*e5436536SAndroid Build Coastguard Worker  * \param gainLpc1 pointer to gain based on old input LPC coefficients.
531*e5436536SAndroid Build Coastguard Worker  * \param gainLpc2 pointer to gain based on new input LPC coefficients.
532*e5436536SAndroid Build Coastguard Worker  * \param gLpc_e pointer to exponent of gainLpc1 and gainLpc2.
533*e5436536SAndroid Build Coastguard Worker  */
534*e5436536SAndroid Build Coastguard Worker /* static */
535*e5436536SAndroid Build Coastguard Worker #define NSHAPE_SCALE (4)
536*e5436536SAndroid Build Coastguard Worker 
537*e5436536SAndroid Build Coastguard Worker #define LPC2MDCT_CALC (1)
538*e5436536SAndroid Build Coastguard Worker #define LPC2MDCT_GAIN_LOAD (2)
539*e5436536SAndroid Build Coastguard Worker #define LPC2MDCT_GAIN_SAVE (4)
540*e5436536SAndroid Build Coastguard Worker #define LPC2MDCT_APPLY_NSHAPE (8)
541*e5436536SAndroid Build Coastguard Worker 
lpc2mdctAndNoiseShaping(FIXP_DBL * r,SHORT * pScale,const INT lg,const INT fdns_npts,const FIXP_LPC * A1,const INT A1_exp,const FIXP_LPC * A2,const INT A2_exp)542*e5436536SAndroid Build Coastguard Worker void lpc2mdctAndNoiseShaping(FIXP_DBL *r, SHORT *pScale, const INT lg,
543*e5436536SAndroid Build Coastguard Worker                              const INT fdns_npts, const FIXP_LPC *A1,
544*e5436536SAndroid Build Coastguard Worker                              const INT A1_exp, const FIXP_LPC *A2,
545*e5436536SAndroid Build Coastguard Worker                              const INT A2_exp) {
546*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *tmp2 = NULL;
547*e5436536SAndroid Build Coastguard Worker   FIXP_DBL rr_minus_one;
548*e5436536SAndroid Build Coastguard Worker   int i, k, s, step;
549*e5436536SAndroid Build Coastguard Worker 
550*e5436536SAndroid Build Coastguard Worker   C_AALLOC_SCRATCH_START(tmp1, FIXP_DBL, FDNS_NPTS * 8)
551*e5436536SAndroid Build Coastguard Worker 
552*e5436536SAndroid Build Coastguard Worker   {
553*e5436536SAndroid Build Coastguard Worker     tmp2 = tmp1 + fdns_npts * 4;
554*e5436536SAndroid Build Coastguard Worker 
555*e5436536SAndroid Build Coastguard Worker     /* lpc2mdct() */
556*e5436536SAndroid Build Coastguard Worker 
557*e5436536SAndroid Build Coastguard Worker     /* ODFT. E_LPC_a_weight() for A1 and A2 vectors is included into the loop
558*e5436536SAndroid Build Coastguard Worker      * below. */
559*e5436536SAndroid Build Coastguard Worker     FIXP_DBL f = FL2FXCONST_DBL(0.92f);
560*e5436536SAndroid Build Coastguard Worker 
561*e5436536SAndroid Build Coastguard Worker     const FIXP_STP *SinTab;
562*e5436536SAndroid Build Coastguard Worker     int k_step;
563*e5436536SAndroid Build Coastguard Worker     /* needed values: sin(phi), cos(phi); phi = i*PI/(2*fdns_npts), i = 0 ...
564*e5436536SAndroid Build Coastguard Worker      * M_LP_FILTER_ORDER */
565*e5436536SAndroid Build Coastguard Worker     switch (fdns_npts) {
566*e5436536SAndroid Build Coastguard Worker       case 64:
567*e5436536SAndroid Build Coastguard Worker         SinTab = SineTable512;
568*e5436536SAndroid Build Coastguard Worker         k_step = (512 / 64);
569*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(512 >= 64);
570*e5436536SAndroid Build Coastguard Worker         break;
571*e5436536SAndroid Build Coastguard Worker       case 48:
572*e5436536SAndroid Build Coastguard Worker         SinTab = SineTable384;
573*e5436536SAndroid Build Coastguard Worker         k_step = 384 / 48;
574*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(384 >= 48);
575*e5436536SAndroid Build Coastguard Worker         break;
576*e5436536SAndroid Build Coastguard Worker       default:
577*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(0);
578*e5436536SAndroid Build Coastguard Worker         return;
579*e5436536SAndroid Build Coastguard Worker     }
580*e5436536SAndroid Build Coastguard Worker 
581*e5436536SAndroid Build Coastguard Worker     for (i = 0, k = k_step; i < M_LP_FILTER_ORDER; i++, k += k_step) {
582*e5436536SAndroid Build Coastguard Worker       FIXP_STP cs = SinTab[k];
583*e5436536SAndroid Build Coastguard Worker       FIXP_DBL wA1, wA2;
584*e5436536SAndroid Build Coastguard Worker 
585*e5436536SAndroid Build Coastguard Worker       wA1 = fMult(A1[i], f);
586*e5436536SAndroid Build Coastguard Worker       wA2 = fMult(A2[i], f);
587*e5436536SAndroid Build Coastguard Worker 
588*e5436536SAndroid Build Coastguard Worker       /* r[i] = A[i]*cos() */
589*e5436536SAndroid Build Coastguard Worker       tmp1[2 + i * 2] = fMult(wA1, cs.v.re);
590*e5436536SAndroid Build Coastguard Worker       tmp2[2 + i * 2] = fMult(wA2, cs.v.re);
591*e5436536SAndroid Build Coastguard Worker       /* i[i] = A[i]*sin() */
592*e5436536SAndroid Build Coastguard Worker       tmp1[3 + i * 2] = -fMult(wA1, cs.v.im);
593*e5436536SAndroid Build Coastguard Worker       tmp2[3 + i * 2] = -fMult(wA2, cs.v.im);
594*e5436536SAndroid Build Coastguard Worker 
595*e5436536SAndroid Build Coastguard Worker       f = fMult(f, FL2FXCONST_DBL(0.92f));
596*e5436536SAndroid Build Coastguard Worker     }
597*e5436536SAndroid Build Coastguard Worker 
598*e5436536SAndroid Build Coastguard Worker     /* Guarantee at least 2 bits of headroom for the FFT */
599*e5436536SAndroid Build Coastguard Worker     /* "3" stands for 1.0 with 2 bits of headroom; (A1_exp + 2) guarantess 2
600*e5436536SAndroid Build Coastguard Worker      * bits of headroom if A1_exp > 1 */
601*e5436536SAndroid Build Coastguard Worker     int A1_exp_fix = fMax(3, A1_exp + 2);
602*e5436536SAndroid Build Coastguard Worker     int A2_exp_fix = fMax(3, A2_exp + 2);
603*e5436536SAndroid Build Coastguard Worker 
604*e5436536SAndroid Build Coastguard Worker     /* Set 1.0 in the proper format */
605*e5436536SAndroid Build Coastguard Worker     tmp1[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A1_exp_fix);
606*e5436536SAndroid Build Coastguard Worker     tmp2[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A2_exp_fix);
607*e5436536SAndroid Build Coastguard Worker 
608*e5436536SAndroid Build Coastguard Worker     tmp1[1] = tmp2[1] = (FIXP_DBL)0;
609*e5436536SAndroid Build Coastguard Worker 
610*e5436536SAndroid Build Coastguard Worker     /* Clear the resto of the array */
611*e5436536SAndroid Build Coastguard Worker     FDKmemclear(
612*e5436536SAndroid Build Coastguard Worker         tmp1 + 2 * (M_LP_FILTER_ORDER + 1),
613*e5436536SAndroid Build Coastguard Worker         2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL));
614*e5436536SAndroid Build Coastguard Worker     FDKmemclear(
615*e5436536SAndroid Build Coastguard Worker         tmp2 + 2 * (M_LP_FILTER_ORDER + 1),
616*e5436536SAndroid Build Coastguard Worker         2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL));
617*e5436536SAndroid Build Coastguard Worker 
618*e5436536SAndroid Build Coastguard Worker     /* Guarantee 2 bits of headroom for FFT */
619*e5436536SAndroid Build Coastguard Worker     scaleValues(&tmp1[2], (2 * M_LP_FILTER_ORDER), (A1_exp - A1_exp_fix));
620*e5436536SAndroid Build Coastguard Worker     scaleValues(&tmp2[2], (2 * M_LP_FILTER_ORDER), (A2_exp - A2_exp_fix));
621*e5436536SAndroid Build Coastguard Worker 
622*e5436536SAndroid Build Coastguard Worker     INT s2;
623*e5436536SAndroid Build Coastguard Worker     s = A1_exp_fix;
624*e5436536SAndroid Build Coastguard Worker     s2 = A2_exp_fix;
625*e5436536SAndroid Build Coastguard Worker 
626*e5436536SAndroid Build Coastguard Worker     fft(2 * fdns_npts, tmp1, &s);
627*e5436536SAndroid Build Coastguard Worker     fft(2 * fdns_npts, tmp2, &s2);
628*e5436536SAndroid Build Coastguard Worker 
629*e5436536SAndroid Build Coastguard Worker     /* Adjust the exponents of both fft outputs if necessary*/
630*e5436536SAndroid Build Coastguard Worker     if (s > s2) {
631*e5436536SAndroid Build Coastguard Worker       scaleValues(tmp2, 2 * fdns_npts, s2 - s);
632*e5436536SAndroid Build Coastguard Worker       s2 = s;
633*e5436536SAndroid Build Coastguard Worker     } else if (s < s2) {
634*e5436536SAndroid Build Coastguard Worker       scaleValues(tmp1, 2 * fdns_npts, s - s2);
635*e5436536SAndroid Build Coastguard Worker       s = s2;
636*e5436536SAndroid Build Coastguard Worker     }
637*e5436536SAndroid Build Coastguard Worker 
638*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(s == s2);
639*e5436536SAndroid Build Coastguard Worker   }
640*e5436536SAndroid Build Coastguard Worker 
641*e5436536SAndroid Build Coastguard Worker   /* Get amplitude and apply gains */
642*e5436536SAndroid Build Coastguard Worker   step = lg / fdns_npts;
643*e5436536SAndroid Build Coastguard Worker   rr_minus_one = (FIXP_DBL)0;
644*e5436536SAndroid Build Coastguard Worker 
645*e5436536SAndroid Build Coastguard Worker   for (k = 0; k < fdns_npts; k++) {
646*e5436536SAndroid Build Coastguard Worker     FIXP_DBL g1, g2, inv_g1_g2, a, b;
647*e5436536SAndroid Build Coastguard Worker     INT inv_g1_g2_e;
648*e5436536SAndroid Build Coastguard Worker     int g_e, shift;
649*e5436536SAndroid Build Coastguard Worker 
650*e5436536SAndroid Build Coastguard Worker     {
651*e5436536SAndroid Build Coastguard Worker       FIXP_DBL real, imag;
652*e5436536SAndroid Build Coastguard Worker       int si1, si2, sInput;
653*e5436536SAndroid Build Coastguard Worker 
654*e5436536SAndroid Build Coastguard Worker       real = tmp1[k * 2];
655*e5436536SAndroid Build Coastguard Worker       imag = tmp1[k * 2 + 1];
656*e5436536SAndroid Build Coastguard Worker       sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0);
657*e5436536SAndroid Build Coastguard Worker       real <<= sInput;
658*e5436536SAndroid Build Coastguard Worker       imag <<= sInput;
659*e5436536SAndroid Build Coastguard Worker       /* g1_e = si1 - 2*s/2 */
660*e5436536SAndroid Build Coastguard Worker       g1 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si1);
661*e5436536SAndroid Build Coastguard Worker       si1 += sInput;
662*e5436536SAndroid Build Coastguard Worker 
663*e5436536SAndroid Build Coastguard Worker       real = tmp2[k * 2];
664*e5436536SAndroid Build Coastguard Worker       imag = tmp2[k * 2 + 1];
665*e5436536SAndroid Build Coastguard Worker       sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0);
666*e5436536SAndroid Build Coastguard Worker       real <<= sInput;
667*e5436536SAndroid Build Coastguard Worker       imag <<= sInput;
668*e5436536SAndroid Build Coastguard Worker       /* g2_e = si2 - 2*s/2 */
669*e5436536SAndroid Build Coastguard Worker       g2 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si2);
670*e5436536SAndroid Build Coastguard Worker       si2 += sInput;
671*e5436536SAndroid Build Coastguard Worker 
672*e5436536SAndroid Build Coastguard Worker       /* Pick a common scale factor for g1 and g2 */
673*e5436536SAndroid Build Coastguard Worker       if (si1 > si2) {
674*e5436536SAndroid Build Coastguard Worker         g2 >>= si1 - si2;
675*e5436536SAndroid Build Coastguard Worker         g_e = si1 - s;
676*e5436536SAndroid Build Coastguard Worker       } else {
677*e5436536SAndroid Build Coastguard Worker         g1 >>= si2 - si1;
678*e5436536SAndroid Build Coastguard Worker         g_e = si2 - s;
679*e5436536SAndroid Build Coastguard Worker       }
680*e5436536SAndroid Build Coastguard Worker     }
681*e5436536SAndroid Build Coastguard Worker 
682*e5436536SAndroid Build Coastguard Worker     /* end of lpc2mdct() */
683*e5436536SAndroid Build Coastguard Worker 
684*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(g1 >= (FIXP_DBL)0);
685*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(g2 >= (FIXP_DBL)0);
686*e5436536SAndroid Build Coastguard Worker 
687*e5436536SAndroid Build Coastguard Worker     /* mdct_IntNoiseShaping() */
688*e5436536SAndroid Build Coastguard Worker     {
689*e5436536SAndroid Build Coastguard Worker       /* inv_g1_g2 * 2^inv_g1_g2_e = 1/(g1+g2) */
690*e5436536SAndroid Build Coastguard Worker       inv_g1_g2 = (g1 >> 1) + (g2 >> 1);
691*e5436536SAndroid Build Coastguard Worker       if (inv_g1_g2 != (FIXP_DBL)0) {
692*e5436536SAndroid Build Coastguard Worker         inv_g1_g2 = fDivNorm(FL2FXCONST_DBL(0.5f), inv_g1_g2, &inv_g1_g2_e);
693*e5436536SAndroid Build Coastguard Worker         inv_g1_g2_e = inv_g1_g2_e - g_e;
694*e5436536SAndroid Build Coastguard Worker       } else {
695*e5436536SAndroid Build Coastguard Worker         inv_g1_g2 = (FIXP_DBL)MAXVAL_DBL;
696*e5436536SAndroid Build Coastguard Worker         inv_g1_g2_e = 0;
697*e5436536SAndroid Build Coastguard Worker       }
698*e5436536SAndroid Build Coastguard Worker 
699*e5436536SAndroid Build Coastguard Worker       if (g_e < 0) {
700*e5436536SAndroid Build Coastguard Worker         /* a_e = g_e + inv_g1_g2_e + 1 */
701*e5436536SAndroid Build Coastguard Worker         a = scaleValue(fMult(fMult(g1, g2), inv_g1_g2), g_e);
702*e5436536SAndroid Build Coastguard Worker         /* b_e = g_e + inv_g1_g2_e */
703*e5436536SAndroid Build Coastguard Worker         b = fMult(g2 - g1, inv_g1_g2);
704*e5436536SAndroid Build Coastguard Worker         shift = g_e + inv_g1_g2_e + 1 - NSHAPE_SCALE;
705*e5436536SAndroid Build Coastguard Worker       } else {
706*e5436536SAndroid Build Coastguard Worker         /* a_e = (g_e+g_e) + inv_g1_g2_e + 1 */
707*e5436536SAndroid Build Coastguard Worker         a = fMult(fMult(g1, g2), inv_g1_g2);
708*e5436536SAndroid Build Coastguard Worker         /* b_e = (g_e+g_e) + inv_g1_g2_e */
709*e5436536SAndroid Build Coastguard Worker         b = scaleValue(fMult(g2 - g1, inv_g1_g2), -g_e);
710*e5436536SAndroid Build Coastguard Worker         shift = (g_e + g_e) + inv_g1_g2_e + 1 - NSHAPE_SCALE;
711*e5436536SAndroid Build Coastguard Worker       }
712*e5436536SAndroid Build Coastguard Worker 
713*e5436536SAndroid Build Coastguard Worker       for (i = k * step; i < (k + 1) * step; i++) {
714*e5436536SAndroid Build Coastguard Worker         FIXP_DBL tmp;
715*e5436536SAndroid Build Coastguard Worker 
716*e5436536SAndroid Build Coastguard Worker         /* rr[i] = 2*a*r[i] + b*rr[i-1] */
717*e5436536SAndroid Build Coastguard Worker         tmp = fMult(a, r[i]);
718*e5436536SAndroid Build Coastguard Worker         tmp += scaleValue(fMultDiv2(b, rr_minus_one), NSHAPE_SCALE);
719*e5436536SAndroid Build Coastguard Worker         tmp = scaleValueSaturate(tmp, shift);
720*e5436536SAndroid Build Coastguard Worker         rr_minus_one = tmp;
721*e5436536SAndroid Build Coastguard Worker         r[i] = tmp;
722*e5436536SAndroid Build Coastguard Worker       }
723*e5436536SAndroid Build Coastguard Worker     }
724*e5436536SAndroid Build Coastguard Worker   }
725*e5436536SAndroid Build Coastguard Worker 
726*e5436536SAndroid Build Coastguard Worker   /* end of mdct_IntNoiseShaping() */
727*e5436536SAndroid Build Coastguard Worker   { *pScale += NSHAPE_SCALE; }
728*e5436536SAndroid Build Coastguard Worker 
729*e5436536SAndroid Build Coastguard Worker   C_AALLOC_SCRATCH_END(tmp1, FIXP_DBL, FDNS_NPTS * 8)
730*e5436536SAndroid Build Coastguard Worker }
731*e5436536SAndroid Build Coastguard Worker 
732*e5436536SAndroid Build Coastguard Worker /**
733*e5436536SAndroid Build Coastguard Worker  * \brief Calculates the energy.
734*e5436536SAndroid Build Coastguard Worker  * \param r pointer to spectrum.
735*e5436536SAndroid Build Coastguard Worker  * \param rs scale factor of spectrum r.
736*e5436536SAndroid Build Coastguard Worker  * \param lg frame length in audio samples.
737*e5436536SAndroid Build Coastguard Worker  * \param rms_e pointer to exponent of energy value.
738*e5436536SAndroid Build Coastguard Worker  * \return mantissa of energy value.
739*e5436536SAndroid Build Coastguard Worker  */
calcEnergy(const FIXP_DBL * r,const SHORT rs,const INT lg,INT * rms_e)740*e5436536SAndroid Build Coastguard Worker static FIXP_DBL calcEnergy(const FIXP_DBL *r, const SHORT rs, const INT lg,
741*e5436536SAndroid Build Coastguard Worker                            INT *rms_e) {
742*e5436536SAndroid Build Coastguard Worker   int headroom = getScalefactor(r, lg);
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker   FIXP_DBL rms_m = 0;
745*e5436536SAndroid Build Coastguard Worker 
746*e5436536SAndroid Build Coastguard Worker   /* Calculate number of growth bits due to addition */
747*e5436536SAndroid Build Coastguard Worker   INT shift = (INT)(fNormz((FIXP_DBL)lg));
748*e5436536SAndroid Build Coastguard Worker   shift = 31 - shift;
749*e5436536SAndroid Build Coastguard Worker 
750*e5436536SAndroid Build Coastguard Worker   /* Generate 1e-2 in Q-6.37 */
751*e5436536SAndroid Build Coastguard Worker   const FIXP_DBL value0_01 = 0x51eb851e;
752*e5436536SAndroid Build Coastguard Worker   const INT value0_01_exp = -6;
753*e5436536SAndroid Build Coastguard Worker 
754*e5436536SAndroid Build Coastguard Worker   /* Find the exponent of the resulting energy value */
755*e5436536SAndroid Build Coastguard Worker   *rms_e = ((rs - headroom) << 1) + shift + 1;
756*e5436536SAndroid Build Coastguard Worker 
757*e5436536SAndroid Build Coastguard Worker   INT delta = *rms_e - value0_01_exp;
758*e5436536SAndroid Build Coastguard Worker   if (delta > 0) {
759*e5436536SAndroid Build Coastguard Worker     /* Limit shift_to 31*/
760*e5436536SAndroid Build Coastguard Worker     delta = fMin(31, delta);
761*e5436536SAndroid Build Coastguard Worker     rms_m = value0_01 >> delta;
762*e5436536SAndroid Build Coastguard Worker   } else {
763*e5436536SAndroid Build Coastguard Worker     rms_m = value0_01;
764*e5436536SAndroid Build Coastguard Worker     *rms_e = value0_01_exp;
765*e5436536SAndroid Build Coastguard Worker     shift = shift - delta;
766*e5436536SAndroid Build Coastguard Worker     /* Limit shift_to 31*/
767*e5436536SAndroid Build Coastguard Worker     shift = fMin(31, shift);
768*e5436536SAndroid Build Coastguard Worker   }
769*e5436536SAndroid Build Coastguard Worker 
770*e5436536SAndroid Build Coastguard Worker   for (int i = 0; i < lg; i++) {
771*e5436536SAndroid Build Coastguard Worker     rms_m += fPow2Div2(r[i] << headroom) >> shift;
772*e5436536SAndroid Build Coastguard Worker   }
773*e5436536SAndroid Build Coastguard Worker 
774*e5436536SAndroid Build Coastguard Worker   return rms_m;
775*e5436536SAndroid Build Coastguard Worker }
776*e5436536SAndroid Build Coastguard Worker 
777*e5436536SAndroid Build Coastguard Worker /**
778*e5436536SAndroid Build Coastguard Worker  * \brief TCX gain calculation.
779*e5436536SAndroid Build Coastguard Worker  * \param pAacDecoderChannelInfo channel context data.
780*e5436536SAndroid Build Coastguard Worker  * \param r output spectrum.
781*e5436536SAndroid Build Coastguard Worker  * \param rms_e pointer to mantissa of energy value.
782*e5436536SAndroid Build Coastguard Worker  * \param rms_e pointer to exponent of energy value.
783*e5436536SAndroid Build Coastguard Worker  * \param frame the frame index of the LPD super frame.
784*e5436536SAndroid Build Coastguard Worker  * \param lg the frame length in audio samples.
785*e5436536SAndroid Build Coastguard Worker  * \param gain_m pointer to mantissa of TCX gain.
786*e5436536SAndroid Build Coastguard Worker  * \param gain_e pointer to exponent of TCX gain.
787*e5436536SAndroid Build Coastguard Worker  * \param elFlags element specific parser guidance flags.
788*e5436536SAndroid Build Coastguard Worker  * \param lg_fb the fullband frame length in audio samples.
789*e5436536SAndroid Build Coastguard Worker  * \param IGF_bgn the IGF start index.
790*e5436536SAndroid Build Coastguard Worker  */
calcTCXGain(CAacDecoderChannelInfo * pAacDecoderChannelInfo,FIXP_DBL * r,FIXP_DBL rms_m,INT rms_e,const INT frame,const INT lg)791*e5436536SAndroid Build Coastguard Worker static void calcTCXGain(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
792*e5436536SAndroid Build Coastguard Worker                         FIXP_DBL *r, FIXP_DBL rms_m, INT rms_e, const INT frame,
793*e5436536SAndroid Build Coastguard Worker                         const INT lg) {
794*e5436536SAndroid Build Coastguard Worker   if ((rms_m != (FIXP_DBL)0)) {
795*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tcx_gain_m;
796*e5436536SAndroid Build Coastguard Worker     INT tcx_gain_e;
797*e5436536SAndroid Build Coastguard Worker 
798*e5436536SAndroid Build Coastguard Worker     CLpd_DecodeGain(&tcx_gain_m, &tcx_gain_e,
799*e5436536SAndroid Build Coastguard Worker                     pAacDecoderChannelInfo->pDynData->specificTo.usac
800*e5436536SAndroid Build Coastguard Worker                         .tcx_global_gain[frame]);
801*e5436536SAndroid Build Coastguard Worker 
802*e5436536SAndroid Build Coastguard Worker     /* rms * 2^rms_e = lg/sqrt(sum(spec^2)) */
803*e5436536SAndroid Build Coastguard Worker     if (rms_e & 1) {
804*e5436536SAndroid Build Coastguard Worker       rms_m >>= 1;
805*e5436536SAndroid Build Coastguard Worker       rms_e++;
806*e5436536SAndroid Build Coastguard Worker     }
807*e5436536SAndroid Build Coastguard Worker 
808*e5436536SAndroid Build Coastguard Worker     {
809*e5436536SAndroid Build Coastguard Worker       FIXP_DBL fx_lg;
810*e5436536SAndroid Build Coastguard Worker       INT fx_lg_e, s;
811*e5436536SAndroid Build Coastguard Worker       INT inv_e;
812*e5436536SAndroid Build Coastguard Worker 
813*e5436536SAndroid Build Coastguard Worker       /* lg = fx_lg * 2^fx_lg_e */
814*e5436536SAndroid Build Coastguard Worker       s = fNorm((FIXP_DBL)lg);
815*e5436536SAndroid Build Coastguard Worker       fx_lg = (FIXP_DBL)lg << s;
816*e5436536SAndroid Build Coastguard Worker       fx_lg_e = DFRACT_BITS - 1 - s;
817*e5436536SAndroid Build Coastguard Worker       /* 1/sqrt(rms) */
818*e5436536SAndroid Build Coastguard Worker       rms_m = invSqrtNorm2(rms_m, &inv_e);
819*e5436536SAndroid Build Coastguard Worker       rms_m = fMult(rms_m, fx_lg);
820*e5436536SAndroid Build Coastguard Worker       rms_e = inv_e - (rms_e >> 1) + fx_lg_e;
821*e5436536SAndroid Build Coastguard Worker     }
822*e5436536SAndroid Build Coastguard Worker 
823*e5436536SAndroid Build Coastguard Worker     {
824*e5436536SAndroid Build Coastguard Worker       int s = fNorm(tcx_gain_m);
825*e5436536SAndroid Build Coastguard Worker       tcx_gain_m = tcx_gain_m << s;
826*e5436536SAndroid Build Coastguard Worker       tcx_gain_e -= s;
827*e5436536SAndroid Build Coastguard Worker     }
828*e5436536SAndroid Build Coastguard Worker 
829*e5436536SAndroid Build Coastguard Worker     tcx_gain_m = fMultDiv2(tcx_gain_m, rms_m);
830*e5436536SAndroid Build Coastguard Worker     tcx_gain_e = tcx_gain_e + rms_e;
831*e5436536SAndroid Build Coastguard Worker 
832*e5436536SAndroid Build Coastguard Worker     /* global_gain * 2^(global_gain_e+rms_e) = (10^(global_gain/28)) * rms *
833*e5436536SAndroid Build Coastguard Worker      * 2^rms_e */
834*e5436536SAndroid Build Coastguard Worker     {
835*e5436536SAndroid Build Coastguard Worker       { tcx_gain_e += 1; }
836*e5436536SAndroid Build Coastguard Worker     }
837*e5436536SAndroid Build Coastguard Worker 
838*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.tcx_gain[frame] = tcx_gain_m;
839*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.tcx_gain_e[frame] = tcx_gain_e;
840*e5436536SAndroid Build Coastguard Worker 
841*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->specScale[frame] += tcx_gain_e;
842*e5436536SAndroid Build Coastguard Worker   }
843*e5436536SAndroid Build Coastguard Worker }
844*e5436536SAndroid Build Coastguard Worker 
845*e5436536SAndroid Build Coastguard Worker /**
846*e5436536SAndroid Build Coastguard Worker  * \brief FDNS decoding.
847*e5436536SAndroid Build Coastguard Worker  * \param pAacDecoderChannelInfo channel context data.
848*e5436536SAndroid Build Coastguard Worker  * \param pAacDecoderStaticChannelInfo channel context static data.
849*e5436536SAndroid Build Coastguard Worker  * \param r output spectrum.
850*e5436536SAndroid Build Coastguard Worker  * \param lg the frame length in audio samples.
851*e5436536SAndroid Build Coastguard Worker  * \param frame the frame index of the LPD super frame.
852*e5436536SAndroid Build Coastguard Worker  * \param pScale pointer to current scale shift factor of r[].
853*e5436536SAndroid Build Coastguard Worker  * \param A1 old input LPC coefficients of length M_LP_FILTER_ORDER.
854*e5436536SAndroid Build Coastguard Worker  * \param A2 new input LPC coefficients of length M_LP_FILTER_ORDER.
855*e5436536SAndroid Build Coastguard Worker  * \param pAlfdGains pointer for ALFD gains output scaled by 1.
856*e5436536SAndroid Build Coastguard Worker  * \param fdns_npts number of lines (FDNS_NPTS).
857*e5436536SAndroid Build Coastguard Worker  * \param inf_mask pointer to noise mask.
858*e5436536SAndroid Build Coastguard Worker  * \param IGF_win_mode IGF window mode (LONG, SHORT, TCX10, TCX20).
859*e5436536SAndroid Build Coastguard Worker  * \param frameType (IGF_FRAME_DIVISION_AAC_OR_TCX_LONG or
860*e5436536SAndroid Build Coastguard Worker  * IGF_FRAME_DIVISION_TCX_SHORT_1).
861*e5436536SAndroid Build Coastguard Worker  * \param elFlags element specific parser guidance flags.
862*e5436536SAndroid Build Coastguard Worker  * \param lg_fb the fullband frame length in audio samples.
863*e5436536SAndroid Build Coastguard Worker  * \param IGF_bgn the IGF start index.
864*e5436536SAndroid Build Coastguard Worker  * \param rms_m mantisse of energy.
865*e5436536SAndroid Build Coastguard Worker  * \param rms_e exponent of energy.
866*e5436536SAndroid Build Coastguard Worker  */
867*e5436536SAndroid Build Coastguard Worker /* static */
CLpd_FdnsDecode(CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,FIXP_DBL r[],const INT lg,const INT frame,SHORT * pScale,const FIXP_LPC A1[M_LP_FILTER_ORDER],const INT A1_exp,const FIXP_LPC A2[M_LP_FILTER_ORDER],const INT A2_exp,FIXP_DBL pAlfdGains[LFAC/4],const INT fdns_npts)868*e5436536SAndroid Build Coastguard Worker void CLpd_FdnsDecode(CAacDecoderChannelInfo *pAacDecoderChannelInfo,
869*e5436536SAndroid Build Coastguard Worker                      CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
870*e5436536SAndroid Build Coastguard Worker                      FIXP_DBL r[], const INT lg, const INT frame, SHORT *pScale,
871*e5436536SAndroid Build Coastguard Worker                      const FIXP_LPC A1[M_LP_FILTER_ORDER], const INT A1_exp,
872*e5436536SAndroid Build Coastguard Worker                      const FIXP_LPC A2[M_LP_FILTER_ORDER], const INT A2_exp,
873*e5436536SAndroid Build Coastguard Worker                      FIXP_DBL pAlfdGains[LFAC / 4], const INT fdns_npts) {
874*e5436536SAndroid Build Coastguard Worker   /* Weight LPC coefficients using Rm values */
875*e5436536SAndroid Build Coastguard Worker   CLpd_AdaptLowFreqDeemph(r, lg, pAlfdGains, *pScale);
876*e5436536SAndroid Build Coastguard Worker 
877*e5436536SAndroid Build Coastguard Worker   FIXP_DBL rms_m = (FIXP_DBL)0;
878*e5436536SAndroid Build Coastguard Worker   INT rms_e = 0;
879*e5436536SAndroid Build Coastguard Worker   {
880*e5436536SAndroid Build Coastguard Worker     /* Calculate Energy */
881*e5436536SAndroid Build Coastguard Worker     rms_m = calcEnergy(r, *pScale, lg, &rms_e);
882*e5436536SAndroid Build Coastguard Worker   }
883*e5436536SAndroid Build Coastguard Worker 
884*e5436536SAndroid Build Coastguard Worker   calcTCXGain(pAacDecoderChannelInfo, r, rms_m, rms_e, frame, lg);
885*e5436536SAndroid Build Coastguard Worker 
886*e5436536SAndroid Build Coastguard Worker   /* Apply ODFT and Noise Shaping. LP coefficient (A1, A2) weighting is done
887*e5436536SAndroid Build Coastguard Worker    * inside on the fly. */
888*e5436536SAndroid Build Coastguard Worker 
889*e5436536SAndroid Build Coastguard Worker   lpc2mdctAndNoiseShaping(r, pScale, lg, fdns_npts, A1, A1_exp, A2, A2_exp);
890*e5436536SAndroid Build Coastguard Worker }
891*e5436536SAndroid Build Coastguard Worker 
892*e5436536SAndroid Build Coastguard Worker /**
893*e5436536SAndroid Build Coastguard Worker  * find pitch for TCX20 (time domain) concealment.
894*e5436536SAndroid Build Coastguard Worker  */
find_mpitch(FIXP_DBL xri[],int lg)895*e5436536SAndroid Build Coastguard Worker static int find_mpitch(FIXP_DBL xri[], int lg) {
896*e5436536SAndroid Build Coastguard Worker   FIXP_DBL max, pitch;
897*e5436536SAndroid Build Coastguard Worker   INT pitch_e;
898*e5436536SAndroid Build Coastguard Worker   int i, n;
899*e5436536SAndroid Build Coastguard Worker 
900*e5436536SAndroid Build Coastguard Worker   max = (FIXP_DBL)0;
901*e5436536SAndroid Build Coastguard Worker   n = 2;
902*e5436536SAndroid Build Coastguard Worker 
903*e5436536SAndroid Build Coastguard Worker   /* find maximum below 400Hz */
904*e5436536SAndroid Build Coastguard Worker   for (i = 2; i < (lg >> 4); i += 2) {
905*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp = fPow2Div2(xri[i]) + fPow2Div2(xri[i + 1]);
906*e5436536SAndroid Build Coastguard Worker     if (tmp > max) {
907*e5436536SAndroid Build Coastguard Worker       max = tmp;
908*e5436536SAndroid Build Coastguard Worker       n = i;
909*e5436536SAndroid Build Coastguard Worker     }
910*e5436536SAndroid Build Coastguard Worker   }
911*e5436536SAndroid Build Coastguard Worker 
912*e5436536SAndroid Build Coastguard Worker   // pitch = ((float)lg<<1)/(float)n;
913*e5436536SAndroid Build Coastguard Worker   pitch = fDivNorm((FIXP_DBL)lg << 1, (FIXP_DBL)n, &pitch_e);
914*e5436536SAndroid Build Coastguard Worker   pitch >>= fixMax(0, DFRACT_BITS - 1 - pitch_e - 16);
915*e5436536SAndroid Build Coastguard Worker 
916*e5436536SAndroid Build Coastguard Worker   /* find pitch multiple under 20ms */
917*e5436536SAndroid Build Coastguard Worker   if (pitch >= (FIXP_DBL)((256 << 16) - 1)) { /*231.0f*/
918*e5436536SAndroid Build Coastguard Worker     n = 256;
919*e5436536SAndroid Build Coastguard Worker   } else {
920*e5436536SAndroid Build Coastguard Worker     FIXP_DBL mpitch = pitch;
921*e5436536SAndroid Build Coastguard Worker     while (mpitch < (FIXP_DBL)(255 << 16)) {
922*e5436536SAndroid Build Coastguard Worker       mpitch += pitch;
923*e5436536SAndroid Build Coastguard Worker     }
924*e5436536SAndroid Build Coastguard Worker     n = (int)(mpitch - pitch) >> 16;
925*e5436536SAndroid Build Coastguard Worker   }
926*e5436536SAndroid Build Coastguard Worker 
927*e5436536SAndroid Build Coastguard Worker   return (n);
928*e5436536SAndroid Build Coastguard Worker }
929*e5436536SAndroid Build Coastguard Worker 
930*e5436536SAndroid Build Coastguard Worker /**
931*e5436536SAndroid Build Coastguard Worker  * number of spectral coefficients / time domain samples using frame mode as
932*e5436536SAndroid Build Coastguard Worker  * index.
933*e5436536SAndroid Build Coastguard Worker  */
934*e5436536SAndroid Build Coastguard Worker static const int lg_table_ccfl[2][4] = {
935*e5436536SAndroid Build Coastguard Worker     {256, 256, 512, 1024}, /* coreCoderFrameLength = 1024 */
936*e5436536SAndroid Build Coastguard Worker     {192, 192, 384, 768}   /* coreCoderFrameLength = 768  */
937*e5436536SAndroid Build Coastguard Worker };
938*e5436536SAndroid Build Coastguard Worker 
939*e5436536SAndroid Build Coastguard Worker /**
940*e5436536SAndroid Build Coastguard Worker  * \brief Decode and render one MDCT-TCX frame.
941*e5436536SAndroid Build Coastguard Worker  * \param pAacDecoderChannelInfo channel context data.
942*e5436536SAndroid Build Coastguard Worker  * \param lg the frame length in audio samples.
943*e5436536SAndroid Build Coastguard Worker  * \param frame the frame index of the LPD super frame.
944*e5436536SAndroid Build Coastguard Worker  */
CLpd_TcxDecode(CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,UINT flags,int mod,int last_mod,int frame,int frameOk)945*e5436536SAndroid Build Coastguard Worker static void CLpd_TcxDecode(
946*e5436536SAndroid Build Coastguard Worker     CAacDecoderChannelInfo *pAacDecoderChannelInfo,
947*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags,
948*e5436536SAndroid Build Coastguard Worker     int mod, int last_mod, int frame, int frameOk) {
949*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pAlfd_gains = pAacDecoderStaticChannelInfo->last_alfd_gains;
950*e5436536SAndroid Build Coastguard Worker   ULONG *pSeed = &pAacDecoderStaticChannelInfo->nfRandomSeed;
951*e5436536SAndroid Build Coastguard Worker   int lg = (pAacDecoderChannelInfo->granuleLength == 128)
952*e5436536SAndroid Build Coastguard Worker                ? lg_table_ccfl[0][mod + 0]
953*e5436536SAndroid Build Coastguard Worker                : lg_table_ccfl[1][mod + 0];
954*e5436536SAndroid Build Coastguard Worker   int next_frame = frame + (1 << (mod - 1));
955*e5436536SAndroid Build Coastguard Worker   int isFullBandLpd = 0;
956*e5436536SAndroid Build Coastguard Worker 
957*e5436536SAndroid Build Coastguard Worker   /* Obtain r[] vector by combining the quant[] and noise[] vectors */
958*e5436536SAndroid Build Coastguard Worker   {
959*e5436536SAndroid Build Coastguard Worker     FIXP_DBL noise_level;
960*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *coeffs =
961*e5436536SAndroid Build Coastguard Worker         SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame,
962*e5436536SAndroid Build Coastguard Worker                  pAacDecoderChannelInfo->granuleLength, isFullBandLpd);
963*e5436536SAndroid Build Coastguard Worker     int scale = pAacDecoderChannelInfo->specScale[frame];
964*e5436536SAndroid Build Coastguard Worker     int i, nfBgn, nfEnd;
965*e5436536SAndroid Build Coastguard Worker     UCHAR tcx_noise_factor = pAacDecoderChannelInfo->pDynData->specificTo.usac
966*e5436536SAndroid Build Coastguard Worker                                  .tcx_noise_factor[frame];
967*e5436536SAndroid Build Coastguard Worker 
968*e5436536SAndroid Build Coastguard Worker     /* find pitch for bfi case */
969*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->last_tcx_pitch = find_mpitch(coeffs, lg);
970*e5436536SAndroid Build Coastguard Worker 
971*e5436536SAndroid Build Coastguard Worker     if (frameOk) {
972*e5436536SAndroid Build Coastguard Worker       /* store for concealment */
973*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->last_tcx_noise_factor = tcx_noise_factor;
974*e5436536SAndroid Build Coastguard Worker     } else {
975*e5436536SAndroid Build Coastguard Worker       /* restore last frames value */
976*e5436536SAndroid Build Coastguard Worker       tcx_noise_factor = pAacDecoderStaticChannelInfo->last_tcx_noise_factor;
977*e5436536SAndroid Build Coastguard Worker     }
978*e5436536SAndroid Build Coastguard Worker 
979*e5436536SAndroid Build Coastguard Worker     noise_level =
980*e5436536SAndroid Build Coastguard Worker         (FIXP_DBL)((LONG)FL2FXCONST_DBL(0.0625f) * (8 - tcx_noise_factor));
981*e5436536SAndroid Build Coastguard Worker     noise_level = scaleValue(noise_level, -scale);
982*e5436536SAndroid Build Coastguard Worker 
983*e5436536SAndroid Build Coastguard Worker     const FIXP_DBL neg_noise_level = -noise_level;
984*e5436536SAndroid Build Coastguard Worker 
985*e5436536SAndroid Build Coastguard Worker     {
986*e5436536SAndroid Build Coastguard Worker       nfBgn = lg / 6;
987*e5436536SAndroid Build Coastguard Worker       nfEnd = lg;
988*e5436536SAndroid Build Coastguard Worker     }
989*e5436536SAndroid Build Coastguard Worker 
990*e5436536SAndroid Build Coastguard Worker     for (i = nfBgn; i < nfEnd - 7; i += 8) {
991*e5436536SAndroid Build Coastguard Worker       LONG tmp;
992*e5436536SAndroid Build Coastguard Worker 
993*e5436536SAndroid Build Coastguard Worker       /* Fill all 8 consecutive zero coeffs with noise */
994*e5436536SAndroid Build Coastguard Worker       tmp = coeffs[i + 0] | coeffs[i + 1] | coeffs[i + 2] | coeffs[i + 3] |
995*e5436536SAndroid Build Coastguard Worker             coeffs[i + 4] | coeffs[i + 5] | coeffs[i + 6] | coeffs[i + 7];
996*e5436536SAndroid Build Coastguard Worker 
997*e5436536SAndroid Build Coastguard Worker       if (tmp == 0) {
998*e5436536SAndroid Build Coastguard Worker         for (int k = i; k < i + 8; k++) {
999*e5436536SAndroid Build Coastguard Worker           UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level)
1000*e5436536SAndroid Build Coastguard Worker                                 : (coeffs[k] = noise_level);
1001*e5436536SAndroid Build Coastguard Worker         }
1002*e5436536SAndroid Build Coastguard Worker       }
1003*e5436536SAndroid Build Coastguard Worker     }
1004*e5436536SAndroid Build Coastguard Worker     if ((nfEnd - i) >
1005*e5436536SAndroid Build Coastguard Worker         0) { /* noise filling for last "band" with less than 8 bins */
1006*e5436536SAndroid Build Coastguard Worker       LONG tmp = (LONG)coeffs[i];
1007*e5436536SAndroid Build Coastguard Worker       int k;
1008*e5436536SAndroid Build Coastguard Worker 
1009*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT((nfEnd - i) < 8);
1010*e5436536SAndroid Build Coastguard Worker       for (k = 1; k < (nfEnd - i); k++) {
1011*e5436536SAndroid Build Coastguard Worker         tmp |= (LONG)coeffs[i + k];
1012*e5436536SAndroid Build Coastguard Worker       }
1013*e5436536SAndroid Build Coastguard Worker       if (tmp == 0) {
1014*e5436536SAndroid Build Coastguard Worker         for (k = i; k < nfEnd; k++) {
1015*e5436536SAndroid Build Coastguard Worker           UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level)
1016*e5436536SAndroid Build Coastguard Worker                                 : (coeffs[k] = noise_level);
1017*e5436536SAndroid Build Coastguard Worker         }
1018*e5436536SAndroid Build Coastguard Worker       }
1019*e5436536SAndroid Build Coastguard Worker     }
1020*e5436536SAndroid Build Coastguard Worker   }
1021*e5436536SAndroid Build Coastguard Worker 
1022*e5436536SAndroid Build Coastguard Worker   {
1023*e5436536SAndroid Build Coastguard Worker     /* Convert LPC to LP domain */
1024*e5436536SAndroid Build Coastguard Worker     if (last_mod == 0) {
1025*e5436536SAndroid Build Coastguard Worker       /* Note: The case where last_mod == 255 is handled by other means
1026*e5436536SAndroid Build Coastguard Worker        * in CLpdChannelStream_Read() */
1027*e5436536SAndroid Build Coastguard Worker       E_LPC_f_lsp_a_conversion(
1028*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.lsp_coeff[frame],
1029*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.lp_coeff[frame],
1030*e5436536SAndroid Build Coastguard Worker           &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame]);
1031*e5436536SAndroid Build Coastguard Worker     }
1032*e5436536SAndroid Build Coastguard Worker 
1033*e5436536SAndroid Build Coastguard Worker     E_LPC_f_lsp_a_conversion(
1034*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lsp_coeff[next_frame],
1035*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame],
1036*e5436536SAndroid Build Coastguard Worker         &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame]);
1037*e5436536SAndroid Build Coastguard Worker 
1038*e5436536SAndroid Build Coastguard Worker     /* FDNS decoding */
1039*e5436536SAndroid Build Coastguard Worker     CLpd_FdnsDecode(
1040*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo,
1041*e5436536SAndroid Build Coastguard Worker         SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame,
1042*e5436536SAndroid Build Coastguard Worker                  pAacDecoderChannelInfo->granuleLength, isFullBandLpd),
1043*e5436536SAndroid Build Coastguard Worker         lg, frame, pAacDecoderChannelInfo->specScale + frame,
1044*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff[frame],
1045*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame],
1046*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame],
1047*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame], pAlfd_gains,
1048*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->granuleLength / 2 /* == FDNS_NPTS(ccfl) */
1049*e5436536SAndroid Build Coastguard Worker     );
1050*e5436536SAndroid Build Coastguard Worker   }
1051*e5436536SAndroid Build Coastguard Worker }
1052*e5436536SAndroid Build Coastguard Worker 
1053*e5436536SAndroid Build Coastguard Worker /**
1054*e5436536SAndroid Build Coastguard Worker  * \brief Read the tcx_coding bitstream part
1055*e5436536SAndroid Build Coastguard Worker  * \param hBs bitstream handle to read from.
1056*e5436536SAndroid Build Coastguard Worker  * \param pAacDecoderChannelInfo channel context info to store data into.
1057*e5436536SAndroid Build Coastguard Worker  * \param lg the frame length in audio samples.
1058*e5436536SAndroid Build Coastguard Worker  * \param first_tcx_flag flag indicating that this is the first TCX frame.
1059*e5436536SAndroid Build Coastguard Worker  * \param frame the frame index of the LPD super frame.
1060*e5436536SAndroid Build Coastguard Worker  */
CLpd_TCX_Read(HANDLE_FDK_BITSTREAM hBs,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,int lg,int first_tcx_flag,int frame,UINT flags)1061*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CLpd_TCX_Read(
1062*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
1063*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, int lg,
1064*e5436536SAndroid Build Coastguard Worker     int first_tcx_flag, int frame, UINT flags) {
1065*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR errorAAC = AAC_DEC_OK;
1066*e5436536SAndroid Build Coastguard Worker   ARITH_CODING_ERROR error = ARITH_CODER_OK;
1067*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pSpec;
1068*e5436536SAndroid Build Coastguard Worker   int arith_reset_flag = 0;
1069*e5436536SAndroid Build Coastguard Worker   int isFullBandLpd = 0;
1070*e5436536SAndroid Build Coastguard Worker 
1071*e5436536SAndroid Build Coastguard Worker   pSpec = SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame,
1072*e5436536SAndroid Build Coastguard Worker                    pAacDecoderChannelInfo->granuleLength, isFullBandLpd);
1073*e5436536SAndroid Build Coastguard Worker 
1074*e5436536SAndroid Build Coastguard Worker   /* TCX noise level */
1075*e5436536SAndroid Build Coastguard Worker   {
1076*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_noise_factor[frame] =
1077*e5436536SAndroid Build Coastguard Worker         FDKreadBits(hBs, 3);
1078*e5436536SAndroid Build Coastguard Worker   }
1079*e5436536SAndroid Build Coastguard Worker   /* TCX global gain */
1080*e5436536SAndroid Build Coastguard Worker   pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_global_gain[frame] =
1081*e5436536SAndroid Build Coastguard Worker       FDKreadBits(hBs, 7);
1082*e5436536SAndroid Build Coastguard Worker 
1083*e5436536SAndroid Build Coastguard Worker   /* Arithmetic coded residual/spectrum */
1084*e5436536SAndroid Build Coastguard Worker   if (first_tcx_flag) {
1085*e5436536SAndroid Build Coastguard Worker     if (flags & AC_INDEP) {
1086*e5436536SAndroid Build Coastguard Worker       arith_reset_flag = 1;
1087*e5436536SAndroid Build Coastguard Worker     } else {
1088*e5436536SAndroid Build Coastguard Worker       arith_reset_flag = FDKreadBits(hBs, 1);
1089*e5436536SAndroid Build Coastguard Worker     }
1090*e5436536SAndroid Build Coastguard Worker   }
1091*e5436536SAndroid Build Coastguard Worker 
1092*e5436536SAndroid Build Coastguard Worker   /* CArco_DecodeArithData() output scale of "pSpec" is DFRACT_BITS-1 */
1093*e5436536SAndroid Build Coastguard Worker   error = CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs, pSpec,
1094*e5436536SAndroid Build Coastguard Worker                                 lg, lg, arith_reset_flag);
1095*e5436536SAndroid Build Coastguard Worker 
1096*e5436536SAndroid Build Coastguard Worker   /* Rescale residual/spectrum */
1097*e5436536SAndroid Build Coastguard Worker   {
1098*e5436536SAndroid Build Coastguard Worker     int scale = getScalefactor(pSpec, lg) - 2; /* Leave 2 bits headroom */
1099*e5436536SAndroid Build Coastguard Worker 
1100*e5436536SAndroid Build Coastguard Worker     /* Exponent of CArco_DecodeArithData() output is DFRACT_BITS; integer
1101*e5436536SAndroid Build Coastguard Worker      * values. */
1102*e5436536SAndroid Build Coastguard Worker     scaleValues(pSpec, lg, scale);
1103*e5436536SAndroid Build Coastguard Worker     scale = DFRACT_BITS - 1 - scale;
1104*e5436536SAndroid Build Coastguard Worker 
1105*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->specScale[frame] = scale;
1106*e5436536SAndroid Build Coastguard Worker   }
1107*e5436536SAndroid Build Coastguard Worker 
1108*e5436536SAndroid Build Coastguard Worker   if (error == ARITH_CODER_ERROR) errorAAC = AAC_DEC_UNKNOWN;
1109*e5436536SAndroid Build Coastguard Worker 
1110*e5436536SAndroid Build Coastguard Worker   return errorAAC;
1111*e5436536SAndroid Build Coastguard Worker }
1112*e5436536SAndroid Build Coastguard Worker 
1113*e5436536SAndroid Build Coastguard Worker /**
1114*e5436536SAndroid Build Coastguard Worker  * \brief translate lpd_mode into the mod[] array which describes the mode of
1115*e5436536SAndroid Build Coastguard Worker  * each each LPD frame
1116*e5436536SAndroid Build Coastguard Worker  * \param mod[] the array that will be filled with the mode indexes of the
1117*e5436536SAndroid Build Coastguard Worker  * inidividual frames.
1118*e5436536SAndroid Build Coastguard Worker  * \param lpd_mode the lpd_mode field read from the lpd_channel_stream
1119*e5436536SAndroid Build Coastguard Worker  */
CLpd_ReadAndMapLpdModeToModArray(UCHAR mod[4],HANDLE_FDK_BITSTREAM hBs,UINT elFlags)1120*e5436536SAndroid Build Coastguard Worker static AAC_DECODER_ERROR CLpd_ReadAndMapLpdModeToModArray(
1121*e5436536SAndroid Build Coastguard Worker     UCHAR mod[4], HANDLE_FDK_BITSTREAM hBs, UINT elFlags) {
1122*e5436536SAndroid Build Coastguard Worker   int lpd_mode;
1123*e5436536SAndroid Build Coastguard Worker 
1124*e5436536SAndroid Build Coastguard Worker   {
1125*e5436536SAndroid Build Coastguard Worker     lpd_mode = FDKreadBits(hBs, 5);
1126*e5436536SAndroid Build Coastguard Worker 
1127*e5436536SAndroid Build Coastguard Worker     if (lpd_mode > 25 || lpd_mode < 0) {
1128*e5436536SAndroid Build Coastguard Worker       return AAC_DEC_PARSE_ERROR;
1129*e5436536SAndroid Build Coastguard Worker     }
1130*e5436536SAndroid Build Coastguard Worker 
1131*e5436536SAndroid Build Coastguard Worker     switch (lpd_mode) {
1132*e5436536SAndroid Build Coastguard Worker       case 25:
1133*e5436536SAndroid Build Coastguard Worker         /* 1 80MS frame */
1134*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 3;
1135*e5436536SAndroid Build Coastguard Worker         break;
1136*e5436536SAndroid Build Coastguard Worker       case 24:
1137*e5436536SAndroid Build Coastguard Worker         /* 2 40MS frames */
1138*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 2;
1139*e5436536SAndroid Build Coastguard Worker         break;
1140*e5436536SAndroid Build Coastguard Worker       default:
1141*e5436536SAndroid Build Coastguard Worker         switch (lpd_mode >> 2) {
1142*e5436536SAndroid Build Coastguard Worker           case 4:
1143*e5436536SAndroid Build Coastguard Worker             /* lpd_mode 19 - 16  => 1 40MS and 2 20MS frames */
1144*e5436536SAndroid Build Coastguard Worker             mod[0] = mod[1] = 2;
1145*e5436536SAndroid Build Coastguard Worker             mod[2] = (lpd_mode & 1) ? 1 : 0;
1146*e5436536SAndroid Build Coastguard Worker             mod[3] = (lpd_mode & 2) ? 1 : 0;
1147*e5436536SAndroid Build Coastguard Worker             break;
1148*e5436536SAndroid Build Coastguard Worker           case 5:
1149*e5436536SAndroid Build Coastguard Worker             /* lpd_mode 23 - 20 => 2 20MS and 1 40MS frames */
1150*e5436536SAndroid Build Coastguard Worker             mod[2] = mod[3] = 2;
1151*e5436536SAndroid Build Coastguard Worker             mod[0] = (lpd_mode & 1) ? 1 : 0;
1152*e5436536SAndroid Build Coastguard Worker             mod[1] = (lpd_mode & 2) ? 1 : 0;
1153*e5436536SAndroid Build Coastguard Worker             break;
1154*e5436536SAndroid Build Coastguard Worker           default:
1155*e5436536SAndroid Build Coastguard Worker             /* lpd_mode < 16 => 4 20MS frames */
1156*e5436536SAndroid Build Coastguard Worker             mod[0] = (lpd_mode & 1) ? 1 : 0;
1157*e5436536SAndroid Build Coastguard Worker             mod[1] = (lpd_mode & 2) ? 1 : 0;
1158*e5436536SAndroid Build Coastguard Worker             mod[2] = (lpd_mode & 4) ? 1 : 0;
1159*e5436536SAndroid Build Coastguard Worker             mod[3] = (lpd_mode & 8) ? 1 : 0;
1160*e5436536SAndroid Build Coastguard Worker             break;
1161*e5436536SAndroid Build Coastguard Worker         }
1162*e5436536SAndroid Build Coastguard Worker         break;
1163*e5436536SAndroid Build Coastguard Worker     }
1164*e5436536SAndroid Build Coastguard Worker   }
1165*e5436536SAndroid Build Coastguard Worker   return AAC_DEC_OK;
1166*e5436536SAndroid Build Coastguard Worker }
1167*e5436536SAndroid Build Coastguard Worker 
CLpd_Reset(CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,int keep_past_signal)1168*e5436536SAndroid Build Coastguard Worker static void CLpd_Reset(
1169*e5436536SAndroid Build Coastguard Worker     CAacDecoderChannelInfo *pAacDecoderChannelInfo,
1170*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1171*e5436536SAndroid Build Coastguard Worker     int keep_past_signal) {
1172*e5436536SAndroid Build Coastguard Worker   int i;
1173*e5436536SAndroid Build Coastguard Worker 
1174*e5436536SAndroid Build Coastguard Worker   /* Reset TCX / ACELP common memory */
1175*e5436536SAndroid Build Coastguard Worker   if (!keep_past_signal) {
1176*e5436536SAndroid Build Coastguard Worker     FDKmemclear(pAacDecoderStaticChannelInfo->old_synth,
1177*e5436536SAndroid Build Coastguard Worker                 sizeof(pAacDecoderStaticChannelInfo->old_synth));
1178*e5436536SAndroid Build Coastguard Worker   }
1179*e5436536SAndroid Build Coastguard Worker 
1180*e5436536SAndroid Build Coastguard Worker   /* Initialize the LSFs */
1181*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1182*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->lpc4_lsf[i] = fdk_dec_lsf_init[i];
1183*e5436536SAndroid Build Coastguard Worker   }
1184*e5436536SAndroid Build Coastguard Worker 
1185*e5436536SAndroid Build Coastguard Worker   /* Reset memory needed by bass post-filter */
1186*e5436536SAndroid Build Coastguard Worker   FDKmemclear(pAacDecoderStaticChannelInfo->mem_bpf,
1187*e5436536SAndroid Build Coastguard Worker               sizeof(pAacDecoderStaticChannelInfo->mem_bpf));
1188*e5436536SAndroid Build Coastguard Worker 
1189*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->old_bpf_control_info = 0;
1190*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < SYN_SFD; i++) {
1191*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->old_T_pf[i] = 64;
1192*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->old_gain_pf[i] = (FIXP_DBL)0;
1193*e5436536SAndroid Build Coastguard Worker   }
1194*e5436536SAndroid Build Coastguard Worker 
1195*e5436536SAndroid Build Coastguard Worker   /* Reset ACELP memory */
1196*e5436536SAndroid Build Coastguard Worker   CLpd_AcelpReset(&pAacDecoderStaticChannelInfo->acelp);
1197*e5436536SAndroid Build Coastguard Worker 
1198*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->last_lpc_lost = 0;      /* prev_lpc_lost */
1199*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->last_tcx_pitch = L_DIV; /* pitch_tcx     */
1200*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->numLostLpdFrames = 0;   /* nbLostCmpt    */
1201*e5436536SAndroid Build Coastguard Worker }
1202*e5436536SAndroid Build Coastguard Worker 
1203*e5436536SAndroid Build Coastguard Worker /*
1204*e5436536SAndroid Build Coastguard Worker  * Externally visible functions
1205*e5436536SAndroid Build Coastguard Worker  */
1206*e5436536SAndroid Build Coastguard Worker 
CLpdChannelStream_Read(HANDLE_FDK_BITSTREAM hBs,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,const SamplingRateInfo * pSamplingRateInfo,UINT flags)1207*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR CLpdChannelStream_Read(
1208*e5436536SAndroid Build Coastguard Worker     HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
1209*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1210*e5436536SAndroid Build Coastguard Worker     const SamplingRateInfo *pSamplingRateInfo, UINT flags) {
1211*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
1212*e5436536SAndroid Build Coastguard Worker   int first_tcx_flag;
1213*e5436536SAndroid Build Coastguard Worker   int k, nbDiv, fFacDataPresent, first_lpd_flag, acelp_core_mode,
1214*e5436536SAndroid Build Coastguard Worker       facGetMemState = 0;
1215*e5436536SAndroid Build Coastguard Worker   UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod;
1216*e5436536SAndroid Build Coastguard Worker   int lpd_mode_last, prev_frame_was_lpd;
1217*e5436536SAndroid Build Coastguard Worker   USAC_COREMODE core_mode_last;
1218*e5436536SAndroid Build Coastguard Worker   const int lg_table_offset = 0;
1219*e5436536SAndroid Build Coastguard Worker   const int *lg_table = (pAacDecoderChannelInfo->granuleLength == 128)
1220*e5436536SAndroid Build Coastguard Worker                             ? &lg_table_ccfl[0][lg_table_offset]
1221*e5436536SAndroid Build Coastguard Worker                             : &lg_table_ccfl[1][lg_table_offset];
1222*e5436536SAndroid Build Coastguard Worker   int last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost;
1223*e5436536SAndroid Build Coastguard Worker 
1224*e5436536SAndroid Build Coastguard Worker   int last_frame_ok = CConcealment_GetLastFrameOk(
1225*e5436536SAndroid Build Coastguard Worker       &pAacDecoderStaticChannelInfo->concealmentInfo, 1);
1226*e5436536SAndroid Build Coastguard Worker 
1227*e5436536SAndroid Build Coastguard Worker   INT i_offset;
1228*e5436536SAndroid Build Coastguard Worker   UINT samplingRate;
1229*e5436536SAndroid Build Coastguard Worker 
1230*e5436536SAndroid Build Coastguard Worker   samplingRate = pSamplingRateInfo->samplingRate;
1231*e5436536SAndroid Build Coastguard Worker 
1232*e5436536SAndroid Build Coastguard Worker   i_offset =
1233*e5436536SAndroid Build Coastguard Worker       (INT)(samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM -
1234*e5436536SAndroid Build Coastguard Worker       (INT)PIT_MIN_12k8;
1235*e5436536SAndroid Build Coastguard Worker 
1236*e5436536SAndroid Build Coastguard Worker   if ((samplingRate < FAC_FSCALE_MIN) || (samplingRate > FAC_FSCALE_MAX)) {
1237*e5436536SAndroid Build Coastguard Worker     error = AAC_DEC_PARSE_ERROR;
1238*e5436536SAndroid Build Coastguard Worker     goto bail;
1239*e5436536SAndroid Build Coastguard Worker   }
1240*e5436536SAndroid Build Coastguard Worker 
1241*e5436536SAndroid Build Coastguard Worker   acelp_core_mode = FDKreadBits(hBs, 3);
1242*e5436536SAndroid Build Coastguard Worker 
1243*e5436536SAndroid Build Coastguard Worker   /* lpd_mode */
1244*e5436536SAndroid Build Coastguard Worker   error = CLpd_ReadAndMapLpdModeToModArray(mod, hBs, 0);
1245*e5436536SAndroid Build Coastguard Worker   if (error != AAC_DEC_OK) {
1246*e5436536SAndroid Build Coastguard Worker     goto bail;
1247*e5436536SAndroid Build Coastguard Worker   }
1248*e5436536SAndroid Build Coastguard Worker 
1249*e5436536SAndroid Build Coastguard Worker   /* bpf_control_info */
1250*e5436536SAndroid Build Coastguard Worker   pAacDecoderChannelInfo->data.usac.bpf_control_info = FDKreadBit(hBs);
1251*e5436536SAndroid Build Coastguard Worker 
1252*e5436536SAndroid Build Coastguard Worker   /* last_core_mode */
1253*e5436536SAndroid Build Coastguard Worker   prev_frame_was_lpd = FDKreadBit(hBs);
1254*e5436536SAndroid Build Coastguard Worker   /* fac_data_present */
1255*e5436536SAndroid Build Coastguard Worker   fFacDataPresent = FDKreadBit(hBs);
1256*e5436536SAndroid Build Coastguard Worker 
1257*e5436536SAndroid Build Coastguard Worker   /* Set valid values from
1258*e5436536SAndroid Build Coastguard Worker    * pAacDecoderStaticChannelInfo->{last_core_mode,last_lpd_mode} */
1259*e5436536SAndroid Build Coastguard Worker   pAacDecoderChannelInfo->data.usac.core_mode_last =
1260*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->last_core_mode;
1261*e5436536SAndroid Build Coastguard Worker   lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last =
1262*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->last_lpd_mode;
1263*e5436536SAndroid Build Coastguard Worker 
1264*e5436536SAndroid Build Coastguard Worker   if (prev_frame_was_lpd == 0) {
1265*e5436536SAndroid Build Coastguard Worker     /* Last frame was FD */
1266*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.core_mode_last = FD_LONG;
1267*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255;
1268*e5436536SAndroid Build Coastguard Worker   } else {
1269*e5436536SAndroid Build Coastguard Worker     /* Last frame was LPD */
1270*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.core_mode_last = LPD;
1271*e5436536SAndroid Build Coastguard Worker     if (((mod[0] == 0) && fFacDataPresent) ||
1272*e5436536SAndroid Build Coastguard Worker         ((mod[0] != 0) && !fFacDataPresent)) {
1273*e5436536SAndroid Build Coastguard Worker       /* Currend mod is ACELP, fac data present -> TCX, current mod TCX, no fac
1274*e5436536SAndroid Build Coastguard Worker        * data -> TCX */
1275*e5436536SAndroid Build Coastguard Worker       if (lpd_mode_last == 0) {
1276*e5436536SAndroid Build Coastguard Worker         /* Bit stream interruption detected. Assume last TCX mode as TCX20. */
1277*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lpd_mode_last = 1;
1278*e5436536SAndroid Build Coastguard Worker       }
1279*e5436536SAndroid Build Coastguard Worker       /* Else assume that remembered TCX mode is correct. */
1280*e5436536SAndroid Build Coastguard Worker     } else {
1281*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.lpd_mode_last = 0;
1282*e5436536SAndroid Build Coastguard Worker     }
1283*e5436536SAndroid Build Coastguard Worker   }
1284*e5436536SAndroid Build Coastguard Worker 
1285*e5436536SAndroid Build Coastguard Worker   first_lpd_flag = (pAacDecoderChannelInfo->data.usac.core_mode_last !=
1286*e5436536SAndroid Build Coastguard Worker                     LPD); /* Depends on bitstream configuration */
1287*e5436536SAndroid Build Coastguard Worker   first_tcx_flag = 1;
1288*e5436536SAndroid Build Coastguard Worker 
1289*e5436536SAndroid Build Coastguard Worker   if (pAacDecoderStaticChannelInfo->last_core_mode !=
1290*e5436536SAndroid Build Coastguard Worker       LPD) { /* ATTENTION: Reset depends on what we rendered before! */
1291*e5436536SAndroid Build Coastguard Worker     CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, 0);
1292*e5436536SAndroid Build Coastguard Worker 
1293*e5436536SAndroid Build Coastguard Worker     if (!last_frame_ok) {
1294*e5436536SAndroid Build Coastguard Worker       /* If last rendered frame was not LPD and first lpd flag is not set, this
1295*e5436536SAndroid Build Coastguard Worker        * must be an error - set last_lpc_lost flag */
1296*e5436536SAndroid Build Coastguard Worker       last_lpc_lost |= (first_lpd_flag) ? 0 : 1;
1297*e5436536SAndroid Build Coastguard Worker     }
1298*e5436536SAndroid Build Coastguard Worker   }
1299*e5436536SAndroid Build Coastguard Worker 
1300*e5436536SAndroid Build Coastguard Worker   core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last;
1301*e5436536SAndroid Build Coastguard Worker   lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last;
1302*e5436536SAndroid Build Coastguard Worker 
1303*e5436536SAndroid Build Coastguard Worker   nbDiv = NB_DIV;
1304*e5436536SAndroid Build Coastguard Worker 
1305*e5436536SAndroid Build Coastguard Worker   /* k is the frame index. If a frame is of size 40MS or 80MS,
1306*e5436536SAndroid Build Coastguard Worker      this frame index is incremented 2 or 4 instead of 1 respectively. */
1307*e5436536SAndroid Build Coastguard Worker 
1308*e5436536SAndroid Build Coastguard Worker   k = 0;
1309*e5436536SAndroid Build Coastguard Worker   while (k < nbDiv) {
1310*e5436536SAndroid Build Coastguard Worker     /* Reset FAC data pointers in order to avoid applying old random FAC data.
1311*e5436536SAndroid Build Coastguard Worker      */
1312*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.fac_data[k] = NULL;
1313*e5436536SAndroid Build Coastguard Worker 
1314*e5436536SAndroid Build Coastguard Worker     if ((k == 0 && core_mode_last == LPD && fFacDataPresent) ||
1315*e5436536SAndroid Build Coastguard Worker         (lpd_mode_last == 0 && mod[k] > 0) ||
1316*e5436536SAndroid Build Coastguard Worker         ((lpd_mode_last != 255) && lpd_mode_last > 0 && mod[k] == 0)) {
1317*e5436536SAndroid Build Coastguard Worker       int err;
1318*e5436536SAndroid Build Coastguard Worker 
1319*e5436536SAndroid Build Coastguard Worker       /* Assign FAC memory */
1320*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.fac_data[k] =
1321*e5436536SAndroid Build Coastguard Worker           CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState);
1322*e5436536SAndroid Build Coastguard Worker 
1323*e5436536SAndroid Build Coastguard Worker       /* FAC for (ACELP -> TCX) or (TCX -> ACELP) */
1324*e5436536SAndroid Build Coastguard Worker       err = CLpd_FAC_Read(
1325*e5436536SAndroid Build Coastguard Worker           hBs, pAacDecoderChannelInfo->data.usac.fac_data[k],
1326*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.fac_data_e,
1327*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->granuleLength, /* == fac_length */
1328*e5436536SAndroid Build Coastguard Worker           0, k);
1329*e5436536SAndroid Build Coastguard Worker       if (err != 0) {
1330*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1331*e5436536SAndroid Build Coastguard Worker         goto bail;
1332*e5436536SAndroid Build Coastguard Worker       }
1333*e5436536SAndroid Build Coastguard Worker     }
1334*e5436536SAndroid Build Coastguard Worker 
1335*e5436536SAndroid Build Coastguard Worker     if (mod[k] == 0) /* acelp-mode */
1336*e5436536SAndroid Build Coastguard Worker     {
1337*e5436536SAndroid Build Coastguard Worker       int err;
1338*e5436536SAndroid Build Coastguard Worker       err = CLpd_AcelpRead(
1339*e5436536SAndroid Build Coastguard Worker           hBs, &pAacDecoderChannelInfo->data.usac.acelp[k], acelp_core_mode,
1340*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->granuleLength * 8 /* coreCoderFrameLength */,
1341*e5436536SAndroid Build Coastguard Worker           i_offset);
1342*e5436536SAndroid Build Coastguard Worker       if (err != 0) {
1343*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1344*e5436536SAndroid Build Coastguard Worker         goto bail;
1345*e5436536SAndroid Build Coastguard Worker       }
1346*e5436536SAndroid Build Coastguard Worker 
1347*e5436536SAndroid Build Coastguard Worker       lpd_mode_last = 0;
1348*e5436536SAndroid Build Coastguard Worker       k++;
1349*e5436536SAndroid Build Coastguard Worker     } else /* mode != 0  =>  TCX */
1350*e5436536SAndroid Build Coastguard Worker     {
1351*e5436536SAndroid Build Coastguard Worker       error = CLpd_TCX_Read(hBs, pAacDecoderChannelInfo,
1352*e5436536SAndroid Build Coastguard Worker                             pAacDecoderStaticChannelInfo, lg_table[mod[k]],
1353*e5436536SAndroid Build Coastguard Worker                             first_tcx_flag, k, flags);
1354*e5436536SAndroid Build Coastguard Worker 
1355*e5436536SAndroid Build Coastguard Worker       lpd_mode_last = mod[k];
1356*e5436536SAndroid Build Coastguard Worker       first_tcx_flag = 0;
1357*e5436536SAndroid Build Coastguard Worker       k += 1 << (mod[k] - 1);
1358*e5436536SAndroid Build Coastguard Worker     }
1359*e5436536SAndroid Build Coastguard Worker     if (error != AAC_DEC_OK) {
1360*e5436536SAndroid Build Coastguard Worker       error = AAC_DEC_PARSE_ERROR;
1361*e5436536SAndroid Build Coastguard Worker       goto bail;
1362*e5436536SAndroid Build Coastguard Worker     }
1363*e5436536SAndroid Build Coastguard Worker   }
1364*e5436536SAndroid Build Coastguard Worker 
1365*e5436536SAndroid Build Coastguard Worker   {
1366*e5436536SAndroid Build Coastguard Worker     int err;
1367*e5436536SAndroid Build Coastguard Worker 
1368*e5436536SAndroid Build Coastguard Worker     /* Read LPC coefficients */
1369*e5436536SAndroid Build Coastguard Worker     err = CLpc_Read(
1370*e5436536SAndroid Build Coastguard Worker         hBs, pAacDecoderChannelInfo->data.usac.lsp_coeff,
1371*e5436536SAndroid Build Coastguard Worker         pAacDecoderStaticChannelInfo->lpc4_lsf,
1372*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand,
1373*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.aStability, mod, first_lpd_flag,
1374*e5436536SAndroid Build Coastguard Worker         /* if last lpc4 is available from concealment do not extrapolate lpc0
1375*e5436536SAndroid Build Coastguard Worker            from lpc2 */
1376*e5436536SAndroid Build Coastguard Worker         (mod[0] & 0x3) ? 0
1377*e5436536SAndroid Build Coastguard Worker                        : (last_lpc_lost &&
1378*e5436536SAndroid Build Coastguard Worker                           pAacDecoderStaticChannelInfo->last_core_mode != LPD),
1379*e5436536SAndroid Build Coastguard Worker         last_frame_ok);
1380*e5436536SAndroid Build Coastguard Worker     if (err != 0) {
1381*e5436536SAndroid Build Coastguard Worker       error = AAC_DEC_PARSE_ERROR;
1382*e5436536SAndroid Build Coastguard Worker       goto bail;
1383*e5436536SAndroid Build Coastguard Worker     }
1384*e5436536SAndroid Build Coastguard Worker   }
1385*e5436536SAndroid Build Coastguard Worker 
1386*e5436536SAndroid Build Coastguard Worker   /* adjust old lsp[] following to a bad frame (to avoid overshoot) (ref:
1387*e5436536SAndroid Build Coastguard Worker    * dec_LPD.c) */
1388*e5436536SAndroid Build Coastguard Worker   if (last_lpc_lost && !last_frame_ok) {
1389*e5436536SAndroid Build Coastguard Worker     int k_next;
1390*e5436536SAndroid Build Coastguard Worker     k = 0;
1391*e5436536SAndroid Build Coastguard Worker     while (k < nbDiv) {
1392*e5436536SAndroid Build Coastguard Worker       int i;
1393*e5436536SAndroid Build Coastguard Worker       k_next = k + (((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1)));
1394*e5436536SAndroid Build Coastguard Worker       FIXP_LPC *lsp_old = pAacDecoderChannelInfo->data.usac.lsp_coeff[k];
1395*e5436536SAndroid Build Coastguard Worker       FIXP_LPC *lsp_new = pAacDecoderChannelInfo->data.usac.lsp_coeff[k_next];
1396*e5436536SAndroid Build Coastguard Worker 
1397*e5436536SAndroid Build Coastguard Worker       for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1398*e5436536SAndroid Build Coastguard Worker         if (lsp_new[i] < lsp_old[i]) {
1399*e5436536SAndroid Build Coastguard Worker           lsp_old[i] = lsp_new[i];
1400*e5436536SAndroid Build Coastguard Worker         }
1401*e5436536SAndroid Build Coastguard Worker       }
1402*e5436536SAndroid Build Coastguard Worker       k = k_next;
1403*e5436536SAndroid Build Coastguard Worker     }
1404*e5436536SAndroid Build Coastguard Worker   }
1405*e5436536SAndroid Build Coastguard Worker 
1406*e5436536SAndroid Build Coastguard Worker   if (!CConcealment_GetLastFrameOk(
1407*e5436536SAndroid Build Coastguard Worker           &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) {
1408*e5436536SAndroid Build Coastguard Worker     E_LPC_f_lsp_a_conversion(
1409*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lsp_coeff[0],
1410*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff[0],
1411*e5436536SAndroid Build Coastguard Worker         &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]);
1412*e5436536SAndroid Build Coastguard Worker   } else if (pAacDecoderStaticChannelInfo->last_lpd_mode != 0) {
1413*e5436536SAndroid Build Coastguard Worker     if (pAacDecoderStaticChannelInfo->last_lpd_mode == 255) {
1414*e5436536SAndroid Build Coastguard Worker       /* We need it for TCX decoding or ACELP excitation update */
1415*e5436536SAndroid Build Coastguard Worker       E_LPC_f_lsp_a_conversion(
1416*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.lsp_coeff[0],
1417*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.lp_coeff[0],
1418*e5436536SAndroid Build Coastguard Worker           &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]);
1419*e5436536SAndroid Build Coastguard Worker     } else { /* last_lpd_mode was TCX */
1420*e5436536SAndroid Build Coastguard Worker       /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid
1421*e5436536SAndroid Build Coastguard Worker        * converting LSP coefficients again). */
1422*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0],
1423*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->lp_coeff_old[0],
1424*e5436536SAndroid Build Coastguard Worker                 M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1425*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] =
1426*e5436536SAndroid Build Coastguard Worker           pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0];
1427*e5436536SAndroid Build Coastguard Worker     }
1428*e5436536SAndroid Build Coastguard Worker   } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */
1429*e5436536SAndroid Build Coastguard Worker 
1430*e5436536SAndroid Build Coastguard Worker   if (fFacDataPresent && (core_mode_last != LPD)) {
1431*e5436536SAndroid Build Coastguard Worker     int prev_frame_was_short;
1432*e5436536SAndroid Build Coastguard Worker 
1433*e5436536SAndroid Build Coastguard Worker     prev_frame_was_short = FDKreadBit(hBs);
1434*e5436536SAndroid Build Coastguard Worker 
1435*e5436536SAndroid Build Coastguard Worker     if (prev_frame_was_short) {
1436*e5436536SAndroid Build Coastguard Worker       core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last =
1437*e5436536SAndroid Build Coastguard Worker           FD_SHORT;
1438*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255;
1439*e5436536SAndroid Build Coastguard Worker 
1440*e5436536SAndroid Build Coastguard Worker       if ((pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) &&
1441*e5436536SAndroid Build Coastguard Worker           CConcealment_GetLastFrameOk(
1442*e5436536SAndroid Build Coastguard Worker               &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) {
1443*e5436536SAndroid Build Coastguard Worker         /* USAC Conformance document:
1444*e5436536SAndroid Build Coastguard Worker            short_fac_flag   shall be encoded with a value of 1 if the
1445*e5436536SAndroid Build Coastguard Worker            window_sequence of the previous frame was 2 (EIGHT_SHORT_SEQUENCE).
1446*e5436536SAndroid Build Coastguard Worker                             Otherwise short_fac_flag shall be encoded with a
1447*e5436536SAndroid Build Coastguard Worker            value of 0. */
1448*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1449*e5436536SAndroid Build Coastguard Worker         goto bail;
1450*e5436536SAndroid Build Coastguard Worker       }
1451*e5436536SAndroid Build Coastguard Worker     }
1452*e5436536SAndroid Build Coastguard Worker 
1453*e5436536SAndroid Build Coastguard Worker     /* Assign memory */
1454*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.fac_data[0] =
1455*e5436536SAndroid Build Coastguard Worker         CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState);
1456*e5436536SAndroid Build Coastguard Worker 
1457*e5436536SAndroid Build Coastguard Worker     {
1458*e5436536SAndroid Build Coastguard Worker       int err;
1459*e5436536SAndroid Build Coastguard Worker 
1460*e5436536SAndroid Build Coastguard Worker       /* FAC for FD -> ACELP */
1461*e5436536SAndroid Build Coastguard Worker       err = CLpd_FAC_Read(
1462*e5436536SAndroid Build Coastguard Worker           hBs, pAacDecoderChannelInfo->data.usac.fac_data[0],
1463*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.fac_data_e,
1464*e5436536SAndroid Build Coastguard Worker           CLpd_FAC_getLength(core_mode_last != FD_SHORT,
1465*e5436536SAndroid Build Coastguard Worker                              pAacDecoderChannelInfo->granuleLength),
1466*e5436536SAndroid Build Coastguard Worker           1, 0);
1467*e5436536SAndroid Build Coastguard Worker       if (err != 0) {
1468*e5436536SAndroid Build Coastguard Worker         error = AAC_DEC_PARSE_ERROR;
1469*e5436536SAndroid Build Coastguard Worker         goto bail;
1470*e5436536SAndroid Build Coastguard Worker       }
1471*e5436536SAndroid Build Coastguard Worker     }
1472*e5436536SAndroid Build Coastguard Worker   }
1473*e5436536SAndroid Build Coastguard Worker 
1474*e5436536SAndroid Build Coastguard Worker bail:
1475*e5436536SAndroid Build Coastguard Worker   if (error == AAC_DEC_OK) {
1476*e5436536SAndroid Build Coastguard Worker     /* check consitency of last core/lpd mode values */
1477*e5436536SAndroid Build Coastguard Worker     if ((pAacDecoderChannelInfo->data.usac.core_mode_last !=
1478*e5436536SAndroid Build Coastguard Worker          pAacDecoderStaticChannelInfo->last_core_mode) &&
1479*e5436536SAndroid Build Coastguard Worker         (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) {
1480*e5436536SAndroid Build Coastguard Worker       /* Something got wrong! */
1481*e5436536SAndroid Build Coastguard Worker       /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */
1482*e5436536SAndroid Build Coastguard Worker     } else if ((pAacDecoderChannelInfo->data.usac.core_mode_last == LPD) &&
1483*e5436536SAndroid Build Coastguard Worker                (pAacDecoderChannelInfo->data.usac.lpd_mode_last !=
1484*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->last_lpd_mode) &&
1485*e5436536SAndroid Build Coastguard Worker                (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) {
1486*e5436536SAndroid Build Coastguard Worker       /* Something got wrong! */
1487*e5436536SAndroid Build Coastguard Worker       /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */
1488*e5436536SAndroid Build Coastguard Worker     }
1489*e5436536SAndroid Build Coastguard Worker   }
1490*e5436536SAndroid Build Coastguard Worker 
1491*e5436536SAndroid Build Coastguard Worker   return error;
1492*e5436536SAndroid Build Coastguard Worker }
1493*e5436536SAndroid Build Coastguard Worker 
CLpdChannelStream_Decode(CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,UINT flags)1494*e5436536SAndroid Build Coastguard Worker void CLpdChannelStream_Decode(
1495*e5436536SAndroid Build Coastguard Worker     CAacDecoderChannelInfo *pAacDecoderChannelInfo,
1496*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags) {
1497*e5436536SAndroid Build Coastguard Worker   UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod;
1498*e5436536SAndroid Build Coastguard Worker   int k;
1499*e5436536SAndroid Build Coastguard Worker   UCHAR last_lpd_mode;
1500*e5436536SAndroid Build Coastguard Worker   int nbDiv = NB_DIV;
1501*e5436536SAndroid Build Coastguard Worker 
1502*e5436536SAndroid Build Coastguard Worker   /* k is the frame index. If a frame is of size 40MS or 80MS,
1503*e5436536SAndroid Build Coastguard Worker      this frame index is incremented 2 or 4 instead of 1 respectively. */
1504*e5436536SAndroid Build Coastguard Worker   k = 0;
1505*e5436536SAndroid Build Coastguard Worker   last_lpd_mode =
1506*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac
1507*e5436536SAndroid Build Coastguard Worker           .lpd_mode_last; /* could be different to what has been rendered */
1508*e5436536SAndroid Build Coastguard Worker   while (k < nbDiv) {
1509*e5436536SAndroid Build Coastguard Worker     if (mod[k] == 0) {
1510*e5436536SAndroid Build Coastguard Worker       /* ACELP */
1511*e5436536SAndroid Build Coastguard Worker 
1512*e5436536SAndroid Build Coastguard Worker       /* If FAC (fac_data[k] != NULL), and previous frame was TCX, apply (TCX)
1513*e5436536SAndroid Build Coastguard Worker        * gains to FAC data */
1514*e5436536SAndroid Build Coastguard Worker       if (last_lpd_mode > 0 && last_lpd_mode != 255 &&
1515*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.fac_data[k]) {
1516*e5436536SAndroid Build Coastguard Worker         CFac_ApplyGains(pAacDecoderChannelInfo->data.usac.fac_data[k],
1517*e5436536SAndroid Build Coastguard Worker                         pAacDecoderChannelInfo->granuleLength,
1518*e5436536SAndroid Build Coastguard Worker                         pAacDecoderStaticChannelInfo->last_tcx_gain,
1519*e5436536SAndroid Build Coastguard Worker                         pAacDecoderStaticChannelInfo->last_alfd_gains,
1520*e5436536SAndroid Build Coastguard Worker                         (last_lpd_mode < 4) ? last_lpd_mode : 3);
1521*e5436536SAndroid Build Coastguard Worker 
1522*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.fac_data_e[k] +=
1523*e5436536SAndroid Build Coastguard Worker             pAacDecoderStaticChannelInfo->last_tcx_gain_e;
1524*e5436536SAndroid Build Coastguard Worker       }
1525*e5436536SAndroid Build Coastguard Worker     } else {
1526*e5436536SAndroid Build Coastguard Worker       /* TCX */
1527*e5436536SAndroid Build Coastguard Worker       CLpd_TcxDecode(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo,
1528*e5436536SAndroid Build Coastguard Worker                      flags, mod[k], last_lpd_mode, k, 1 /* frameOk == 1 */
1529*e5436536SAndroid Build Coastguard Worker       );
1530*e5436536SAndroid Build Coastguard Worker 
1531*e5436536SAndroid Build Coastguard Worker       /* Store TCX gain scale for next possible FAC transition. */
1532*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->last_tcx_gain =
1533*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.tcx_gain[k];
1534*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->last_tcx_gain_e =
1535*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.tcx_gain_e[k];
1536*e5436536SAndroid Build Coastguard Worker 
1537*e5436536SAndroid Build Coastguard Worker       /* If FAC (fac_data[k] != NULL), apply gains */
1538*e5436536SAndroid Build Coastguard Worker       if (last_lpd_mode == 0 && pAacDecoderChannelInfo->data.usac.fac_data[k]) {
1539*e5436536SAndroid Build Coastguard Worker         CFac_ApplyGains(
1540*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.fac_data[k],
1541*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->granuleLength /* == fac_length */,
1542*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.tcx_gain[k],
1543*e5436536SAndroid Build Coastguard Worker             pAacDecoderStaticChannelInfo->last_alfd_gains, mod[k]);
1544*e5436536SAndroid Build Coastguard Worker 
1545*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.fac_data_e[k] +=
1546*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.tcx_gain_e[k];
1547*e5436536SAndroid Build Coastguard Worker       }
1548*e5436536SAndroid Build Coastguard Worker     }
1549*e5436536SAndroid Build Coastguard Worker 
1550*e5436536SAndroid Build Coastguard Worker     /* remember previous mode */
1551*e5436536SAndroid Build Coastguard Worker     last_lpd_mode = mod[k];
1552*e5436536SAndroid Build Coastguard Worker 
1553*e5436536SAndroid Build Coastguard Worker     /* Increase k to next frame */
1554*e5436536SAndroid Build Coastguard Worker     k += (mod[k] == 0) ? 1 : (1 << (mod[k] - 1));
1555*e5436536SAndroid Build Coastguard Worker   }
1556*e5436536SAndroid Build Coastguard Worker }
1557*e5436536SAndroid Build Coastguard Worker 
CLpd_RenderTimeSignal(CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,CAacDecoderChannelInfo * pAacDecoderChannelInfo,PCM_DEC * pTimeData,INT lFrame,SamplingRateInfo * pSamplingRateInfo,UINT frameOk,const INT aacOutDataHeadroom,UINT flags,UINT strmFlags)1558*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR CLpd_RenderTimeSignal(
1559*e5436536SAndroid Build Coastguard Worker     CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1560*e5436536SAndroid Build Coastguard Worker     CAacDecoderChannelInfo *pAacDecoderChannelInfo, PCM_DEC *pTimeData,
1561*e5436536SAndroid Build Coastguard Worker     INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk,
1562*e5436536SAndroid Build Coastguard Worker     const INT aacOutDataHeadroom, UINT flags, UINT strmFlags) {
1563*e5436536SAndroid Build Coastguard Worker   UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod;
1564*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR error = AAC_DEC_OK;
1565*e5436536SAndroid Build Coastguard Worker   int k, i_offset;
1566*e5436536SAndroid Build Coastguard Worker   int last_k;
1567*e5436536SAndroid Build Coastguard Worker   int nrSamples = 0;
1568*e5436536SAndroid Build Coastguard Worker   int facFB = 1;
1569*e5436536SAndroid Build Coastguard Worker   int nbDiv = NB_DIV;
1570*e5436536SAndroid Build Coastguard Worker   int lDiv = lFrame / nbDiv; /* length of division (acelp or tcx20 frame)*/
1571*e5436536SAndroid Build Coastguard Worker   int lFac = lDiv / 2;
1572*e5436536SAndroid Build Coastguard Worker   int nbSubfr =
1573*e5436536SAndroid Build Coastguard Worker       lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */
1574*e5436536SAndroid Build Coastguard Worker   int nbSubfrSuperfr = nbDiv * nbSubfr;
1575*e5436536SAndroid Build Coastguard Worker   int synSfd = (nbSubfrSuperfr / 2) - BPF_SFD;
1576*e5436536SAndroid Build Coastguard Worker   int SynDelay = synSfd * L_SUBFR;
1577*e5436536SAndroid Build Coastguard Worker   int aacDelay = lFrame / 2;
1578*e5436536SAndroid Build Coastguard Worker 
1579*e5436536SAndroid Build Coastguard Worker   /*
1580*e5436536SAndroid Build Coastguard Worker    In respect to the reference software, the synth pointer here is lagging by
1581*e5436536SAndroid Build Coastguard Worker    aacDelay ( == SYN_DELAY + BPF_DELAY ) samples. The corresponding old
1582*e5436536SAndroid Build Coastguard Worker    synthesis samples are handled by the IMDCT overlap.
1583*e5436536SAndroid Build Coastguard Worker    */
1584*e5436536SAndroid Build Coastguard Worker 
1585*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *synth_buf =
1586*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->synth_buf;
1587*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *synth = synth_buf + PIT_MAX_MAX - BPF_DELAY;
1588*e5436536SAndroid Build Coastguard Worker   UCHAR last_lpd_mode, last_last_lpd_mode, last_lpc_lost, last_frame_lost;
1589*e5436536SAndroid Build Coastguard Worker 
1590*e5436536SAndroid Build Coastguard Worker   INT pitch[NB_SUBFR_SUPERFR + SYN_SFD];
1591*e5436536SAndroid Build Coastguard Worker   FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD];
1592*e5436536SAndroid Build Coastguard Worker 
1593*e5436536SAndroid Build Coastguard Worker   const int *lg_table;
1594*e5436536SAndroid Build Coastguard Worker   int lg_table_offset = 0;
1595*e5436536SAndroid Build Coastguard Worker 
1596*e5436536SAndroid Build Coastguard Worker   UINT samplingRate = pSamplingRateInfo->samplingRate;
1597*e5436536SAndroid Build Coastguard Worker 
1598*e5436536SAndroid Build Coastguard Worker   FDKmemclear(pitch, (NB_SUBFR_SUPERFR + SYN_SFD) * sizeof(INT));
1599*e5436536SAndroid Build Coastguard Worker 
1600*e5436536SAndroid Build Coastguard Worker   if (flags & AACDEC_FLUSH) {
1601*e5436536SAndroid Build Coastguard Worker     CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo,
1602*e5436536SAndroid Build Coastguard Worker                flags & AACDEC_FLUSH);
1603*e5436536SAndroid Build Coastguard Worker     frameOk = 0;
1604*e5436536SAndroid Build Coastguard Worker   }
1605*e5436536SAndroid Build Coastguard Worker 
1606*e5436536SAndroid Build Coastguard Worker   switch (lFrame) {
1607*e5436536SAndroid Build Coastguard Worker     case 1024:
1608*e5436536SAndroid Build Coastguard Worker       lg_table = &lg_table_ccfl[0][lg_table_offset];
1609*e5436536SAndroid Build Coastguard Worker       break;
1610*e5436536SAndroid Build Coastguard Worker     case 768:
1611*e5436536SAndroid Build Coastguard Worker       lg_table = &lg_table_ccfl[1][lg_table_offset];
1612*e5436536SAndroid Build Coastguard Worker       break;
1613*e5436536SAndroid Build Coastguard Worker     default:
1614*e5436536SAndroid Build Coastguard Worker       FDK_ASSERT(0);
1615*e5436536SAndroid Build Coastguard Worker       return AAC_DEC_UNKNOWN;
1616*e5436536SAndroid Build Coastguard Worker   }
1617*e5436536SAndroid Build Coastguard Worker 
1618*e5436536SAndroid Build Coastguard Worker   last_frame_lost = !CConcealment_GetLastFrameOk(
1619*e5436536SAndroid Build Coastguard Worker       &pAacDecoderStaticChannelInfo->concealmentInfo, 0);
1620*e5436536SAndroid Build Coastguard Worker 
1621*e5436536SAndroid Build Coastguard Worker   /* Maintain LPD mode from previous frame */
1622*e5436536SAndroid Build Coastguard Worker   if ((pAacDecoderStaticChannelInfo->last_core_mode == FD_LONG) ||
1623*e5436536SAndroid Build Coastguard Worker       (pAacDecoderStaticChannelInfo->last_core_mode == FD_SHORT)) {
1624*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->last_lpd_mode = 255;
1625*e5436536SAndroid Build Coastguard Worker   }
1626*e5436536SAndroid Build Coastguard Worker 
1627*e5436536SAndroid Build Coastguard Worker   if (!frameOk) {
1628*e5436536SAndroid Build Coastguard Worker     FIXP_DBL old_tcx_gain;
1629*e5436536SAndroid Build Coastguard Worker     FIXP_SGL old_stab;
1630*e5436536SAndroid Build Coastguard Worker     SCHAR old_tcx_gain_e;
1631*e5436536SAndroid Build Coastguard Worker     int nLostSf;
1632*e5436536SAndroid Build Coastguard Worker 
1633*e5436536SAndroid Build Coastguard Worker     last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode;
1634*e5436536SAndroid Build Coastguard Worker     old_tcx_gain = pAacDecoderStaticChannelInfo->last_tcx_gain;
1635*e5436536SAndroid Build Coastguard Worker     old_tcx_gain_e = pAacDecoderStaticChannelInfo->last_tcx_gain_e;
1636*e5436536SAndroid Build Coastguard Worker     old_stab = pAacDecoderStaticChannelInfo->oldStability;
1637*e5436536SAndroid Build Coastguard Worker     nLostSf = pAacDecoderStaticChannelInfo->numLostLpdFrames;
1638*e5436536SAndroid Build Coastguard Worker 
1639*e5436536SAndroid Build Coastguard Worker     /* patch the last LPD mode */
1640*e5436536SAndroid Build Coastguard Worker     pAacDecoderChannelInfo->data.usac.lpd_mode_last = last_lpd_mode;
1641*e5436536SAndroid Build Coastguard Worker 
1642*e5436536SAndroid Build Coastguard Worker     /* Do mode extrapolation and repeat the previous mode:
1643*e5436536SAndroid Build Coastguard Worker        if previous mode = ACELP        -> ACELP
1644*e5436536SAndroid Build Coastguard Worker        if previous mode = TCX-20/40    -> TCX-20
1645*e5436536SAndroid Build Coastguard Worker        if previous mode = TCX-80       -> TCX-80
1646*e5436536SAndroid Build Coastguard Worker        notes:
1647*e5436536SAndroid Build Coastguard Worker        - ACELP is not allowed after TCX (no pitch information to reuse)
1648*e5436536SAndroid Build Coastguard Worker        - TCX-40 is not allowed in the mode repetition to keep the logic simple
1649*e5436536SAndroid Build Coastguard Worker      */
1650*e5436536SAndroid Build Coastguard Worker     switch (last_lpd_mode) {
1651*e5436536SAndroid Build Coastguard Worker       case 0:
1652*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 0; /* -> ACELP concealment */
1653*e5436536SAndroid Build Coastguard Worker         break;
1654*e5436536SAndroid Build Coastguard Worker       case 3:
1655*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 3; /* -> TCX FD concealment */
1656*e5436536SAndroid Build Coastguard Worker         break;
1657*e5436536SAndroid Build Coastguard Worker       case 2:
1658*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 2; /* -> TCX FD concealment */
1659*e5436536SAndroid Build Coastguard Worker         break;
1660*e5436536SAndroid Build Coastguard Worker       case 1:
1661*e5436536SAndroid Build Coastguard Worker       default:
1662*e5436536SAndroid Build Coastguard Worker         mod[0] = mod[1] = mod[2] = mod[3] = 4; /* -> TCX TD concealment */
1663*e5436536SAndroid Build Coastguard Worker         break;
1664*e5436536SAndroid Build Coastguard Worker     }
1665*e5436536SAndroid Build Coastguard Worker 
1666*e5436536SAndroid Build Coastguard Worker     /* LPC extrapolation */
1667*e5436536SAndroid Build Coastguard Worker     CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff,
1668*e5436536SAndroid Build Coastguard Worker                  pAacDecoderStaticChannelInfo->lpc4_lsf,
1669*e5436536SAndroid Build Coastguard Worker                  pAacDecoderStaticChannelInfo->lsf_adaptive_mean,
1670*e5436536SAndroid Build Coastguard Worker                  /*(pAacDecoderStaticChannelInfo->numLostLpdFrames == 0) ||*/
1671*e5436536SAndroid Build Coastguard Worker                  (last_lpd_mode == 255));
1672*e5436536SAndroid Build Coastguard Worker 
1673*e5436536SAndroid Build Coastguard Worker     if ((last_lpd_mode > 0) && (last_lpd_mode < 255)) {
1674*e5436536SAndroid Build Coastguard Worker       /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid
1675*e5436536SAndroid Build Coastguard Worker        * converting LSP coefficients again). */
1676*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0],
1677*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->lp_coeff_old[0],
1678*e5436536SAndroid Build Coastguard Worker                 M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1679*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] =
1680*e5436536SAndroid Build Coastguard Worker           pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0];
1681*e5436536SAndroid Build Coastguard Worker     } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */
1682*e5436536SAndroid Build Coastguard Worker     /* case last_lpd_mode was Time domain TCX concealment is handled after this
1683*e5436536SAndroid Build Coastguard Worker      * "if (!frameOk)"-block */
1684*e5436536SAndroid Build Coastguard Worker 
1685*e5436536SAndroid Build Coastguard Worker     /* k is the frame index. If a frame is of size 40MS or 80MS,
1686*e5436536SAndroid Build Coastguard Worker        this frame index is incremented 2 or 4 instead of 1 respectively. */
1687*e5436536SAndroid Build Coastguard Worker     k = 0;
1688*e5436536SAndroid Build Coastguard Worker     while (k < nbDiv) {
1689*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.tcx_gain[k] = old_tcx_gain;
1690*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] = old_tcx_gain_e;
1691*e5436536SAndroid Build Coastguard Worker 
1692*e5436536SAndroid Build Coastguard Worker       /* restore stability value from last frame */
1693*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.aStability[k] = old_stab;
1694*e5436536SAndroid Build Coastguard Worker 
1695*e5436536SAndroid Build Coastguard Worker       /* Increase k to next frame */
1696*e5436536SAndroid Build Coastguard Worker       k += ((mod[k] & 0x3) == 0) ? 1 : (1 << ((mod[k] & 0x3) - 1));
1697*e5436536SAndroid Build Coastguard Worker 
1698*e5436536SAndroid Build Coastguard Worker       nLostSf++;
1699*e5436536SAndroid Build Coastguard Worker     }
1700*e5436536SAndroid Build Coastguard Worker   } else {
1701*e5436536SAndroid Build Coastguard Worker     if ((pAacDecoderStaticChannelInfo->last_lpd_mode == 4) && (mod[0] > 0)) {
1702*e5436536SAndroid Build Coastguard Worker       /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid
1703*e5436536SAndroid Build Coastguard Worker        * converting LSP coefficients again). */
1704*e5436536SAndroid Build Coastguard Worker       FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0],
1705*e5436536SAndroid Build Coastguard Worker                 pAacDecoderStaticChannelInfo->lp_coeff_old[0],
1706*e5436536SAndroid Build Coastguard Worker                 M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1707*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] =
1708*e5436536SAndroid Build Coastguard Worker           pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0];
1709*e5436536SAndroid Build Coastguard Worker     }
1710*e5436536SAndroid Build Coastguard Worker   }
1711*e5436536SAndroid Build Coastguard Worker 
1712*e5436536SAndroid Build Coastguard Worker   Acelp_PreProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth, pitch,
1713*e5436536SAndroid Build Coastguard Worker                       pAacDecoderStaticChannelInfo->old_T_pf, pit_gain,
1714*e5436536SAndroid Build Coastguard Worker                       pAacDecoderStaticChannelInfo->old_gain_pf, samplingRate,
1715*e5436536SAndroid Build Coastguard Worker                       &i_offset, lFrame, synSfd, nbSubfrSuperfr);
1716*e5436536SAndroid Build Coastguard Worker 
1717*e5436536SAndroid Build Coastguard Worker   /* k is the frame index. If a frame is of size 40MS or 80MS,
1718*e5436536SAndroid Build Coastguard Worker      this frame index is incremented 2 or 4 instead of 1 respectively. */
1719*e5436536SAndroid Build Coastguard Worker   k = 0;
1720*e5436536SAndroid Build Coastguard Worker   last_k = -1; /* mark invalid */
1721*e5436536SAndroid Build Coastguard Worker   last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode;
1722*e5436536SAndroid Build Coastguard Worker   last_last_lpd_mode = pAacDecoderStaticChannelInfo->last_last_lpd_mode;
1723*e5436536SAndroid Build Coastguard Worker   last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost | last_frame_lost;
1724*e5436536SAndroid Build Coastguard Worker 
1725*e5436536SAndroid Build Coastguard Worker   /* This buffer must be avalable for the case of FD->ACELP transition. The
1726*e5436536SAndroid Build Coastguard Worker   beginning of the buffer is used after the BPF to overwrite the output signal.
1727*e5436536SAndroid Build Coastguard Worker   Only the FAC area must be affected by the BPF */
1728*e5436536SAndroid Build Coastguard Worker 
1729*e5436536SAndroid Build Coastguard Worker   while (k < nbDiv) {
1730*e5436536SAndroid Build Coastguard Worker     if (frameOk == 0) {
1731*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->numLostLpdFrames++;
1732*e5436536SAndroid Build Coastguard Worker     } else {
1733*e5436536SAndroid Build Coastguard Worker       last_frame_lost |=
1734*e5436536SAndroid Build Coastguard Worker           (pAacDecoderStaticChannelInfo->numLostLpdFrames > 0) ? 1 : 0;
1735*e5436536SAndroid Build Coastguard Worker       pAacDecoderStaticChannelInfo->numLostLpdFrames = 0;
1736*e5436536SAndroid Build Coastguard Worker     }
1737*e5436536SAndroid Build Coastguard Worker     if (mod[k] == 0 || mod[k] == 4) {
1738*e5436536SAndroid Build Coastguard Worker       /* ACELP or TCX time domain concealment */
1739*e5436536SAndroid Build Coastguard Worker       FIXP_DBL *acelp_out;
1740*e5436536SAndroid Build Coastguard Worker 
1741*e5436536SAndroid Build Coastguard Worker       /* FAC management */
1742*e5436536SAndroid Build Coastguard Worker       if ((last_lpd_mode != 0) && (last_lpd_mode != 4)) /* TCX TD concealment */
1743*e5436536SAndroid Build Coastguard Worker       {
1744*e5436536SAndroid Build Coastguard Worker         FIXP_DBL *pFacData = NULL;
1745*e5436536SAndroid Build Coastguard Worker 
1746*e5436536SAndroid Build Coastguard Worker         if (frameOk && !last_frame_lost) {
1747*e5436536SAndroid Build Coastguard Worker           pFacData = pAacDecoderChannelInfo->data.usac.fac_data[k];
1748*e5436536SAndroid Build Coastguard Worker         }
1749*e5436536SAndroid Build Coastguard Worker 
1750*e5436536SAndroid Build Coastguard Worker         nrSamples += CLpd_FAC_Mdct2Acelp(
1751*e5436536SAndroid Build Coastguard Worker             &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, pFacData,
1752*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.fac_data_e[k],
1753*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.lp_coeff[k],
1754*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k],
1755*e5436536SAndroid Build Coastguard Worker             lFrame - nrSamples,
1756*e5436536SAndroid Build Coastguard Worker             CLpd_FAC_getLength(
1757*e5436536SAndroid Build Coastguard Worker                 (pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) ||
1758*e5436536SAndroid Build Coastguard Worker                     (k > 0),
1759*e5436536SAndroid Build Coastguard Worker                 lFac),
1760*e5436536SAndroid Build Coastguard Worker             (pAacDecoderStaticChannelInfo->last_core_mode != LPD) && (k == 0),
1761*e5436536SAndroid Build Coastguard Worker             0);
1762*e5436536SAndroid Build Coastguard Worker 
1763*e5436536SAndroid Build Coastguard Worker         FDKmemcpy(
1764*e5436536SAndroid Build Coastguard Worker             synth + nrSamples, pAacDecoderStaticChannelInfo->IMdct.overlap.time,
1765*e5436536SAndroid Build Coastguard Worker             pAacDecoderStaticChannelInfo->IMdct.ov_offset * sizeof(FIXP_DBL));
1766*e5436536SAndroid Build Coastguard Worker         {
1767*e5436536SAndroid Build Coastguard Worker           FIXP_LPC *lp_prev =
1768*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac
1769*e5436536SAndroid Build Coastguard Worker                   .lp_coeff[0]; /* init value does not real matter */
1770*e5436536SAndroid Build Coastguard Worker           INT lp_prev_exp = pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0];
1771*e5436536SAndroid Build Coastguard Worker 
1772*e5436536SAndroid Build Coastguard Worker           if (last_lpd_mode != 255) { /* last mode was tcx */
1773*e5436536SAndroid Build Coastguard Worker             last_k = k - (1 << (last_lpd_mode - 1));
1774*e5436536SAndroid Build Coastguard Worker             if (last_k < 0) {
1775*e5436536SAndroid Build Coastguard Worker               lp_prev = pAacDecoderStaticChannelInfo->lp_coeff_old[1];
1776*e5436536SAndroid Build Coastguard Worker               lp_prev_exp = pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1];
1777*e5436536SAndroid Build Coastguard Worker             } else {
1778*e5436536SAndroid Build Coastguard Worker               lp_prev = pAacDecoderChannelInfo->data.usac.lp_coeff[last_k];
1779*e5436536SAndroid Build Coastguard Worker               lp_prev_exp =
1780*e5436536SAndroid Build Coastguard Worker                   pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k];
1781*e5436536SAndroid Build Coastguard Worker             }
1782*e5436536SAndroid Build Coastguard Worker           }
1783*e5436536SAndroid Build Coastguard Worker 
1784*e5436536SAndroid Build Coastguard Worker           CLpd_AcelpPrepareInternalMem(
1785*e5436536SAndroid Build Coastguard Worker               synth + aacDelay + k * lDiv, last_lpd_mode,
1786*e5436536SAndroid Build Coastguard Worker               (last_last_lpd_mode == 4) ? 0 : last_last_lpd_mode,
1787*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac.lp_coeff[k],
1788*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], lp_prev,
1789*e5436536SAndroid Build Coastguard Worker               lp_prev_exp, &pAacDecoderStaticChannelInfo->acelp, lFrame,
1790*e5436536SAndroid Build Coastguard Worker               (last_frame_lost && k < 2), mod[k]);
1791*e5436536SAndroid Build Coastguard Worker         }
1792*e5436536SAndroid Build Coastguard Worker       } else {
1793*e5436536SAndroid Build Coastguard Worker         if (k == 0 && pAacDecoderStaticChannelInfo->IMdct.ov_offset !=
1794*e5436536SAndroid Build Coastguard Worker                           lFrame / facFB / 2) {
1795*e5436536SAndroid Build Coastguard Worker           pAacDecoderStaticChannelInfo->IMdct.ov_offset = lFrame / facFB / 2;
1796*e5436536SAndroid Build Coastguard Worker         }
1797*e5436536SAndroid Build Coastguard Worker         nrSamples += imdct_drain(&pAacDecoderStaticChannelInfo->IMdct,
1798*e5436536SAndroid Build Coastguard Worker                                  synth + nrSamples, lFrame / facFB - nrSamples);
1799*e5436536SAndroid Build Coastguard Worker       }
1800*e5436536SAndroid Build Coastguard Worker 
1801*e5436536SAndroid Build Coastguard Worker       if (nrSamples >= lFrame / facFB) {
1802*e5436536SAndroid Build Coastguard Worker         /* Write ACELP time domain samples into IMDCT overlap buffer at
1803*e5436536SAndroid Build Coastguard Worker          * pAacDecoderStaticChannelInfo->IMdct.overlap.time +
1804*e5436536SAndroid Build Coastguard Worker          * pAacDecoderStaticChannelInfo->IMdct.ov_offset
1805*e5436536SAndroid Build Coastguard Worker          */
1806*e5436536SAndroid Build Coastguard Worker         acelp_out = pAacDecoderStaticChannelInfo->IMdct.overlap.time +
1807*e5436536SAndroid Build Coastguard Worker                     pAacDecoderStaticChannelInfo->IMdct.ov_offset;
1808*e5436536SAndroid Build Coastguard Worker 
1809*e5436536SAndroid Build Coastguard Worker         /* Account ACELP time domain output samples to overlap buffer */
1810*e5436536SAndroid Build Coastguard Worker         pAacDecoderStaticChannelInfo->IMdct.ov_offset += lDiv;
1811*e5436536SAndroid Build Coastguard Worker       } else {
1812*e5436536SAndroid Build Coastguard Worker         /* Write ACELP time domain samples into output buffer at pTimeData +
1813*e5436536SAndroid Build Coastguard Worker          * nrSamples */
1814*e5436536SAndroid Build Coastguard Worker         acelp_out = synth + nrSamples;
1815*e5436536SAndroid Build Coastguard Worker 
1816*e5436536SAndroid Build Coastguard Worker         /* Account ACELP time domain output samples to output buffer */
1817*e5436536SAndroid Build Coastguard Worker         nrSamples += lDiv;
1818*e5436536SAndroid Build Coastguard Worker       }
1819*e5436536SAndroid Build Coastguard Worker 
1820*e5436536SAndroid Build Coastguard Worker       if (mod[k] == 4) {
1821*e5436536SAndroid Build Coastguard Worker         pAacDecoderStaticChannelInfo->acelp.wsyn_rms = scaleValue(
1822*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.tcx_gain[k],
1823*e5436536SAndroid Build Coastguard Worker             fixMin(0,
1824*e5436536SAndroid Build Coastguard Worker                    pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] - SF_EXC));
1825*e5436536SAndroid Build Coastguard Worker         CLpd_TcxTDConceal(&pAacDecoderStaticChannelInfo->acelp,
1826*e5436536SAndroid Build Coastguard Worker                           &pAacDecoderStaticChannelInfo->last_tcx_pitch,
1827*e5436536SAndroid Build Coastguard Worker                           pAacDecoderChannelInfo->data.usac.lsp_coeff[k],
1828*e5436536SAndroid Build Coastguard Worker                           pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1],
1829*e5436536SAndroid Build Coastguard Worker                           pAacDecoderChannelInfo->data.usac.aStability[k],
1830*e5436536SAndroid Build Coastguard Worker                           pAacDecoderStaticChannelInfo->numLostLpdFrames,
1831*e5436536SAndroid Build Coastguard Worker                           acelp_out, lFrame,
1832*e5436536SAndroid Build Coastguard Worker                           pAacDecoderStaticChannelInfo->last_tcx_noise_factor);
1833*e5436536SAndroid Build Coastguard Worker 
1834*e5436536SAndroid Build Coastguard Worker       } else {
1835*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[k] >=
1836*e5436536SAndroid Build Coastguard Worker                    (FIXP_SGL)0);
1837*e5436536SAndroid Build Coastguard Worker         CLpd_AcelpDecode(&pAacDecoderStaticChannelInfo->acelp, i_offset,
1838*e5436536SAndroid Build Coastguard Worker                          pAacDecoderChannelInfo->data.usac.lsp_coeff[k],
1839*e5436536SAndroid Build Coastguard Worker                          pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1],
1840*e5436536SAndroid Build Coastguard Worker                          pAacDecoderChannelInfo->data.usac.aStability[k],
1841*e5436536SAndroid Build Coastguard Worker                          &pAacDecoderChannelInfo->data.usac.acelp[k],
1842*e5436536SAndroid Build Coastguard Worker                          pAacDecoderStaticChannelInfo->numLostLpdFrames,
1843*e5436536SAndroid Build Coastguard Worker                          last_lpc_lost, k, acelp_out,
1844*e5436536SAndroid Build Coastguard Worker                          &pitch[(k * nbSubfr) + synSfd],
1845*e5436536SAndroid Build Coastguard Worker                          &pit_gain[(k * nbSubfr) + synSfd], lFrame);
1846*e5436536SAndroid Build Coastguard Worker       }
1847*e5436536SAndroid Build Coastguard Worker 
1848*e5436536SAndroid Build Coastguard Worker       if (mod[k] != 4) {
1849*e5436536SAndroid Build Coastguard Worker         if (last_lpd_mode != 0 &&
1850*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac
1851*e5436536SAndroid Build Coastguard Worker                 .bpf_control_info) { /* FD/TCX -> ACELP transition */
1852*e5436536SAndroid Build Coastguard Worker           /* bass post-filter past FAC area (past two (one for FD short)
1853*e5436536SAndroid Build Coastguard Worker            * subframes) */
1854*e5436536SAndroid Build Coastguard Worker           int currentSf = synSfd + k * nbSubfr;
1855*e5436536SAndroid Build Coastguard Worker 
1856*e5436536SAndroid Build Coastguard Worker           if ((k > 0) || (pAacDecoderStaticChannelInfo->last_core_mode !=
1857*e5436536SAndroid Build Coastguard Worker                           FD_SHORT)) { /* TCX or FD long -> ACELP */
1858*e5436536SAndroid Build Coastguard Worker             pitch[currentSf - 2] = pitch[currentSf - 1] = pitch[currentSf];
1859*e5436536SAndroid Build Coastguard Worker             pit_gain[currentSf - 2] = pit_gain[currentSf - 1] =
1860*e5436536SAndroid Build Coastguard Worker                 pit_gain[currentSf];
1861*e5436536SAndroid Build Coastguard Worker           } else { /* FD short -> ACELP */
1862*e5436536SAndroid Build Coastguard Worker             pitch[currentSf - 1] = pitch[currentSf];
1863*e5436536SAndroid Build Coastguard Worker             pit_gain[currentSf - 1] = pit_gain[currentSf];
1864*e5436536SAndroid Build Coastguard Worker           }
1865*e5436536SAndroid Build Coastguard Worker         }
1866*e5436536SAndroid Build Coastguard Worker       }
1867*e5436536SAndroid Build Coastguard Worker     } else { /* TCX */
1868*e5436536SAndroid Build Coastguard Worker       int lg = lg_table[mod[k]];
1869*e5436536SAndroid Build Coastguard Worker       int isFullBandLpd = 0;
1870*e5436536SAndroid Build Coastguard Worker 
1871*e5436536SAndroid Build Coastguard Worker       /* FAC management */
1872*e5436536SAndroid Build Coastguard Worker       if ((last_lpd_mode == 0) || (last_lpd_mode == 4)) /* TCX TD concealment */
1873*e5436536SAndroid Build Coastguard Worker       {
1874*e5436536SAndroid Build Coastguard Worker         C_AALLOC_SCRATCH_START(fac_buf, FIXP_DBL, 1024 / 8);
1875*e5436536SAndroid Build Coastguard Worker 
1876*e5436536SAndroid Build Coastguard Worker         /* pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL means no FAC
1877*e5436536SAndroid Build Coastguard Worker          * data available. */
1878*e5436536SAndroid Build Coastguard Worker         if (last_frame_lost == 1 ||
1879*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL) {
1880*e5436536SAndroid Build Coastguard Worker           FDKmemclear(fac_buf, 1024 / 8 * sizeof(FIXP_DBL));
1881*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.fac_data[k] = fac_buf;
1882*e5436536SAndroid Build Coastguard Worker           pAacDecoderChannelInfo->data.usac.fac_data_e[k] = 0;
1883*e5436536SAndroid Build Coastguard Worker         }
1884*e5436536SAndroid Build Coastguard Worker 
1885*e5436536SAndroid Build Coastguard Worker         nrSamples += CLpd_FAC_Acelp2Mdct(
1886*e5436536SAndroid Build Coastguard Worker             &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples,
1887*e5436536SAndroid Build Coastguard Worker             SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k,
1888*e5436536SAndroid Build Coastguard Worker                      pAacDecoderChannelInfo->granuleLength, isFullBandLpd),
1889*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->specScale + k, 1,
1890*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.fac_data[k],
1891*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.fac_data_e[k],
1892*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->granuleLength /* == fac_length */,
1893*e5436536SAndroid Build Coastguard Worker             lFrame - nrSamples, lg,
1894*e5436536SAndroid Build Coastguard Worker             FDKgetWindowSlope(lDiv,
1895*e5436536SAndroid Build Coastguard Worker                               GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
1896*e5436536SAndroid Build Coastguard Worker             lDiv, pAacDecoderChannelInfo->data.usac.lp_coeff[k],
1897*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k],
1898*e5436536SAndroid Build Coastguard Worker             &pAacDecoderStaticChannelInfo->acelp,
1899*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->data.usac.tcx_gain[k],
1900*e5436536SAndroid Build Coastguard Worker             (last_frame_lost || !frameOk), 0 /* is not FD FAC */
1901*e5436536SAndroid Build Coastguard Worker             ,
1902*e5436536SAndroid Build Coastguard Worker             last_lpd_mode, k,
1903*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo
1904*e5436536SAndroid Build Coastguard Worker                 ->currAliasingSymmetry /* Note: The current aliasing
1905*e5436536SAndroid Build Coastguard Worker                                           symmetry for a TCX (i.e. LPD)
1906*e5436536SAndroid Build Coastguard Worker                                           frame must always be 0 */
1907*e5436536SAndroid Build Coastguard Worker         );
1908*e5436536SAndroid Build Coastguard Worker 
1909*e5436536SAndroid Build Coastguard Worker         pitch[(k * nbSubfr) + synSfd + 1] = pitch[(k * nbSubfr) + synSfd] =
1910*e5436536SAndroid Build Coastguard Worker             pitch[(k * nbSubfr) + synSfd - 1];
1911*e5436536SAndroid Build Coastguard Worker         pit_gain[(k * nbSubfr) + synSfd + 1] =
1912*e5436536SAndroid Build Coastguard Worker             pit_gain[(k * nbSubfr) + synSfd] =
1913*e5436536SAndroid Build Coastguard Worker                 pit_gain[(k * nbSubfr) + synSfd - 1];
1914*e5436536SAndroid Build Coastguard Worker 
1915*e5436536SAndroid Build Coastguard Worker         C_AALLOC_SCRATCH_END(fac_buf, FIXP_DBL, 1024 / 8);
1916*e5436536SAndroid Build Coastguard Worker       } else {
1917*e5436536SAndroid Build Coastguard Worker         int tl = lg;
1918*e5436536SAndroid Build Coastguard Worker         int fl = lDiv;
1919*e5436536SAndroid Build Coastguard Worker         int fr = lDiv;
1920*e5436536SAndroid Build Coastguard Worker 
1921*e5436536SAndroid Build Coastguard Worker         nrSamples += imlt_block(
1922*e5436536SAndroid Build Coastguard Worker             &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples,
1923*e5436536SAndroid Build Coastguard Worker             SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k,
1924*e5436536SAndroid Build Coastguard Worker                      pAacDecoderChannelInfo->granuleLength, isFullBandLpd),
1925*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->specScale + k, 1, lFrame - nrSamples, tl,
1926*e5436536SAndroid Build Coastguard Worker             FDKgetWindowSlope(fl,
1927*e5436536SAndroid Build Coastguard Worker                               GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
1928*e5436536SAndroid Build Coastguard Worker             fl,
1929*e5436536SAndroid Build Coastguard Worker             FDKgetWindowSlope(fr,
1930*e5436536SAndroid Build Coastguard Worker                               GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
1931*e5436536SAndroid Build Coastguard Worker             fr, pAacDecoderChannelInfo->data.usac.tcx_gain[k],
1932*e5436536SAndroid Build Coastguard Worker             pAacDecoderChannelInfo->currAliasingSymmetry
1933*e5436536SAndroid Build Coastguard Worker                 ? MLT_FLAG_CURR_ALIAS_SYMMETRY
1934*e5436536SAndroid Build Coastguard Worker                 : 0);
1935*e5436536SAndroid Build Coastguard Worker       }
1936*e5436536SAndroid Build Coastguard Worker     }
1937*e5436536SAndroid Build Coastguard Worker     /* remember previous mode */
1938*e5436536SAndroid Build Coastguard Worker     last_last_lpd_mode = last_lpd_mode;
1939*e5436536SAndroid Build Coastguard Worker     last_lpd_mode = mod[k];
1940*e5436536SAndroid Build Coastguard Worker     last_lpc_lost = (frameOk == 0) ? 1 : 0;
1941*e5436536SAndroid Build Coastguard Worker 
1942*e5436536SAndroid Build Coastguard Worker     /* Increase k to next frame */
1943*e5436536SAndroid Build Coastguard Worker     last_k = k;
1944*e5436536SAndroid Build Coastguard Worker     k += ((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1));
1945*e5436536SAndroid Build Coastguard Worker   }
1946*e5436536SAndroid Build Coastguard Worker 
1947*e5436536SAndroid Build Coastguard Worker   if (frameOk) {
1948*e5436536SAndroid Build Coastguard Worker     /* assume data was ok => store for concealment */
1949*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[last_k] >=
1950*e5436536SAndroid Build Coastguard Worker                (FIXP_SGL)0);
1951*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->oldStability =
1952*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.aStability[last_k];
1953*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(pAacDecoderStaticChannelInfo->lsf_adaptive_mean,
1954*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand,
1955*e5436536SAndroid Build Coastguard Worker               M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1956*e5436536SAndroid Build Coastguard Worker   }
1957*e5436536SAndroid Build Coastguard Worker 
1958*e5436536SAndroid Build Coastguard Worker   /* store past lp coeffs for next superframe (they are only valid and needed if
1959*e5436536SAndroid Build Coastguard Worker    * last_lpd_mode was tcx) */
1960*e5436536SAndroid Build Coastguard Worker   if (last_lpd_mode > 0) {
1961*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[0],
1962*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac.lp_coeff[nbDiv],
1963*e5436536SAndroid Build Coastguard Worker               M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1964*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0] =
1965*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff_exp[nbDiv];
1966*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[1],
1967*e5436536SAndroid Build Coastguard Worker               pAacDecoderChannelInfo->data.usac.lp_coeff[last_k],
1968*e5436536SAndroid Build Coastguard Worker               M_LP_FILTER_ORDER * sizeof(FIXP_LPC));
1969*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1] =
1970*e5436536SAndroid Build Coastguard Worker         pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k];
1971*e5436536SAndroid Build Coastguard Worker   }
1972*e5436536SAndroid Build Coastguard Worker 
1973*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(nrSamples == lFrame);
1974*e5436536SAndroid Build Coastguard Worker 
1975*e5436536SAndroid Build Coastguard Worker   /* check whether usage of bass postfilter was de-activated in the bitstream;
1976*e5436536SAndroid Build Coastguard Worker    if yes, set pitch gain to 0 */
1977*e5436536SAndroid Build Coastguard Worker   if (!(pAacDecoderChannelInfo->data.usac.bpf_control_info)) {
1978*e5436536SAndroid Build Coastguard Worker     if (mod[0] != 0 && (pAacDecoderStaticChannelInfo->old_bpf_control_info)) {
1979*e5436536SAndroid Build Coastguard Worker       for (int i = 2; i < nbSubfrSuperfr; i++)
1980*e5436536SAndroid Build Coastguard Worker         pit_gain[synSfd + i] = (FIXP_DBL)0;
1981*e5436536SAndroid Build Coastguard Worker     } else {
1982*e5436536SAndroid Build Coastguard Worker       for (int i = 0; i < nbSubfrSuperfr; i++)
1983*e5436536SAndroid Build Coastguard Worker         pit_gain[synSfd + i] = (FIXP_DBL)0;
1984*e5436536SAndroid Build Coastguard Worker     }
1985*e5436536SAndroid Build Coastguard Worker   }
1986*e5436536SAndroid Build Coastguard Worker 
1987*e5436536SAndroid Build Coastguard Worker   /* for bass postfilter */
1988*e5436536SAndroid Build Coastguard Worker   for (int n = 0; n < synSfd; n++) {
1989*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->old_T_pf[n] = pitch[nbSubfrSuperfr + n];
1990*e5436536SAndroid Build Coastguard Worker     pAacDecoderStaticChannelInfo->old_gain_pf[n] = pit_gain[nbSubfrSuperfr + n];
1991*e5436536SAndroid Build Coastguard Worker   }
1992*e5436536SAndroid Build Coastguard Worker 
1993*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->old_bpf_control_info =
1994*e5436536SAndroid Build Coastguard Worker       pAacDecoderChannelInfo->data.usac.bpf_control_info;
1995*e5436536SAndroid Build Coastguard Worker 
1996*e5436536SAndroid Build Coastguard Worker   {
1997*e5436536SAndroid Build Coastguard Worker     INT lookahead = -BPF_DELAY;
1998*e5436536SAndroid Build Coastguard Worker     int copySamp = (mod[nbDiv - 1] == 0) ? (aacDelay) : (aacDelay - lFac);
1999*e5436536SAndroid Build Coastguard Worker 
2000*e5436536SAndroid Build Coastguard Worker     /* Copy enough time domain samples from MDCT to synthesis buffer as needed
2001*e5436536SAndroid Build Coastguard Worker      * by the bass postfilter */
2002*e5436536SAndroid Build Coastguard Worker 
2003*e5436536SAndroid Build Coastguard Worker     lookahead += imdct_copy_ov_and_nr(&pAacDecoderStaticChannelInfo->IMdct,
2004*e5436536SAndroid Build Coastguard Worker                                       synth + nrSamples, copySamp);
2005*e5436536SAndroid Build Coastguard Worker 
2006*e5436536SAndroid Build Coastguard Worker     FDK_ASSERT(lookahead == copySamp - BPF_DELAY);
2007*e5436536SAndroid Build Coastguard Worker 
2008*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *p2_synth = synth + BPF_DELAY;
2009*e5436536SAndroid Build Coastguard Worker 
2010*e5436536SAndroid Build Coastguard Worker     /* recalculate pitch gain to allow postfilering on FAC area */
2011*e5436536SAndroid Build Coastguard Worker     for (int i = 0; i < nbSubfrSuperfr; i++) {
2012*e5436536SAndroid Build Coastguard Worker       int T = pitch[i];
2013*e5436536SAndroid Build Coastguard Worker       FIXP_DBL gain = pit_gain[i];
2014*e5436536SAndroid Build Coastguard Worker 
2015*e5436536SAndroid Build Coastguard Worker       if (gain > (FIXP_DBL)0) {
2016*e5436536SAndroid Build Coastguard Worker         gain = get_gain(&p2_synth[i * L_SUBFR], &p2_synth[(i * L_SUBFR) - T],
2017*e5436536SAndroid Build Coastguard Worker                         L_SUBFR);
2018*e5436536SAndroid Build Coastguard Worker         pit_gain[i] = gain;
2019*e5436536SAndroid Build Coastguard Worker       }
2020*e5436536SAndroid Build Coastguard Worker     }
2021*e5436536SAndroid Build Coastguard Worker 
2022*e5436536SAndroid Build Coastguard Worker     {
2023*e5436536SAndroid Build Coastguard Worker       bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB,
2024*e5436536SAndroid Build Coastguard Worker                         mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay,
2025*e5436536SAndroid Build Coastguard Worker                         pTimeData, aacOutDataHeadroom,
2026*e5436536SAndroid Build Coastguard Worker                         pAacDecoderStaticChannelInfo->mem_bpf);
2027*e5436536SAndroid Build Coastguard Worker     }
2028*e5436536SAndroid Build Coastguard Worker   }
2029*e5436536SAndroid Build Coastguard Worker 
2030*e5436536SAndroid Build Coastguard Worker   Acelp_PostProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth,
2031*e5436536SAndroid Build Coastguard Worker                        pitch, pAacDecoderStaticChannelInfo->old_T_pf, lFrame,
2032*e5436536SAndroid Build Coastguard Worker                        synSfd, nbSubfrSuperfr);
2033*e5436536SAndroid Build Coastguard Worker 
2034*e5436536SAndroid Build Coastguard Worker   /* Store last mode for next super frame */
2035*e5436536SAndroid Build Coastguard Worker   { pAacDecoderStaticChannelInfo->last_core_mode = LPD; }
2036*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->last_lpd_mode = last_lpd_mode;
2037*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->last_last_lpd_mode = last_last_lpd_mode;
2038*e5436536SAndroid Build Coastguard Worker   pAacDecoderStaticChannelInfo->last_lpc_lost = last_lpc_lost;
2039*e5436536SAndroid Build Coastguard Worker 
2040*e5436536SAndroid Build Coastguard Worker   return error;
2041*e5436536SAndroid Build Coastguard Worker }
2042