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