xref: /aosp_15_r20/external/aac/libAACdec/src/usacdec_acelp.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker 
4*e5436536SAndroid Build Coastguard Worker © Copyright  1995 - 2020 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):   Matthias Hildenbrand
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: USAC ACELP frame decoder
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "usacdec_acelp.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker #include "usacdec_ace_d4t64.h"
106*e5436536SAndroid Build Coastguard Worker #include "usacdec_ace_ltp.h"
107*e5436536SAndroid Build Coastguard Worker #include "usacdec_rom.h"
108*e5436536SAndroid Build Coastguard Worker #include "usacdec_lpc.h"
109*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
110*e5436536SAndroid Build Coastguard Worker 
111*e5436536SAndroid Build Coastguard Worker #define PIT_FR2_12k8 128 /* Minimum pitch lag with resolution 1/2      */
112*e5436536SAndroid Build Coastguard Worker #define PIT_FR1_12k8 160 /* Minimum pitch lag with resolution 1        */
113*e5436536SAndroid Build Coastguard Worker #define TILT_CODE2 \
114*e5436536SAndroid Build Coastguard Worker   FL2FXCONST_SGL(0.3f * 2.0f) /* ACELP code pre-emphasis factor ( *2 )      */
115*e5436536SAndroid Build Coastguard Worker #define PIT_SHARP \
116*e5436536SAndroid Build Coastguard Worker   FL2FXCONST_SGL(0.85f) /* pitch sharpening factor                    */
117*e5436536SAndroid Build Coastguard Worker #define PREEMPH_FAC \
118*e5436536SAndroid Build Coastguard Worker   FL2FXCONST_SGL(0.68f) /* ACELP synth pre-emphasis factor            */
119*e5436536SAndroid Build Coastguard Worker 
120*e5436536SAndroid Build Coastguard Worker #define ACELP_HEADROOM 1
121*e5436536SAndroid Build Coastguard Worker #define ACELP_OUTSCALE (MDCT_OUT_HEADROOM - ACELP_HEADROOM)
122*e5436536SAndroid Build Coastguard Worker 
123*e5436536SAndroid Build Coastguard Worker /**
124*e5436536SAndroid Build Coastguard Worker  * \brief Calculate pre-emphasis (1 - mu z^-1) on input signal.
125*e5436536SAndroid Build Coastguard Worker  * \param[in] in pointer to input signal; in[-1] is also needed.
126*e5436536SAndroid Build Coastguard Worker  * \param[out] out pointer to output signal.
127*e5436536SAndroid Build Coastguard Worker  * \param[in] L length of filtering.
128*e5436536SAndroid Build Coastguard Worker  */
129*e5436536SAndroid Build Coastguard Worker /* static */
E_UTIL_preemph(const FIXP_DBL * in,FIXP_DBL * out,INT L)130*e5436536SAndroid Build Coastguard Worker void E_UTIL_preemph(const FIXP_DBL *in, FIXP_DBL *out, INT L) {
131*e5436536SAndroid Build Coastguard Worker   int i;
132*e5436536SAndroid Build Coastguard Worker 
133*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < L; i++) {
134*e5436536SAndroid Build Coastguard Worker     out[i] = fAddSaturate(in[i], -fMult(PREEMPH_FAC, in[i - 1]));
135*e5436536SAndroid Build Coastguard Worker   }
136*e5436536SAndroid Build Coastguard Worker 
137*e5436536SAndroid Build Coastguard Worker   return;
138*e5436536SAndroid Build Coastguard Worker }
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker /**
141*e5436536SAndroid Build Coastguard Worker  * \brief Calculate de-emphasis 1/(1 - TILT_CODE z^-1) on innovative codebook
142*e5436536SAndroid Build Coastguard Worker  * vector.
143*e5436536SAndroid Build Coastguard Worker  * \param[in,out] x innovative codebook vector.
144*e5436536SAndroid Build Coastguard Worker  */
Preemph_code(FIXP_COD x[])145*e5436536SAndroid Build Coastguard Worker static void Preemph_code(
146*e5436536SAndroid Build Coastguard Worker     FIXP_COD x[] /* (i/o)   : input signal overwritten by the output */
147*e5436536SAndroid Build Coastguard Worker ) {
148*e5436536SAndroid Build Coastguard Worker   int i;
149*e5436536SAndroid Build Coastguard Worker   FIXP_DBL L_tmp;
150*e5436536SAndroid Build Coastguard Worker 
151*e5436536SAndroid Build Coastguard Worker   /* ARM926: 12 cycles per sample */
152*e5436536SAndroid Build Coastguard Worker   for (i = L_SUBFR - 1; i > 0; i--) {
153*e5436536SAndroid Build Coastguard Worker     L_tmp = FX_COD2FX_DBL(x[i]);
154*e5436536SAndroid Build Coastguard Worker     L_tmp -= fMultDiv2(x[i - 1], TILT_CODE2);
155*e5436536SAndroid Build Coastguard Worker     x[i] = FX_DBL2FX_COD(L_tmp);
156*e5436536SAndroid Build Coastguard Worker   }
157*e5436536SAndroid Build Coastguard Worker }
158*e5436536SAndroid Build Coastguard Worker 
159*e5436536SAndroid Build Coastguard Worker /**
160*e5436536SAndroid Build Coastguard Worker  * \brief Apply pitch sharpener to the innovative codebook vector.
161*e5436536SAndroid Build Coastguard Worker  * \param[in,out] x innovative codebook vector.
162*e5436536SAndroid Build Coastguard Worker  * \param[in] pit_lag decoded pitch lag.
163*e5436536SAndroid Build Coastguard Worker  */
Pit_shrp(FIXP_COD x[],int pit_lag)164*e5436536SAndroid Build Coastguard Worker static void Pit_shrp(
165*e5436536SAndroid Build Coastguard Worker     FIXP_COD x[], /* in/out: impulse response (or algebraic code) */
166*e5436536SAndroid Build Coastguard Worker     int pit_lag   /* input : pitch lag                            */
167*e5436536SAndroid Build Coastguard Worker ) {
168*e5436536SAndroid Build Coastguard Worker   int i;
169*e5436536SAndroid Build Coastguard Worker   FIXP_DBL L_tmp;
170*e5436536SAndroid Build Coastguard Worker 
171*e5436536SAndroid Build Coastguard Worker   for (i = pit_lag; i < L_SUBFR; i++) {
172*e5436536SAndroid Build Coastguard Worker     L_tmp = FX_COD2FX_DBL(x[i]);
173*e5436536SAndroid Build Coastguard Worker     L_tmp += fMult(x[i - pit_lag], PIT_SHARP);
174*e5436536SAndroid Build Coastguard Worker     x[i] = FX_DBL2FX_COD(L_tmp);
175*e5436536SAndroid Build Coastguard Worker   }
176*e5436536SAndroid Build Coastguard Worker 
177*e5436536SAndroid Build Coastguard Worker   return;
178*e5436536SAndroid Build Coastguard Worker }
179*e5436536SAndroid Build Coastguard Worker 
180*e5436536SAndroid Build Coastguard Worker   /**
181*e5436536SAndroid Build Coastguard Worker    * \brief Calculate Quantized codebook gain, Quantized pitch gain and unbiased
182*e5436536SAndroid Build Coastguard Worker    *        Innovative code vector energy.
183*e5436536SAndroid Build Coastguard Worker    * \param[in] index index of quantizer.
184*e5436536SAndroid Build Coastguard Worker    * \param[in] code innovative code vector with exponent = SF_CODE.
185*e5436536SAndroid Build Coastguard Worker    * \param[out] gain_pit Quantized pitch gain g_p with exponent = SF_GAIN_P.
186*e5436536SAndroid Build Coastguard Worker    * \param[out] gain_code Quantized codebook gain g_c.
187*e5436536SAndroid Build Coastguard Worker    * \param[in] mean_ener mean_ener defined in open-loop (2 bits), exponent = 7.
188*e5436536SAndroid Build Coastguard Worker    * \param[out] E_code unbiased innovative code vector energy.
189*e5436536SAndroid Build Coastguard Worker    * \param[out] E_code_e exponent of unbiased innovative code vector energy.
190*e5436536SAndroid Build Coastguard Worker    */
191*e5436536SAndroid Build Coastguard Worker 
192*e5436536SAndroid Build Coastguard Worker #define SF_MEAN_ENER_LG10 9
193*e5436536SAndroid Build Coastguard Worker 
194*e5436536SAndroid Build Coastguard Worker /* pow(10.0, {18, 30, 42, 54}/20.0) /(float)(1<<SF_MEAN_ENER_LG10) */
195*e5436536SAndroid Build Coastguard Worker static const FIXP_DBL pow_10_mean_energy[4] = {0x01fc5ebd, 0x07e7db92,
196*e5436536SAndroid Build Coastguard Worker                                                0x1f791f65, 0x7d4bfba3};
197*e5436536SAndroid Build Coastguard Worker 
D_gain2_plus(int index,FIXP_COD code[],FIXP_SGL * gain_pit,FIXP_DBL * gain_code,int mean_ener_bits,int bfi,FIXP_SGL * past_gpit,FIXP_DBL * past_gcode,FIXP_DBL * pEner_code,int * pEner_code_e)198*e5436536SAndroid Build Coastguard Worker static void D_gain2_plus(int index, FIXP_COD code[], FIXP_SGL *gain_pit,
199*e5436536SAndroid Build Coastguard Worker                          FIXP_DBL *gain_code, int mean_ener_bits, int bfi,
200*e5436536SAndroid Build Coastguard Worker                          FIXP_SGL *past_gpit, FIXP_DBL *past_gcode,
201*e5436536SAndroid Build Coastguard Worker                          FIXP_DBL *pEner_code, int *pEner_code_e) {
202*e5436536SAndroid Build Coastguard Worker   FIXP_DBL Ltmp;
203*e5436536SAndroid Build Coastguard Worker   FIXP_DBL gcode0, gcode_inov;
204*e5436536SAndroid Build Coastguard Worker   INT gcode0_e, gcode_inov_e;
205*e5436536SAndroid Build Coastguard Worker   int i;
206*e5436536SAndroid Build Coastguard Worker 
207*e5436536SAndroid Build Coastguard Worker   FIXP_DBL ener_code;
208*e5436536SAndroid Build Coastguard Worker   INT ener_code_e;
209*e5436536SAndroid Build Coastguard Worker 
210*e5436536SAndroid Build Coastguard Worker   /* ener_code = sum(code[]^2) */
211*e5436536SAndroid Build Coastguard Worker   ener_code = FIXP_DBL(0);
212*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < L_SUBFR; i++) {
213*e5436536SAndroid Build Coastguard Worker     ener_code += fPow2Div2(code[i]);
214*e5436536SAndroid Build Coastguard Worker   }
215*e5436536SAndroid Build Coastguard Worker 
216*e5436536SAndroid Build Coastguard Worker   ener_code_e = fMax(fNorm(ener_code) - 1, 0);
217*e5436536SAndroid Build Coastguard Worker   ener_code <<= ener_code_e;
218*e5436536SAndroid Build Coastguard Worker   ener_code_e = 2 * SF_CODE + 1 - ener_code_e;
219*e5436536SAndroid Build Coastguard Worker 
220*e5436536SAndroid Build Coastguard Worker   /* export energy of code for calc_period_factor() */
221*e5436536SAndroid Build Coastguard Worker   *pEner_code = ener_code;
222*e5436536SAndroid Build Coastguard Worker   *pEner_code_e = ener_code_e;
223*e5436536SAndroid Build Coastguard Worker 
224*e5436536SAndroid Build Coastguard Worker   ener_code += scaleValue(FL2FXCONST_DBL(0.01f), -ener_code_e);
225*e5436536SAndroid Build Coastguard Worker 
226*e5436536SAndroid Build Coastguard Worker   /* ener_code *= 1/L_SUBFR, and make exponent even (because of square root
227*e5436536SAndroid Build Coastguard Worker    * below). */
228*e5436536SAndroid Build Coastguard Worker   if (ener_code_e & 1) {
229*e5436536SAndroid Build Coastguard Worker     ener_code_e -= 5;
230*e5436536SAndroid Build Coastguard Worker     ener_code >>= 1;
231*e5436536SAndroid Build Coastguard Worker   } else {
232*e5436536SAndroid Build Coastguard Worker     ener_code_e -= 6;
233*e5436536SAndroid Build Coastguard Worker   }
234*e5436536SAndroid Build Coastguard Worker   gcode_inov = invSqrtNorm2(ener_code, &gcode0_e);
235*e5436536SAndroid Build Coastguard Worker   gcode_inov_e = gcode0_e - (ener_code_e >> 1);
236*e5436536SAndroid Build Coastguard Worker 
237*e5436536SAndroid Build Coastguard Worker   if (bfi) {
238*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tgcode;
239*e5436536SAndroid Build Coastguard Worker     FIXP_SGL tgpit;
240*e5436536SAndroid Build Coastguard Worker 
241*e5436536SAndroid Build Coastguard Worker     tgpit = *past_gpit;
242*e5436536SAndroid Build Coastguard Worker 
243*e5436536SAndroid Build Coastguard Worker     if (tgpit > FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P))) {
244*e5436536SAndroid Build Coastguard Worker       tgpit = FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P));
245*e5436536SAndroid Build Coastguard Worker     } else if (tgpit < FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P))) {
246*e5436536SAndroid Build Coastguard Worker       tgpit = FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P));
247*e5436536SAndroid Build Coastguard Worker     }
248*e5436536SAndroid Build Coastguard Worker     *gain_pit = tgpit;
249*e5436536SAndroid Build Coastguard Worker     tgpit = FX_DBL2FX_SGL(fMult(tgpit, FL2FXCONST_DBL(0.95f)));
250*e5436536SAndroid Build Coastguard Worker     *past_gpit = tgpit;
251*e5436536SAndroid Build Coastguard Worker 
252*e5436536SAndroid Build Coastguard Worker     tgpit = FL2FXCONST_SGL(1.4f / (1 << SF_GAIN_P)) - tgpit;
253*e5436536SAndroid Build Coastguard Worker     tgcode = fMult(*past_gcode, tgpit) << SF_GAIN_P;
254*e5436536SAndroid Build Coastguard Worker     *gain_code = scaleValue(fMult(tgcode, gcode_inov), gcode_inov_e);
255*e5436536SAndroid Build Coastguard Worker     *past_gcode = tgcode;
256*e5436536SAndroid Build Coastguard Worker 
257*e5436536SAndroid Build Coastguard Worker     return;
258*e5436536SAndroid Build Coastguard Worker   }
259*e5436536SAndroid Build Coastguard Worker 
260*e5436536SAndroid Build Coastguard Worker   /*-------------- Decode gains ---------------*/
261*e5436536SAndroid Build Coastguard Worker   /*
262*e5436536SAndroid Build Coastguard Worker    gcode0 = pow(10.0, (float)mean_ener/20.0);
263*e5436536SAndroid Build Coastguard Worker    gcode0 = gcode0 / sqrt(ener_code/L_SUBFR);
264*e5436536SAndroid Build Coastguard Worker    */
265*e5436536SAndroid Build Coastguard Worker   gcode0 = pow_10_mean_energy[mean_ener_bits];
266*e5436536SAndroid Build Coastguard Worker   gcode0 = fMultDiv2(gcode0, gcode_inov);
267*e5436536SAndroid Build Coastguard Worker   gcode0_e = gcode0_e + SF_MEAN_ENER_LG10 - (ener_code_e >> 1) + 1;
268*e5436536SAndroid Build Coastguard Worker 
269*e5436536SAndroid Build Coastguard Worker   i = index << 1;
270*e5436536SAndroid Build Coastguard Worker   *gain_pit = t_qua_gain7b[i]; /* adaptive codebook gain */
271*e5436536SAndroid Build Coastguard Worker   /* t_qua_gain[ind2p1] : fixed codebook gain correction factor */
272*e5436536SAndroid Build Coastguard Worker   Ltmp = fMult(t_qua_gain7b[i + 1], gcode0);
273*e5436536SAndroid Build Coastguard Worker   *gain_code = scaleValue(Ltmp, gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B);
274*e5436536SAndroid Build Coastguard Worker 
275*e5436536SAndroid Build Coastguard Worker   /* update bad frame handler */
276*e5436536SAndroid Build Coastguard Worker   *past_gpit = *gain_pit;
277*e5436536SAndroid Build Coastguard Worker 
278*e5436536SAndroid Build Coastguard Worker   /*--------------------------------------------------------
279*e5436536SAndroid Build Coastguard Worker     past_gcode  = gain_code/gcode_inov
280*e5436536SAndroid Build Coastguard Worker    --------------------------------------------------------*/
281*e5436536SAndroid Build Coastguard Worker   {
282*e5436536SAndroid Build Coastguard Worker     FIXP_DBL gcode_m;
283*e5436536SAndroid Build Coastguard Worker     INT gcode_e;
284*e5436536SAndroid Build Coastguard Worker 
285*e5436536SAndroid Build Coastguard Worker     gcode_m = fDivNormHighPrec(Ltmp, gcode_inov, &gcode_e);
286*e5436536SAndroid Build Coastguard Worker     gcode_e += (gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B) - (gcode_inov_e);
287*e5436536SAndroid Build Coastguard Worker     *past_gcode = scaleValue(gcode_m, gcode_e);
288*e5436536SAndroid Build Coastguard Worker   }
289*e5436536SAndroid Build Coastguard Worker }
290*e5436536SAndroid Build Coastguard Worker 
291*e5436536SAndroid Build Coastguard Worker /**
292*e5436536SAndroid Build Coastguard Worker  * \brief Calculate period/voicing factor r_v
293*e5436536SAndroid Build Coastguard Worker  * \param[in] exc pitch excitation.
294*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_pit gain of pitch g_p.
295*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_code gain of code g_c.
296*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_code_e exponent of gain of code.
297*e5436536SAndroid Build Coastguard Worker  * \param[in] ener_code unbiased innovative code vector energy.
298*e5436536SAndroid Build Coastguard Worker  * \param[in] ener_code_e exponent of unbiased innovative code vector energy.
299*e5436536SAndroid Build Coastguard Worker  * \return period/voice factor r_v (-1=unvoiced to 1=voiced), exponent SF_PFAC.
300*e5436536SAndroid Build Coastguard Worker  */
calc_period_factor(FIXP_DBL exc[],FIXP_SGL gain_pit,FIXP_DBL gain_code,FIXP_DBL ener_code,int ener_code_e)301*e5436536SAndroid Build Coastguard Worker static FIXP_DBL calc_period_factor(FIXP_DBL exc[], FIXP_SGL gain_pit,
302*e5436536SAndroid Build Coastguard Worker                                    FIXP_DBL gain_code, FIXP_DBL ener_code,
303*e5436536SAndroid Build Coastguard Worker                                    int ener_code_e) {
304*e5436536SAndroid Build Coastguard Worker   int ener_exc_e, L_tmp_e, s = 0;
305*e5436536SAndroid Build Coastguard Worker   FIXP_DBL ener_exc, L_tmp;
306*e5436536SAndroid Build Coastguard Worker   FIXP_DBL period_fac;
307*e5436536SAndroid Build Coastguard Worker 
308*e5436536SAndroid Build Coastguard Worker   /* energy of pitch excitation */
309*e5436536SAndroid Build Coastguard Worker   ener_exc = (FIXP_DBL)0;
310*e5436536SAndroid Build Coastguard Worker   for (int i = 0; i < L_SUBFR; i++) {
311*e5436536SAndroid Build Coastguard Worker     ener_exc += fPow2Div2(exc[i]) >> s;
312*e5436536SAndroid Build Coastguard Worker     if (ener_exc >= FL2FXCONST_DBL(0.5f)) {
313*e5436536SAndroid Build Coastguard Worker       ener_exc >>= 1;
314*e5436536SAndroid Build Coastguard Worker       s++;
315*e5436536SAndroid Build Coastguard Worker     }
316*e5436536SAndroid Build Coastguard Worker   }
317*e5436536SAndroid Build Coastguard Worker 
318*e5436536SAndroid Build Coastguard Worker   ener_exc_e = fNorm(ener_exc);
319*e5436536SAndroid Build Coastguard Worker   ener_exc = fMult(ener_exc << ener_exc_e, fPow2(gain_pit));
320*e5436536SAndroid Build Coastguard Worker   if (ener_exc != (FIXP_DBL)0) {
321*e5436536SAndroid Build Coastguard Worker     ener_exc_e = 2 * SF_EXC + 1 + 2 * SF_GAIN_P - ener_exc_e + s;
322*e5436536SAndroid Build Coastguard Worker   } else {
323*e5436536SAndroid Build Coastguard Worker     ener_exc_e = 0;
324*e5436536SAndroid Build Coastguard Worker   }
325*e5436536SAndroid Build Coastguard Worker 
326*e5436536SAndroid Build Coastguard Worker   /* energy of innovative code excitation */
327*e5436536SAndroid Build Coastguard Worker   /* L_tmp = ener_code * gain_code*gain_code; */
328*e5436536SAndroid Build Coastguard Worker   L_tmp_e = fNorm(gain_code);
329*e5436536SAndroid Build Coastguard Worker   L_tmp = fPow2(gain_code << L_tmp_e);
330*e5436536SAndroid Build Coastguard Worker   L_tmp = fMult(ener_code, L_tmp);
331*e5436536SAndroid Build Coastguard Worker   L_tmp_e = 2 * SF_GAIN_C + ener_code_e - 2 * L_tmp_e;
332*e5436536SAndroid Build Coastguard Worker 
333*e5436536SAndroid Build Coastguard Worker   /* Find common exponent */
334*e5436536SAndroid Build Coastguard Worker   {
335*e5436536SAndroid Build Coastguard Worker     FIXP_DBL num, den;
336*e5436536SAndroid Build Coastguard Worker     int exp_diff;
337*e5436536SAndroid Build Coastguard Worker 
338*e5436536SAndroid Build Coastguard Worker     exp_diff = ener_exc_e - L_tmp_e;
339*e5436536SAndroid Build Coastguard Worker     if (exp_diff >= 0) {
340*e5436536SAndroid Build Coastguard Worker       ener_exc >>= 1;
341*e5436536SAndroid Build Coastguard Worker       if (exp_diff <= DFRACT_BITS - 2) {
342*e5436536SAndroid Build Coastguard Worker         L_tmp >>= exp_diff + 1;
343*e5436536SAndroid Build Coastguard Worker       } else {
344*e5436536SAndroid Build Coastguard Worker         L_tmp = (FIXP_DBL)0;
345*e5436536SAndroid Build Coastguard Worker       }
346*e5436536SAndroid Build Coastguard Worker       den = ener_exc + L_tmp;
347*e5436536SAndroid Build Coastguard Worker       if (ener_exc_e < DFRACT_BITS - 1) {
348*e5436536SAndroid Build Coastguard Worker         den += scaleValue(FL2FXCONST_DBL(0.01f), -ener_exc_e - 1);
349*e5436536SAndroid Build Coastguard Worker       }
350*e5436536SAndroid Build Coastguard Worker     } else {
351*e5436536SAndroid Build Coastguard Worker       if (exp_diff >= -(DFRACT_BITS - 2)) {
352*e5436536SAndroid Build Coastguard Worker         ener_exc >>= 1 - exp_diff;
353*e5436536SAndroid Build Coastguard Worker       } else {
354*e5436536SAndroid Build Coastguard Worker         ener_exc = (FIXP_DBL)0;
355*e5436536SAndroid Build Coastguard Worker       }
356*e5436536SAndroid Build Coastguard Worker       L_tmp >>= 1;
357*e5436536SAndroid Build Coastguard Worker       den = ener_exc + L_tmp;
358*e5436536SAndroid Build Coastguard Worker       if (L_tmp_e < DFRACT_BITS - 1) {
359*e5436536SAndroid Build Coastguard Worker         den += scaleValue(FL2FXCONST_DBL(0.01f), -L_tmp_e - 1);
360*e5436536SAndroid Build Coastguard Worker       }
361*e5436536SAndroid Build Coastguard Worker     }
362*e5436536SAndroid Build Coastguard Worker     num = (ener_exc - L_tmp);
363*e5436536SAndroid Build Coastguard Worker     num >>= SF_PFAC;
364*e5436536SAndroid Build Coastguard Worker 
365*e5436536SAndroid Build Coastguard Worker     if (den > (FIXP_DBL)0) {
366*e5436536SAndroid Build Coastguard Worker       if (ener_exc > L_tmp) {
367*e5436536SAndroid Build Coastguard Worker         period_fac = schur_div(num, den, 16);
368*e5436536SAndroid Build Coastguard Worker       } else {
369*e5436536SAndroid Build Coastguard Worker         period_fac = -schur_div(-num, den, 16);
370*e5436536SAndroid Build Coastguard Worker       }
371*e5436536SAndroid Build Coastguard Worker     } else {
372*e5436536SAndroid Build Coastguard Worker       period_fac = (FIXP_DBL)MAXVAL_DBL;
373*e5436536SAndroid Build Coastguard Worker     }
374*e5436536SAndroid Build Coastguard Worker   }
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker   /* exponent = SF_PFAC */
377*e5436536SAndroid Build Coastguard Worker   return period_fac;
378*e5436536SAndroid Build Coastguard Worker }
379*e5436536SAndroid Build Coastguard Worker 
380*e5436536SAndroid Build Coastguard Worker /*------------------------------------------------------------*
381*e5436536SAndroid Build Coastguard Worker  * noise enhancer                                             *
382*e5436536SAndroid Build Coastguard Worker  * ~~~~~~~~~~~~~~                                             *
383*e5436536SAndroid Build Coastguard Worker  * - Enhance excitation on noise. (modify gain of code)       *
384*e5436536SAndroid Build Coastguard Worker  *   If signal is noisy and LPC filter is stable, move gain   *
385*e5436536SAndroid Build Coastguard Worker  *   of code 1.5 dB toward gain of code threshold.            *
386*e5436536SAndroid Build Coastguard Worker  *   This decrease by 3 dB noise energy variation.            *
387*e5436536SAndroid Build Coastguard Worker  *------------------------------------------------------------*/
388*e5436536SAndroid Build Coastguard Worker /**
389*e5436536SAndroid Build Coastguard Worker  * \brief Enhance excitation on noise. (modify gain of code)
390*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_code Quantized codebook gain g_c, exponent = SF_GAIN_C.
391*e5436536SAndroid Build Coastguard Worker  * \param[in] period_fac periodicity factor, exponent = SF_PFAC.
392*e5436536SAndroid Build Coastguard Worker  * \param[in] stab_fac stability factor, exponent = SF_STAB.
393*e5436536SAndroid Build Coastguard Worker  * \param[in,out] p_gc_threshold modified gain of previous subframe.
394*e5436536SAndroid Build Coastguard Worker  * \return gain_code smoothed gain of code g_sc, exponent = SF_GAIN_C.
395*e5436536SAndroid Build Coastguard Worker  */
396*e5436536SAndroid Build Coastguard Worker static FIXP_DBL
noise_enhancer(FIXP_DBL gain_code,FIXP_DBL period_fac,FIXP_SGL stab_fac,FIXP_DBL * p_gc_threshold)397*e5436536SAndroid Build Coastguard Worker noise_enhancer(/* (o) : smoothed gain g_sc                     SF_GAIN_C */
398*e5436536SAndroid Build Coastguard Worker                FIXP_DBL gain_code, /* (i) : Quantized codebook gain SF_GAIN_C */
399*e5436536SAndroid Build Coastguard Worker                FIXP_DBL period_fac, /* (i) : periodicity factor (-1=unvoiced to
400*e5436536SAndroid Build Coastguard Worker                                        1=voiced), SF_PFAC */
401*e5436536SAndroid Build Coastguard Worker                FIXP_SGL stab_fac,   /* (i) : stability factor (0 <= ... < 1.0)
402*e5436536SAndroid Build Coastguard Worker                                        SF_STAB   */
403*e5436536SAndroid Build Coastguard Worker                FIXP_DBL
404*e5436536SAndroid Build Coastguard Worker                    *p_gc_threshold) /* (io): gain of code threshold SF_GAIN_C */
405*e5436536SAndroid Build Coastguard Worker {
406*e5436536SAndroid Build Coastguard Worker   FIXP_DBL fac, L_tmp, gc_thres;
407*e5436536SAndroid Build Coastguard Worker 
408*e5436536SAndroid Build Coastguard Worker   gc_thres = *p_gc_threshold;
409*e5436536SAndroid Build Coastguard Worker 
410*e5436536SAndroid Build Coastguard Worker   L_tmp = gain_code;
411*e5436536SAndroid Build Coastguard Worker   if (L_tmp < gc_thres) {
412*e5436536SAndroid Build Coastguard Worker     L_tmp += fMultDiv2(gain_code,
413*e5436536SAndroid Build Coastguard Worker                        FL2FXCONST_SGL(2.0 * 0.19f)); /* +1.5dB => *(1.0+0.19) */
414*e5436536SAndroid Build Coastguard Worker     if (L_tmp > gc_thres) {
415*e5436536SAndroid Build Coastguard Worker       L_tmp = gc_thres;
416*e5436536SAndroid Build Coastguard Worker     }
417*e5436536SAndroid Build Coastguard Worker   } else {
418*e5436536SAndroid Build Coastguard Worker     L_tmp = fMult(gain_code,
419*e5436536SAndroid Build Coastguard Worker                   FL2FXCONST_SGL(1.0f / 1.19f)); /* -1.5dB => *10^(-1.5/20) */
420*e5436536SAndroid Build Coastguard Worker     if (L_tmp < gc_thres) {
421*e5436536SAndroid Build Coastguard Worker       L_tmp = gc_thres;
422*e5436536SAndroid Build Coastguard Worker     }
423*e5436536SAndroid Build Coastguard Worker   }
424*e5436536SAndroid Build Coastguard Worker   *p_gc_threshold = L_tmp;
425*e5436536SAndroid Build Coastguard Worker 
426*e5436536SAndroid Build Coastguard Worker   /* voicing factor     lambda = 0.5*(1-period_fac) */
427*e5436536SAndroid Build Coastguard Worker   /* gain smoothing factor S_m = lambda*stab_fac  (=fac)
428*e5436536SAndroid Build Coastguard Worker                                = 0.5(stab_fac - stab_fac * period_fac) */
429*e5436536SAndroid Build Coastguard Worker   fac = (FX_SGL2FX_DBL(stab_fac) >> (SF_PFAC + 1)) -
430*e5436536SAndroid Build Coastguard Worker         fMultDiv2(stab_fac, period_fac);
431*e5436536SAndroid Build Coastguard Worker   /* fac_e = SF_PFAC + SF_STAB */
432*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(fac >= (FIXP_DBL)0);
433*e5436536SAndroid Build Coastguard Worker 
434*e5436536SAndroid Build Coastguard Worker   /* gain_code = (float)((fac*tmp) + ((1.0-fac)*gain_code)); */
435*e5436536SAndroid Build Coastguard Worker   gain_code = fMult(fac, L_tmp) -
436*e5436536SAndroid Build Coastguard Worker               fMult(FL2FXCONST_DBL(-1.0f / (1 << (SF_PFAC + SF_STAB))) + fac,
437*e5436536SAndroid Build Coastguard Worker                     gain_code);
438*e5436536SAndroid Build Coastguard Worker   gain_code <<= (SF_PFAC + SF_STAB);
439*e5436536SAndroid Build Coastguard Worker 
440*e5436536SAndroid Build Coastguard Worker   return gain_code;
441*e5436536SAndroid Build Coastguard Worker }
442*e5436536SAndroid Build Coastguard Worker 
443*e5436536SAndroid Build Coastguard Worker /**
444*e5436536SAndroid Build Coastguard Worker  * \brief Update adaptive codebook u'(n) (exc)
445*e5436536SAndroid Build Coastguard Worker  *        Enhance pitch of c(n) and build post-processed excitation u(n) (exc2)
446*e5436536SAndroid Build Coastguard Worker  * \param[in] code innovative codevector c(n), exponent = SF_CODE.
447*e5436536SAndroid Build Coastguard Worker  * \param[in,out] exc filtered adaptive codebook v(n), exponent = SF_EXC.
448*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_pit adaptive codebook gain, exponent = SF_GAIN_P.
449*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_code innovative codebook gain g_c, exponent = SF_GAIN_C.
450*e5436536SAndroid Build Coastguard Worker  * \param[in] gain_code_smoothed smoothed innov. codebook gain g_sc, exponent =
451*e5436536SAndroid Build Coastguard Worker  * SF_GAIN_C.
452*e5436536SAndroid Build Coastguard Worker  * \param[in] period_fac periodicity factor r_v, exponent = SF_PFAC.
453*e5436536SAndroid Build Coastguard Worker  * \param[out] exc2 post-processed excitation u(n), exponent = SF_EXC.
454*e5436536SAndroid Build Coastguard Worker  */
BuildAdaptiveExcitation(FIXP_COD code[],FIXP_DBL exc[],FIXP_SGL gain_pit,FIXP_DBL gain_code,FIXP_DBL gain_code_smoothed,FIXP_DBL period_fac,FIXP_DBL exc2[])455*e5436536SAndroid Build Coastguard Worker void BuildAdaptiveExcitation(
456*e5436536SAndroid Build Coastguard Worker     FIXP_COD code[],    /* (i) : algebraic codevector c(n)             Q9  */
457*e5436536SAndroid Build Coastguard Worker     FIXP_DBL exc[],     /* (io): filtered adaptive codebook v(n)       Q15 */
458*e5436536SAndroid Build Coastguard Worker     FIXP_SGL gain_pit,  /* (i) : adaptive codebook gain g_p            Q14 */
459*e5436536SAndroid Build Coastguard Worker     FIXP_DBL gain_code, /* (i) : innovative codebook gain g_c          Q16 */
460*e5436536SAndroid Build Coastguard Worker     FIXP_DBL gain_code_smoothed, /* (i) : smoothed innov. codebook gain g_sc
461*e5436536SAndroid Build Coastguard Worker                                     Q16 */
462*e5436536SAndroid Build Coastguard Worker     FIXP_DBL period_fac, /* (i) : periodicity factor r_v                Q15 */
463*e5436536SAndroid Build Coastguard Worker     FIXP_DBL exc2[]      /* (o) : post-processed excitation u(n)        Q15 */
464*e5436536SAndroid Build Coastguard Worker ) {
465*e5436536SAndroid Build Coastguard Worker /* Note: code[L_SUBFR] and exc2[L_SUBFR] share the same memory!
466*e5436536SAndroid Build Coastguard Worker          If exc2[i] is written, code[i] will be destroyed!
467*e5436536SAndroid Build Coastguard Worker */
468*e5436536SAndroid Build Coastguard Worker #define SF_HEADROOM (1)
469*e5436536SAndroid Build Coastguard Worker #define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC - SF_HEADROOM)
470*e5436536SAndroid Build Coastguard Worker #define SF_GAIN_P2 (SF_GAIN_P - SF_HEADROOM)
471*e5436536SAndroid Build Coastguard Worker 
472*e5436536SAndroid Build Coastguard Worker   int i;
473*e5436536SAndroid Build Coastguard Worker   FIXP_DBL tmp, cpe, code_smooth_prev, code_smooth;
474*e5436536SAndroid Build Coastguard Worker 
475*e5436536SAndroid Build Coastguard Worker   FIXP_COD code_i;
476*e5436536SAndroid Build Coastguard Worker   FIXP_DBL cpe_code_smooth, cpe_code_smooth_prev;
477*e5436536SAndroid Build Coastguard Worker 
478*e5436536SAndroid Build Coastguard Worker   /* cpe = (1+r_v)/8 * 2 ; ( SF = -1) */
479*e5436536SAndroid Build Coastguard Worker   cpe = (period_fac >> (2 - SF_PFAC)) + FL2FXCONST_DBL(0.25f);
480*e5436536SAndroid Build Coastguard Worker 
481*e5436536SAndroid Build Coastguard Worker   /* u'(n) */
482*e5436536SAndroid Build Coastguard Worker   tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); /* v(0)*g_p */
483*e5436536SAndroid Build Coastguard Worker   *exc++ = (tmp + (fMultDiv2(code[0], gain_code) << SF)) << SF_HEADROOM;
484*e5436536SAndroid Build Coastguard Worker 
485*e5436536SAndroid Build Coastguard Worker   /* u(n) */
486*e5436536SAndroid Build Coastguard Worker   code_smooth_prev = fMultDiv2(*code++, gain_code_smoothed)
487*e5436536SAndroid Build Coastguard Worker                      << SF; /* c(0) * g_sc */
488*e5436536SAndroid Build Coastguard Worker   code_i = *code++;
489*e5436536SAndroid Build Coastguard Worker   code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; /* c(1) * g_sc */
490*e5436536SAndroid Build Coastguard Worker   tmp += code_smooth_prev; /* tmp = v(0)*g_p + c(0)*g_sc */
491*e5436536SAndroid Build Coastguard Worker   cpe_code_smooth = fMultDiv2(cpe, code_smooth);
492*e5436536SAndroid Build Coastguard Worker   *exc2++ = (tmp - cpe_code_smooth) << SF_HEADROOM;
493*e5436536SAndroid Build Coastguard Worker   cpe_code_smooth_prev = fMultDiv2(cpe, code_smooth_prev);
494*e5436536SAndroid Build Coastguard Worker 
495*e5436536SAndroid Build Coastguard Worker   i = L_SUBFR - 2;
496*e5436536SAndroid Build Coastguard Worker   do /* ARM926: 22 cycles per iteration */
497*e5436536SAndroid Build Coastguard Worker   {
498*e5436536SAndroid Build Coastguard Worker     /* u'(n) */
499*e5436536SAndroid Build Coastguard Worker     tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
500*e5436536SAndroid Build Coastguard Worker     *exc++ = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
501*e5436536SAndroid Build Coastguard Worker     /* u(n) */
502*e5436536SAndroid Build Coastguard Worker     tmp += code_smooth; /* += g_sc * c(i) */
503*e5436536SAndroid Build Coastguard Worker     tmp -= cpe_code_smooth_prev;
504*e5436536SAndroid Build Coastguard Worker     cpe_code_smooth_prev = cpe_code_smooth;
505*e5436536SAndroid Build Coastguard Worker     code_i = *code++;
506*e5436536SAndroid Build Coastguard Worker     code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF;
507*e5436536SAndroid Build Coastguard Worker     cpe_code_smooth = fMultDiv2(cpe, code_smooth);
508*e5436536SAndroid Build Coastguard Worker     *exc2++ = (tmp - cpe_code_smooth)
509*e5436536SAndroid Build Coastguard Worker               << SF_HEADROOM; /* tmp - c_pe * g_sc * c(i+1) */
510*e5436536SAndroid Build Coastguard Worker   } while (--i != 0);
511*e5436536SAndroid Build Coastguard Worker 
512*e5436536SAndroid Build Coastguard Worker   /* u'(n) */
513*e5436536SAndroid Build Coastguard Worker   tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
514*e5436536SAndroid Build Coastguard Worker   *exc = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
515*e5436536SAndroid Build Coastguard Worker   /* u(n) */
516*e5436536SAndroid Build Coastguard Worker   tmp += code_smooth;
517*e5436536SAndroid Build Coastguard Worker   tmp -= cpe_code_smooth_prev;
518*e5436536SAndroid Build Coastguard Worker   *exc2++ = tmp << SF_HEADROOM;
519*e5436536SAndroid Build Coastguard Worker 
520*e5436536SAndroid Build Coastguard Worker   return;
521*e5436536SAndroid Build Coastguard Worker }
522*e5436536SAndroid Build Coastguard Worker 
523*e5436536SAndroid Build Coastguard Worker /**
524*e5436536SAndroid Build Coastguard Worker  * \brief Interpolate LPC vector in LSP domain for current subframe and convert
525*e5436536SAndroid Build Coastguard Worker  * to LP domain
526*e5436536SAndroid Build Coastguard Worker  * \param[in] lsp_old LPC vector (LSP domain) corresponding to the beginning of
527*e5436536SAndroid Build Coastguard Worker  * current ACELP frame.
528*e5436536SAndroid Build Coastguard Worker  * \param[in] lsp_new LPC vector (LSP domain) corresponding to the end of
529*e5436536SAndroid Build Coastguard Worker  * current ACELP frame.
530*e5436536SAndroid Build Coastguard Worker  * \param[in] subfr_nr number of current ACELP subframe 0..3.
531*e5436536SAndroid Build Coastguard Worker  * \param[in] nb_subfr total number of ACELP subframes in this frame.
532*e5436536SAndroid Build Coastguard Worker  * \param[out] A LP filter coefficients for current ACELP subframe, exponent =
533*e5436536SAndroid Build Coastguard Worker  * SF_A_COEFFS.
534*e5436536SAndroid Build Coastguard Worker  */
535*e5436536SAndroid Build Coastguard Worker /* static */
int_lpc_acelp(const FIXP_LPC lsp_old[],const FIXP_LPC lsp_new[],int subfr_nr,int nb_subfr,FIXP_LPC A[],INT * A_exp)536*e5436536SAndroid Build Coastguard Worker void int_lpc_acelp(
537*e5436536SAndroid Build Coastguard Worker     const FIXP_LPC lsp_old[], /* input : LSPs from past frame              */
538*e5436536SAndroid Build Coastguard Worker     const FIXP_LPC lsp_new[], /* input : LSPs from present frame           */
539*e5436536SAndroid Build Coastguard Worker     int subfr_nr, int nb_subfr,
540*e5436536SAndroid Build Coastguard Worker     FIXP_LPC
541*e5436536SAndroid Build Coastguard Worker         A[], /* output: interpolated LP coefficients for current subframe */
542*e5436536SAndroid Build Coastguard Worker     INT *A_exp) {
543*e5436536SAndroid Build Coastguard Worker   int i;
544*e5436536SAndroid Build Coastguard Worker   FIXP_LPC lsp_interpol[M_LP_FILTER_ORDER];
545*e5436536SAndroid Build Coastguard Worker   FIXP_SGL fac_old, fac_new;
546*e5436536SAndroid Build Coastguard Worker 
547*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((nb_subfr == 3) || (nb_subfr == 4));
548*e5436536SAndroid Build Coastguard Worker 
549*e5436536SAndroid Build Coastguard Worker   fac_old = lsp_interpol_factor[nb_subfr & 0x1][(nb_subfr - 1) - subfr_nr];
550*e5436536SAndroid Build Coastguard Worker   fac_new = lsp_interpol_factor[nb_subfr & 0x1][subfr_nr];
551*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < M_LP_FILTER_ORDER; i++) {
552*e5436536SAndroid Build Coastguard Worker     lsp_interpol[i] = FX_DBL2FX_LPC(
553*e5436536SAndroid Build Coastguard Worker         (fMultDiv2(lsp_old[i], fac_old) + fMultDiv2(lsp_new[i], fac_new)) << 1);
554*e5436536SAndroid Build Coastguard Worker   }
555*e5436536SAndroid Build Coastguard Worker 
556*e5436536SAndroid Build Coastguard Worker   E_LPC_f_lsp_a_conversion(lsp_interpol, A, A_exp);
557*e5436536SAndroid Build Coastguard Worker 
558*e5436536SAndroid Build Coastguard Worker   return;
559*e5436536SAndroid Build Coastguard Worker }
560*e5436536SAndroid Build Coastguard Worker 
561*e5436536SAndroid Build Coastguard Worker /**
562*e5436536SAndroid Build Coastguard Worker  * \brief Perform LP synthesis by filtering the post-processed excitation u(n)
563*e5436536SAndroid Build Coastguard Worker  *        through the LP synthesis filter 1/A(z)
564*e5436536SAndroid Build Coastguard Worker  * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS.
565*e5436536SAndroid Build Coastguard Worker  * \param[in] length length of input/output signal.
566*e5436536SAndroid Build Coastguard Worker  * \param[in] x post-processed excitation u(n).
567*e5436536SAndroid Build Coastguard Worker  * \param[in,out] y LP synthesis signal and filter memory
568*e5436536SAndroid Build Coastguard Worker  * y[-M_LP_FILTER_ORDER..-1].
569*e5436536SAndroid Build Coastguard Worker  */
570*e5436536SAndroid Build Coastguard Worker 
571*e5436536SAndroid Build Coastguard Worker /* static */
Syn_filt(const FIXP_LPC a[],const INT a_exp,INT length,FIXP_DBL x[],FIXP_DBL y[])572*e5436536SAndroid Build Coastguard Worker void Syn_filt(const FIXP_LPC a[], /* (i) : a[m] prediction coefficients Q12 */
573*e5436536SAndroid Build Coastguard Worker               const INT a_exp,
574*e5436536SAndroid Build Coastguard Worker               INT length,   /* (i) : length of input/output signal (64|128)   */
575*e5436536SAndroid Build Coastguard Worker               FIXP_DBL x[], /* (i) : input signal Qx  */
576*e5436536SAndroid Build Coastguard Worker               FIXP_DBL y[]  /* (i/o) : filter states / output signal  Qx-s*/
577*e5436536SAndroid Build Coastguard Worker ) {
578*e5436536SAndroid Build Coastguard Worker   int i, j;
579*e5436536SAndroid Build Coastguard Worker   FIXP_DBL L_tmp;
580*e5436536SAndroid Build Coastguard Worker 
581*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < length; i++) {
582*e5436536SAndroid Build Coastguard Worker     L_tmp = (FIXP_DBL)0;
583*e5436536SAndroid Build Coastguard Worker 
584*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < M_LP_FILTER_ORDER; j++) {
585*e5436536SAndroid Build Coastguard Worker       L_tmp -= fMultDiv2(a[j], y[i - (j + 1)]) >> (LP_FILTER_SCALE - 1);
586*e5436536SAndroid Build Coastguard Worker     }
587*e5436536SAndroid Build Coastguard Worker 
588*e5436536SAndroid Build Coastguard Worker     L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE);
589*e5436536SAndroid Build Coastguard Worker     y[i] = fAddSaturate(L_tmp, x[i]);
590*e5436536SAndroid Build Coastguard Worker   }
591*e5436536SAndroid Build Coastguard Worker 
592*e5436536SAndroid Build Coastguard Worker   return;
593*e5436536SAndroid Build Coastguard Worker }
594*e5436536SAndroid Build Coastguard Worker 
595*e5436536SAndroid Build Coastguard Worker /**
596*e5436536SAndroid Build Coastguard Worker  * \brief Calculate de-emphasis 1/(1 - mu z^-1) on input signal.
597*e5436536SAndroid Build Coastguard Worker  * \param[in] x input signal.
598*e5436536SAndroid Build Coastguard Worker  * \param[out] y output signal.
599*e5436536SAndroid Build Coastguard Worker  * \param[in] L length of signal.
600*e5436536SAndroid Build Coastguard Worker  * \param[in,out] mem memory (signal[-1]).
601*e5436536SAndroid Build Coastguard Worker  */
602*e5436536SAndroid Build Coastguard Worker /* static */
Deemph(FIXP_DBL * x,FIXP_DBL * y,int L,FIXP_DBL * mem)603*e5436536SAndroid Build Coastguard Worker void Deemph(FIXP_DBL *x, FIXP_DBL *y, int L, FIXP_DBL *mem) {
604*e5436536SAndroid Build Coastguard Worker   int i;
605*e5436536SAndroid Build Coastguard Worker   FIXP_DBL yi = *mem;
606*e5436536SAndroid Build Coastguard Worker 
607*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < L; i++) {
608*e5436536SAndroid Build Coastguard Worker     FIXP_DBL xi = x[i] >> 1;
609*e5436536SAndroid Build Coastguard Worker     xi = fMultAddDiv2(xi, PREEMPH_FAC, yi);
610*e5436536SAndroid Build Coastguard Worker     yi = SATURATE_LEFT_SHIFT(xi, 1, 32);
611*e5436536SAndroid Build Coastguard Worker     y[i] = yi;
612*e5436536SAndroid Build Coastguard Worker   }
613*e5436536SAndroid Build Coastguard Worker   *mem = yi;
614*e5436536SAndroid Build Coastguard Worker   return;
615*e5436536SAndroid Build Coastguard Worker }
616*e5436536SAndroid Build Coastguard Worker 
617*e5436536SAndroid Build Coastguard Worker /**
618*e5436536SAndroid Build Coastguard Worker  * \brief Compute the LP residual by filtering the input speech through the
619*e5436536SAndroid Build Coastguard Worker  * analysis filter A(z).
620*e5436536SAndroid Build Coastguard Worker  * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS
621*e5436536SAndroid Build Coastguard Worker  * \param[in] x input signal (note that values x[-m..-1] are needed), exponent =
622*e5436536SAndroid Build Coastguard Worker  * SF_SYNTH
623*e5436536SAndroid Build Coastguard Worker  * \param[out] y output signal (residual), exponent = SF_EXC
624*e5436536SAndroid Build Coastguard Worker  * \param[in] l length of filtering
625*e5436536SAndroid Build Coastguard Worker  */
626*e5436536SAndroid Build Coastguard Worker /* static */
E_UTIL_residu(const FIXP_LPC * a,const INT a_exp,FIXP_DBL * x,FIXP_DBL * y,INT l)627*e5436536SAndroid Build Coastguard Worker void E_UTIL_residu(const FIXP_LPC *a, const INT a_exp, FIXP_DBL *x, FIXP_DBL *y,
628*e5436536SAndroid Build Coastguard Worker                    INT l) {
629*e5436536SAndroid Build Coastguard Worker   FIXP_DBL s;
630*e5436536SAndroid Build Coastguard Worker   INT i, j;
631*e5436536SAndroid Build Coastguard Worker 
632*e5436536SAndroid Build Coastguard Worker   /* (note that values x[-m..-1] are needed) */
633*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < l; i++) {
634*e5436536SAndroid Build Coastguard Worker     s = (FIXP_DBL)0;
635*e5436536SAndroid Build Coastguard Worker 
636*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < M_LP_FILTER_ORDER; j++) {
637*e5436536SAndroid Build Coastguard Worker       s += fMultDiv2(a[j], x[i - j - 1]) >> (LP_FILTER_SCALE - 1);
638*e5436536SAndroid Build Coastguard Worker     }
639*e5436536SAndroid Build Coastguard Worker 
640*e5436536SAndroid Build Coastguard Worker     s = scaleValue(s, a_exp + LP_FILTER_SCALE);
641*e5436536SAndroid Build Coastguard Worker     y[i] = fAddSaturate(s, x[i]);
642*e5436536SAndroid Build Coastguard Worker   }
643*e5436536SAndroid Build Coastguard Worker 
644*e5436536SAndroid Build Coastguard Worker   return;
645*e5436536SAndroid Build Coastguard Worker }
646*e5436536SAndroid Build Coastguard Worker 
647*e5436536SAndroid Build Coastguard Worker /* use to map subfr number to number of bits used for acb_index */
648*e5436536SAndroid Build Coastguard Worker static const UCHAR num_acb_idx_bits_table[2][NB_SUBFR] = {
649*e5436536SAndroid Build Coastguard Worker     {9, 6, 9, 6}, /* coreCoderFrameLength == 1024 */
650*e5436536SAndroid Build Coastguard Worker     {9, 6, 6, 0}  /* coreCoderFrameLength == 768  */
651*e5436536SAndroid Build Coastguard Worker };
652*e5436536SAndroid Build Coastguard Worker 
DecodePitchLag(HANDLE_FDK_BITSTREAM hBs,const UCHAR num_acb_idx_bits,const int PIT_MIN,const int PIT_FR2,const int PIT_FR1,const int PIT_MAX,int * pT0,int * pT0_frac,int * pT0_min,int * pT0_max)653*e5436536SAndroid Build Coastguard Worker static int DecodePitchLag(HANDLE_FDK_BITSTREAM hBs,
654*e5436536SAndroid Build Coastguard Worker                           const UCHAR num_acb_idx_bits,
655*e5436536SAndroid Build Coastguard Worker                           const int PIT_MIN, /* TMIN */
656*e5436536SAndroid Build Coastguard Worker                           const int PIT_FR2, /* TFR2 */
657*e5436536SAndroid Build Coastguard Worker                           const int PIT_FR1, /* TFR1 */
658*e5436536SAndroid Build Coastguard Worker                           const int PIT_MAX, /* TMAX */
659*e5436536SAndroid Build Coastguard Worker                           int *pT0, int *pT0_frac, int *pT0_min, int *pT0_max) {
660*e5436536SAndroid Build Coastguard Worker   int acb_idx;
661*e5436536SAndroid Build Coastguard Worker   int error = 0;
662*e5436536SAndroid Build Coastguard Worker   int T0, T0_frac;
663*e5436536SAndroid Build Coastguard Worker 
664*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT((num_acb_idx_bits == 9) || (num_acb_idx_bits == 6));
665*e5436536SAndroid Build Coastguard Worker 
666*e5436536SAndroid Build Coastguard Worker   acb_idx = FDKreadBits(hBs, num_acb_idx_bits);
667*e5436536SAndroid Build Coastguard Worker 
668*e5436536SAndroid Build Coastguard Worker   if (num_acb_idx_bits == 6) {
669*e5436536SAndroid Build Coastguard Worker     /* When the pitch value is encoded on 6 bits, a pitch resolution of 1/4 is
670*e5436536SAndroid Build Coastguard Worker        always used in the range [T1-8, T1+7.75], where T1 is nearest integer to
671*e5436536SAndroid Build Coastguard Worker        the fractional pitch lag of the previous subframe.
672*e5436536SAndroid Build Coastguard Worker     */
673*e5436536SAndroid Build Coastguard Worker     T0 = *pT0_min + acb_idx / 4;
674*e5436536SAndroid Build Coastguard Worker     T0_frac = acb_idx & 0x3;
675*e5436536SAndroid Build Coastguard Worker   } else { /* num_acb_idx_bits == 9 */
676*e5436536SAndroid Build Coastguard Worker     /* When the pitch value is encoded on 9 bits, a fractional pitch delay is
677*e5436536SAndroid Build Coastguard Worker        used with resolutions 0.25 in the range [TMIN, TFR2-0.25], resolutions
678*e5436536SAndroid Build Coastguard Worker        0.5 in the range [TFR2, TFR1-0.5], and integers only in the range [TFR1,
679*e5436536SAndroid Build Coastguard Worker        TMAX]. NOTE: for small sampling rates TMAX can get smaller than TFR1.
680*e5436536SAndroid Build Coastguard Worker     */
681*e5436536SAndroid Build Coastguard Worker     int T0_min, T0_max;
682*e5436536SAndroid Build Coastguard Worker 
683*e5436536SAndroid Build Coastguard Worker     if (acb_idx < (PIT_FR2 - PIT_MIN) * 4) {
684*e5436536SAndroid Build Coastguard Worker       /* first interval with 0.25 pitch resolution */
685*e5436536SAndroid Build Coastguard Worker       T0 = PIT_MIN + (acb_idx / 4);
686*e5436536SAndroid Build Coastguard Worker       T0_frac = acb_idx & 0x3;
687*e5436536SAndroid Build Coastguard Worker     } else if (acb_idx < ((PIT_FR2 - PIT_MIN) * 4 + (PIT_FR1 - PIT_FR2) * 2)) {
688*e5436536SAndroid Build Coastguard Worker       /* second interval with 0.5 pitch resolution */
689*e5436536SAndroid Build Coastguard Worker       acb_idx -= (PIT_FR2 - PIT_MIN) * 4;
690*e5436536SAndroid Build Coastguard Worker       T0 = PIT_FR2 + (acb_idx / 2);
691*e5436536SAndroid Build Coastguard Worker       T0_frac = (acb_idx & 0x1) * 2;
692*e5436536SAndroid Build Coastguard Worker     } else {
693*e5436536SAndroid Build Coastguard Worker       /* third interval with 1.0 pitch resolution */
694*e5436536SAndroid Build Coastguard Worker       T0 = acb_idx + PIT_FR1 - ((PIT_FR2 - PIT_MIN) * 4) -
695*e5436536SAndroid Build Coastguard Worker            ((PIT_FR1 - PIT_FR2) * 2);
696*e5436536SAndroid Build Coastguard Worker       T0_frac = 0;
697*e5436536SAndroid Build Coastguard Worker     }
698*e5436536SAndroid Build Coastguard Worker     /* find T0_min and T0_max for subframe 1 or 3 */
699*e5436536SAndroid Build Coastguard Worker     T0_min = T0 - 8;
700*e5436536SAndroid Build Coastguard Worker     if (T0_min < PIT_MIN) {
701*e5436536SAndroid Build Coastguard Worker       T0_min = PIT_MIN;
702*e5436536SAndroid Build Coastguard Worker     }
703*e5436536SAndroid Build Coastguard Worker     T0_max = T0_min + 15;
704*e5436536SAndroid Build Coastguard Worker     if (T0_max > PIT_MAX) {
705*e5436536SAndroid Build Coastguard Worker       T0_max = PIT_MAX;
706*e5436536SAndroid Build Coastguard Worker       T0_min = T0_max - 15;
707*e5436536SAndroid Build Coastguard Worker     }
708*e5436536SAndroid Build Coastguard Worker     *pT0_min = T0_min;
709*e5436536SAndroid Build Coastguard Worker     *pT0_max = T0_max;
710*e5436536SAndroid Build Coastguard Worker   }
711*e5436536SAndroid Build Coastguard Worker   *pT0 = T0;
712*e5436536SAndroid Build Coastguard Worker   *pT0_frac = T0_frac;
713*e5436536SAndroid Build Coastguard Worker 
714*e5436536SAndroid Build Coastguard Worker   return error;
715*e5436536SAndroid Build Coastguard Worker }
ConcealPitchLag(CAcelpStaticMem * acelp_mem,const int PIT_MAX,int * pT0,int * pT0_frac)716*e5436536SAndroid Build Coastguard Worker static void ConcealPitchLag(CAcelpStaticMem *acelp_mem, const int PIT_MAX,
717*e5436536SAndroid Build Coastguard Worker                             int *pT0, int *pT0_frac) {
718*e5436536SAndroid Build Coastguard Worker   USHORT *pold_T0 = &acelp_mem->old_T0;
719*e5436536SAndroid Build Coastguard Worker   UCHAR *pold_T0_frac = &acelp_mem->old_T0_frac;
720*e5436536SAndroid Build Coastguard Worker 
721*e5436536SAndroid Build Coastguard Worker   if ((int)*pold_T0 >= PIT_MAX) {
722*e5436536SAndroid Build Coastguard Worker     *pold_T0 = (USHORT)(PIT_MAX - 5);
723*e5436536SAndroid Build Coastguard Worker   }
724*e5436536SAndroid Build Coastguard Worker   *pT0 = (int)*pold_T0;
725*e5436536SAndroid Build Coastguard Worker   *pT0_frac = (int)*pold_T0_frac;
726*e5436536SAndroid Build Coastguard Worker }
727*e5436536SAndroid Build Coastguard Worker 
728*e5436536SAndroid Build Coastguard Worker static UCHAR tab_coremode2nbits[8] = {20, 28, 36, 44, 52, 64, 12, 16};
729*e5436536SAndroid Build Coastguard Worker 
MapCoreMode2NBits(int core_mode)730*e5436536SAndroid Build Coastguard Worker static int MapCoreMode2NBits(int core_mode) {
731*e5436536SAndroid Build Coastguard Worker   return (int)tab_coremode2nbits[core_mode];
732*e5436536SAndroid Build Coastguard Worker }
733*e5436536SAndroid Build Coastguard Worker 
CLpd_AcelpDecode(CAcelpStaticMem * acelp_mem,INT i_offset,const FIXP_LPC lsp_old[M_LP_FILTER_ORDER],const FIXP_LPC lsp_new[M_LP_FILTER_ORDER],FIXP_SGL stab_fac,CAcelpChannelData * pAcelpData,INT numLostSubframes,int lastLpcLost,int frameCnt,FIXP_DBL synth[],int pT[],FIXP_DBL * pit_gain,INT coreCoderFrameLength)734*e5436536SAndroid Build Coastguard Worker void CLpd_AcelpDecode(CAcelpStaticMem *acelp_mem, INT i_offset,
735*e5436536SAndroid Build Coastguard Worker                       const FIXP_LPC lsp_old[M_LP_FILTER_ORDER],
736*e5436536SAndroid Build Coastguard Worker                       const FIXP_LPC lsp_new[M_LP_FILTER_ORDER],
737*e5436536SAndroid Build Coastguard Worker                       FIXP_SGL stab_fac, CAcelpChannelData *pAcelpData,
738*e5436536SAndroid Build Coastguard Worker                       INT numLostSubframes, int lastLpcLost, int frameCnt,
739*e5436536SAndroid Build Coastguard Worker                       FIXP_DBL synth[], int pT[], FIXP_DBL *pit_gain,
740*e5436536SAndroid Build Coastguard Worker                       INT coreCoderFrameLength) {
741*e5436536SAndroid Build Coastguard Worker   int i_subfr, subfr_nr, l_div, T;
742*e5436536SAndroid Build Coastguard Worker   int T0 = -1, T0_frac = -1; /* mark invalid */
743*e5436536SAndroid Build Coastguard Worker 
744*e5436536SAndroid Build Coastguard Worker   int pit_gain_index = 0;
745*e5436536SAndroid Build Coastguard Worker 
746*e5436536SAndroid Build Coastguard Worker   const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset); /* maximum pitch lag */
747*e5436536SAndroid Build Coastguard Worker 
748*e5436536SAndroid Build Coastguard Worker   FIXP_COD *code;
749*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *exc2;
750*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *syn;
751*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *exc;
752*e5436536SAndroid Build Coastguard Worker   FIXP_LPC A[M_LP_FILTER_ORDER];
753*e5436536SAndroid Build Coastguard Worker   INT A_exp;
754*e5436536SAndroid Build Coastguard Worker 
755*e5436536SAndroid Build Coastguard Worker   FIXP_DBL period_fac;
756*e5436536SAndroid Build Coastguard Worker   FIXP_SGL gain_pit;
757*e5436536SAndroid Build Coastguard Worker   FIXP_DBL gain_code, gain_code_smooth, Ener_code;
758*e5436536SAndroid Build Coastguard Worker   int Ener_code_e;
759*e5436536SAndroid Build Coastguard Worker   int n;
760*e5436536SAndroid Build Coastguard Worker   int bfi = (numLostSubframes > 0) ? 1 : 0;
761*e5436536SAndroid Build Coastguard Worker 
762*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(
763*e5436536SAndroid Build Coastguard Worker       exc_buf, FIXP_DBL,
764*e5436536SAndroid Build Coastguard Worker       PIT_MAX_MAX + L_INTERPOL + L_DIV + 1); /* 411 + 17 + 256 + 1 = 685 */
765*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL,
766*e5436536SAndroid Build Coastguard Worker                         M_LP_FILTER_ORDER + L_DIV); /* 16 + 256 = 272 */
767*e5436536SAndroid Build Coastguard Worker   /* use same memory for code[L_SUBFR] and exc2[L_SUBFR] */
768*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_SUBFR); /* 64 */
769*e5436536SAndroid Build Coastguard Worker   /* make sure they don't overlap if they are accessed alternatingly in
770*e5436536SAndroid Build Coastguard Worker    * BuildAdaptiveExcitation() */
771*e5436536SAndroid Build Coastguard Worker #if (COD_BITS == FRACT_BITS)
772*e5436536SAndroid Build Coastguard Worker   code = (FIXP_COD *)(tmp_buf + L_SUBFR / 2);
773*e5436536SAndroid Build Coastguard Worker #elif (COD_BITS == DFRACT_BITS)
774*e5436536SAndroid Build Coastguard Worker   code = (FIXP_COD *)tmp_buf;
775*e5436536SAndroid Build Coastguard Worker #endif
776*e5436536SAndroid Build Coastguard Worker   exc2 = (FIXP_DBL *)tmp_buf;
777*e5436536SAndroid Build Coastguard Worker 
778*e5436536SAndroid Build Coastguard Worker   syn = syn_buf + M_LP_FILTER_ORDER;
779*e5436536SAndroid Build Coastguard Worker   exc = exc_buf + PIT_MAX_MAX + L_INTERPOL;
780*e5436536SAndroid Build Coastguard Worker 
781*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(syn_buf, acelp_mem->old_syn_mem,
782*e5436536SAndroid Build Coastguard Worker             M_LP_FILTER_ORDER * sizeof(FIXP_DBL));
783*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(exc_buf, acelp_mem->old_exc_mem,
784*e5436536SAndroid Build Coastguard Worker             (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL));
785*e5436536SAndroid Build Coastguard Worker 
786*e5436536SAndroid Build Coastguard Worker   FDKmemclear(exc_buf + (PIT_MAX_MAX + L_INTERPOL),
787*e5436536SAndroid Build Coastguard Worker               (L_DIV + 1) * sizeof(FIXP_DBL));
788*e5436536SAndroid Build Coastguard Worker 
789*e5436536SAndroid Build Coastguard Worker   l_div = coreCoderFrameLength / NB_DIV;
790*e5436536SAndroid Build Coastguard Worker 
791*e5436536SAndroid Build Coastguard Worker   for (i_subfr = 0, subfr_nr = 0; i_subfr < l_div;
792*e5436536SAndroid Build Coastguard Worker        i_subfr += L_SUBFR, subfr_nr++) {
793*e5436536SAndroid Build Coastguard Worker     /*-------------------------------------------------*
794*e5436536SAndroid Build Coastguard Worker      * - Decode pitch lag (T0 and T0_frac)             *
795*e5436536SAndroid Build Coastguard Worker      *-------------------------------------------------*/
796*e5436536SAndroid Build Coastguard Worker     if (bfi) {
797*e5436536SAndroid Build Coastguard Worker       ConcealPitchLag(acelp_mem, PIT_MAX, &T0, &T0_frac);
798*e5436536SAndroid Build Coastguard Worker     } else {
799*e5436536SAndroid Build Coastguard Worker       T0 = (int)pAcelpData->T0[subfr_nr];
800*e5436536SAndroid Build Coastguard Worker       T0_frac = (int)pAcelpData->T0_frac[subfr_nr];
801*e5436536SAndroid Build Coastguard Worker     }
802*e5436536SAndroid Build Coastguard Worker 
803*e5436536SAndroid Build Coastguard Worker     /*-------------------------------------------------*
804*e5436536SAndroid Build Coastguard Worker      * - Find the pitch gain, the interpolation filter *
805*e5436536SAndroid Build Coastguard Worker      *   and the adaptive codebook vector.             *
806*e5436536SAndroid Build Coastguard Worker      *-------------------------------------------------*/
807*e5436536SAndroid Build Coastguard Worker     Pred_lt4(&exc[i_subfr], T0, T0_frac);
808*e5436536SAndroid Build Coastguard Worker 
809*e5436536SAndroid Build Coastguard Worker     if ((!bfi && pAcelpData->ltp_filtering_flag[subfr_nr] == 0) ||
810*e5436536SAndroid Build Coastguard Worker         (bfi && numLostSubframes == 1 && stab_fac < FL2FXCONST_SGL(0.25f))) {
811*e5436536SAndroid Build Coastguard Worker       /* find pitch excitation with lp filter: v'(n) => v(n) */
812*e5436536SAndroid Build Coastguard Worker       Pred_lt4_postfilter(&exc[i_subfr]);
813*e5436536SAndroid Build Coastguard Worker     }
814*e5436536SAndroid Build Coastguard Worker 
815*e5436536SAndroid Build Coastguard Worker     /*-------------------------------------------------------*
816*e5436536SAndroid Build Coastguard Worker      * - Decode innovative codebook.                         *
817*e5436536SAndroid Build Coastguard Worker      * - Add the fixed-gain pitch contribution to code[].    *
818*e5436536SAndroid Build Coastguard Worker      *-------------------------------------------------------*/
819*e5436536SAndroid Build Coastguard Worker     if (bfi) {
820*e5436536SAndroid Build Coastguard Worker       for (n = 0; n < L_SUBFR; n++) {
821*e5436536SAndroid Build Coastguard Worker         code[n] =
822*e5436536SAndroid Build Coastguard Worker             FX_SGL2FX_COD((FIXP_SGL)E_UTIL_random(&acelp_mem->seed_ace)) >> 4;
823*e5436536SAndroid Build Coastguard Worker       }
824*e5436536SAndroid Build Coastguard Worker     } else {
825*e5436536SAndroid Build Coastguard Worker       int nbits = MapCoreMode2NBits((int)pAcelpData->acelp_core_mode);
826*e5436536SAndroid Build Coastguard Worker       D_ACELP_decode_4t64(pAcelpData->icb_index[subfr_nr], nbits, &code[0]);
827*e5436536SAndroid Build Coastguard Worker     }
828*e5436536SAndroid Build Coastguard Worker 
829*e5436536SAndroid Build Coastguard Worker     T = T0;
830*e5436536SAndroid Build Coastguard Worker     if (T0_frac > 2) {
831*e5436536SAndroid Build Coastguard Worker       T += 1;
832*e5436536SAndroid Build Coastguard Worker     }
833*e5436536SAndroid Build Coastguard Worker 
834*e5436536SAndroid Build Coastguard Worker     Preemph_code(code);
835*e5436536SAndroid Build Coastguard Worker     Pit_shrp(code, T);
836*e5436536SAndroid Build Coastguard Worker 
837*e5436536SAndroid Build Coastguard Worker     /* Output pitch lag for bass post-filter */
838*e5436536SAndroid Build Coastguard Worker     if (T > PIT_MAX) {
839*e5436536SAndroid Build Coastguard Worker       pT[subfr_nr] = PIT_MAX;
840*e5436536SAndroid Build Coastguard Worker     } else {
841*e5436536SAndroid Build Coastguard Worker       pT[subfr_nr] = T;
842*e5436536SAndroid Build Coastguard Worker     }
843*e5436536SAndroid Build Coastguard Worker     D_gain2_plus(
844*e5436536SAndroid Build Coastguard Worker         pAcelpData->gains[subfr_nr],
845*e5436536SAndroid Build Coastguard Worker         code,       /* (i)  : Innovative code vector, exponent = SF_CODE */
846*e5436536SAndroid Build Coastguard Worker         &gain_pit,  /* (o)  : Quantized pitch gain, exponent = SF_GAIN_P */
847*e5436536SAndroid Build Coastguard Worker         &gain_code, /* (o)  : Quantized codebook gain                    */
848*e5436536SAndroid Build Coastguard Worker         pAcelpData
849*e5436536SAndroid Build Coastguard Worker             ->mean_energy, /* (i)  : mean_ener defined in open-loop (2 bits) */
850*e5436536SAndroid Build Coastguard Worker         bfi, &acelp_mem->past_gpit, &acelp_mem->past_gcode,
851*e5436536SAndroid Build Coastguard Worker         &Ener_code,    /* (o)  : Innovative code vector energy              */
852*e5436536SAndroid Build Coastguard Worker         &Ener_code_e); /* (o)  : Innovative code vector energy exponent     */
853*e5436536SAndroid Build Coastguard Worker 
854*e5436536SAndroid Build Coastguard Worker     pit_gain[pit_gain_index++] = FX_SGL2FX_DBL(gain_pit);
855*e5436536SAndroid Build Coastguard Worker 
856*e5436536SAndroid Build Coastguard Worker     /* calc periodicity factor r_v */
857*e5436536SAndroid Build Coastguard Worker     period_fac =
858*e5436536SAndroid Build Coastguard Worker         calc_period_factor(/* (o) : factor (-1=unvoiced to 1=voiced)    */
859*e5436536SAndroid Build Coastguard Worker                            &exc[i_subfr], /* (i) : pitch excitation, exponent =
860*e5436536SAndroid Build Coastguard Worker                                              SF_EXC */
861*e5436536SAndroid Build Coastguard Worker                            gain_pit,      /* (i) : gain of pitch, exponent =
862*e5436536SAndroid Build Coastguard Worker                                              SF_GAIN_P */
863*e5436536SAndroid Build Coastguard Worker                            gain_code,     /* (i) : gain of code     */
864*e5436536SAndroid Build Coastguard Worker                            Ener_code,     /* (i) : Energy of code[]     */
865*e5436536SAndroid Build Coastguard Worker                            Ener_code_e);  /* (i) : Exponent of energy of code[]
866*e5436536SAndroid Build Coastguard Worker                                            */
867*e5436536SAndroid Build Coastguard Worker 
868*e5436536SAndroid Build Coastguard Worker     if (lastLpcLost && frameCnt == 0) {
869*e5436536SAndroid Build Coastguard Worker       if (gain_pit > FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P))) {
870*e5436536SAndroid Build Coastguard Worker         gain_pit = FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P));
871*e5436536SAndroid Build Coastguard Worker       }
872*e5436536SAndroid Build Coastguard Worker     }
873*e5436536SAndroid Build Coastguard Worker 
874*e5436536SAndroid Build Coastguard Worker     gain_code_smooth =
875*e5436536SAndroid Build Coastguard Worker         noise_enhancer(/* (o) : smoothed gain g_sc exponent = SF_GAIN_C */
876*e5436536SAndroid Build Coastguard Worker                        gain_code,  /* (i) : Quantized codebook gain  */
877*e5436536SAndroid Build Coastguard Worker                        period_fac, /* (i) : periodicity factor (-1=unvoiced to
878*e5436536SAndroid Build Coastguard Worker                                       1=voiced)  */
879*e5436536SAndroid Build Coastguard Worker                        stab_fac,   /* (i) : stability factor (0 <= ... < 1),
880*e5436536SAndroid Build Coastguard Worker                                       exponent = 1 */
881*e5436536SAndroid Build Coastguard Worker                        &acelp_mem->gc_threshold);
882*e5436536SAndroid Build Coastguard Worker 
883*e5436536SAndroid Build Coastguard Worker     /* Compute adaptive codebook update u'(n), pitch enhancement c'(n) and
884*e5436536SAndroid Build Coastguard Worker      * post-processed excitation u(n). */
885*e5436536SAndroid Build Coastguard Worker     BuildAdaptiveExcitation(code, exc + i_subfr, gain_pit, gain_code,
886*e5436536SAndroid Build Coastguard Worker                             gain_code_smooth, period_fac, exc2);
887*e5436536SAndroid Build Coastguard Worker 
888*e5436536SAndroid Build Coastguard Worker     /* Interpolate filter coeffs for current subframe in lsp domain and convert
889*e5436536SAndroid Build Coastguard Worker      * to LP domain */
890*e5436536SAndroid Build Coastguard Worker     int_lpc_acelp(lsp_old,  /* input : LSPs from past frame              */
891*e5436536SAndroid Build Coastguard Worker                   lsp_new,  /* input : LSPs from present frame           */
892*e5436536SAndroid Build Coastguard Worker                   subfr_nr, /* input : ACELP subframe index              */
893*e5436536SAndroid Build Coastguard Worker                   coreCoderFrameLength / L_DIV,
894*e5436536SAndroid Build Coastguard Worker                   A, /* output: LP coefficients of this subframe  */
895*e5436536SAndroid Build Coastguard Worker                   &A_exp);
896*e5436536SAndroid Build Coastguard Worker 
897*e5436536SAndroid Build Coastguard Worker     Syn_filt(A, /* (i) : a[m] prediction coefficients               */
898*e5436536SAndroid Build Coastguard Worker              A_exp, L_SUBFR, /* (i) : length */
899*e5436536SAndroid Build Coastguard Worker              exc2, /* (i) : input signal                               */
900*e5436536SAndroid Build Coastguard Worker              &syn[i_subfr] /* (i/o) : filter states / output signal */
901*e5436536SAndroid Build Coastguard Worker     );
902*e5436536SAndroid Build Coastguard Worker 
903*e5436536SAndroid Build Coastguard Worker   } /* end of subframe loop */
904*e5436536SAndroid Build Coastguard Worker 
905*e5436536SAndroid Build Coastguard Worker   /* update pitch value for bfi procedure */
906*e5436536SAndroid Build Coastguard Worker   acelp_mem->old_T0_frac = T0_frac;
907*e5436536SAndroid Build Coastguard Worker   acelp_mem->old_T0 = T0;
908*e5436536SAndroid Build Coastguard Worker 
909*e5436536SAndroid Build Coastguard Worker   /* save old excitation and old synthesis memory for next ACELP frame */
910*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(acelp_mem->old_exc_mem, exc + l_div - (PIT_MAX_MAX + L_INTERPOL),
911*e5436536SAndroid Build Coastguard Worker             sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL));
912*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + l_div,
913*e5436536SAndroid Build Coastguard Worker             sizeof(FIXP_DBL) * M_LP_FILTER_ORDER);
914*e5436536SAndroid Build Coastguard Worker 
915*e5436536SAndroid Build Coastguard Worker   Deemph(syn, synth, l_div,
916*e5436536SAndroid Build Coastguard Worker          &acelp_mem->de_emph_mem); /* ref soft: mem = synth[-1] */
917*e5436536SAndroid Build Coastguard Worker 
918*e5436536SAndroid Build Coastguard Worker   scaleValues(synth, l_div, -ACELP_OUTSCALE);
919*e5436536SAndroid Build Coastguard Worker   acelp_mem->deemph_mem_wsyn = acelp_mem->de_emph_mem;
920*e5436536SAndroid Build Coastguard Worker 
921*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_SUBFR);
922*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV);
923*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV + 1);
924*e5436536SAndroid Build Coastguard Worker   return;
925*e5436536SAndroid Build Coastguard Worker }
926*e5436536SAndroid Build Coastguard Worker 
CLpd_AcelpReset(CAcelpStaticMem * acelp)927*e5436536SAndroid Build Coastguard Worker void CLpd_AcelpReset(CAcelpStaticMem *acelp) {
928*e5436536SAndroid Build Coastguard Worker   acelp->gc_threshold = (FIXP_DBL)0;
929*e5436536SAndroid Build Coastguard Worker 
930*e5436536SAndroid Build Coastguard Worker   acelp->past_gpit = (FIXP_SGL)0;
931*e5436536SAndroid Build Coastguard Worker   acelp->past_gcode = (FIXP_DBL)0;
932*e5436536SAndroid Build Coastguard Worker   acelp->old_T0 = 64;
933*e5436536SAndroid Build Coastguard Worker   acelp->old_T0_frac = 0;
934*e5436536SAndroid Build Coastguard Worker   acelp->deemph_mem_wsyn = (FIXP_DBL)0;
935*e5436536SAndroid Build Coastguard Worker   acelp->wsyn_rms = (FIXP_DBL)0;
936*e5436536SAndroid Build Coastguard Worker   acelp->seed_ace = 0;
937*e5436536SAndroid Build Coastguard Worker }
938*e5436536SAndroid Build Coastguard Worker 
939*e5436536SAndroid Build Coastguard Worker /* TCX time domain concealment */
940*e5436536SAndroid Build Coastguard Worker /*   Compare to figure 13a on page 54 in 3GPP TS 26.290 */
CLpd_TcxTDConceal(CAcelpStaticMem * acelp_mem,SHORT * pitch,const FIXP_LPC lsp_old[M_LP_FILTER_ORDER],const FIXP_LPC lsp_new[M_LP_FILTER_ORDER],const FIXP_SGL stab_fac,INT nLostSf,FIXP_DBL synth[],INT coreCoderFrameLength,UCHAR last_tcx_noise_factor)941*e5436536SAndroid Build Coastguard Worker void CLpd_TcxTDConceal(CAcelpStaticMem *acelp_mem, SHORT *pitch,
942*e5436536SAndroid Build Coastguard Worker                        const FIXP_LPC lsp_old[M_LP_FILTER_ORDER],
943*e5436536SAndroid Build Coastguard Worker                        const FIXP_LPC lsp_new[M_LP_FILTER_ORDER],
944*e5436536SAndroid Build Coastguard Worker                        const FIXP_SGL stab_fac, INT nLostSf, FIXP_DBL synth[],
945*e5436536SAndroid Build Coastguard Worker                        INT coreCoderFrameLength, UCHAR last_tcx_noise_factor) {
946*e5436536SAndroid Build Coastguard Worker   /* repeat past excitation with pitch from previous decoded TCX frame */
947*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(
948*e5436536SAndroid Build Coastguard Worker       exc_buf, FIXP_DBL,
949*e5436536SAndroid Build Coastguard Worker       PIT_MAX_MAX + L_INTERPOL + L_DIV); /* 411 +  17 + 256 + 1 =  */
950*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL,
951*e5436536SAndroid Build Coastguard Worker                         M_LP_FILTER_ORDER + L_DIV); /* 256 +  16           =  */
952*e5436536SAndroid Build Coastguard Worker                                                     /*                    +=  */
953*e5436536SAndroid Build Coastguard Worker   FIXP_DBL ns_buf[L_DIV + 1];
954*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *syn = syn_buf + M_LP_FILTER_ORDER;
955*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *exc = exc_buf + PIT_MAX_MAX + L_INTERPOL;
956*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *ns = ns_buf + 1;
957*e5436536SAndroid Build Coastguard Worker   FIXP_DBL tmp, fact_exc;
958*e5436536SAndroid Build Coastguard Worker   INT T = fMin(*pitch, (SHORT)PIT_MAX_MAX);
959*e5436536SAndroid Build Coastguard Worker   int i, i_subfr, subfr_nr;
960*e5436536SAndroid Build Coastguard Worker   int lDiv = coreCoderFrameLength / NB_DIV;
961*e5436536SAndroid Build Coastguard Worker 
962*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(syn_buf, acelp_mem->old_syn_mem,
963*e5436536SAndroid Build Coastguard Worker             M_LP_FILTER_ORDER * sizeof(FIXP_DBL));
964*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(exc_buf, acelp_mem->old_exc_mem,
965*e5436536SAndroid Build Coastguard Worker             (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL));
966*e5436536SAndroid Build Coastguard Worker 
967*e5436536SAndroid Build Coastguard Worker   /* if we lost all packets (i.e. 1 packet of TCX-20 ms, 2 packets of
968*e5436536SAndroid Build Coastguard Worker      the TCX-40 ms or 4 packets of the TCX-80ms), we lost the whole
969*e5436536SAndroid Build Coastguard Worker      coded frame extrapolation strategy: repeat lost excitation and
970*e5436536SAndroid Build Coastguard Worker      use extrapolated LSFs */
971*e5436536SAndroid Build Coastguard Worker 
972*e5436536SAndroid Build Coastguard Worker   /* AMR-WB+ like TCX TD concealment */
973*e5436536SAndroid Build Coastguard Worker 
974*e5436536SAndroid Build Coastguard Worker   /* number of lost frame cmpt */
975*e5436536SAndroid Build Coastguard Worker   if (nLostSf < 2) {
976*e5436536SAndroid Build Coastguard Worker     fact_exc = FL2FXCONST_DBL(0.8f);
977*e5436536SAndroid Build Coastguard Worker   } else {
978*e5436536SAndroid Build Coastguard Worker     fact_exc = FL2FXCONST_DBL(0.4f);
979*e5436536SAndroid Build Coastguard Worker   }
980*e5436536SAndroid Build Coastguard Worker 
981*e5436536SAndroid Build Coastguard Worker   /* repeat past excitation */
982*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < lDiv; i++) {
983*e5436536SAndroid Build Coastguard Worker     exc[i] = fMult(fact_exc, exc[i - T]);
984*e5436536SAndroid Build Coastguard Worker   }
985*e5436536SAndroid Build Coastguard Worker 
986*e5436536SAndroid Build Coastguard Worker   tmp = fMult(fact_exc, acelp_mem->wsyn_rms);
987*e5436536SAndroid Build Coastguard Worker   acelp_mem->wsyn_rms = tmp;
988*e5436536SAndroid Build Coastguard Worker 
989*e5436536SAndroid Build Coastguard Worker   /* init deemph_mem_wsyn */
990*e5436536SAndroid Build Coastguard Worker   acelp_mem->deemph_mem_wsyn = exc[-1];
991*e5436536SAndroid Build Coastguard Worker 
992*e5436536SAndroid Build Coastguard Worker   ns[-1] = acelp_mem->deemph_mem_wsyn;
993*e5436536SAndroid Build Coastguard Worker 
994*e5436536SAndroid Build Coastguard Worker   for (i_subfr = 0, subfr_nr = 0; i_subfr < lDiv;
995*e5436536SAndroid Build Coastguard Worker        i_subfr += L_SUBFR, subfr_nr++) {
996*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tRes[L_SUBFR];
997*e5436536SAndroid Build Coastguard Worker     FIXP_LPC A[M_LP_FILTER_ORDER];
998*e5436536SAndroid Build Coastguard Worker     INT A_exp;
999*e5436536SAndroid Build Coastguard Worker 
1000*e5436536SAndroid Build Coastguard Worker     /* interpolate LPC coefficients */
1001*e5436536SAndroid Build Coastguard Worker     int_lpc_acelp(lsp_old, lsp_new, subfr_nr, lDiv / L_SUBFR, A, &A_exp);
1002*e5436536SAndroid Build Coastguard Worker 
1003*e5436536SAndroid Build Coastguard Worker     Syn_filt(A,              /* (i) : a[m] prediction coefficients         */
1004*e5436536SAndroid Build Coastguard Worker              A_exp, L_SUBFR, /* (i) : length                               */
1005*e5436536SAndroid Build Coastguard Worker              &exc[i_subfr],  /* (i) : input signal                         */
1006*e5436536SAndroid Build Coastguard Worker              &syn[i_subfr]   /* (i/o) : filter states / output signal      */
1007*e5436536SAndroid Build Coastguard Worker     );
1008*e5436536SAndroid Build Coastguard Worker 
1009*e5436536SAndroid Build Coastguard Worker     E_LPC_a_weight(
1010*e5436536SAndroid Build Coastguard Worker         A, A,
1011*e5436536SAndroid Build Coastguard Worker         M_LP_FILTER_ORDER); /* overwrite A as it is not needed any longer */
1012*e5436536SAndroid Build Coastguard Worker 
1013*e5436536SAndroid Build Coastguard Worker     E_UTIL_residu(A, A_exp, &syn[i_subfr], tRes, L_SUBFR);
1014*e5436536SAndroid Build Coastguard Worker 
1015*e5436536SAndroid Build Coastguard Worker     Deemph(tRes, &ns[i_subfr], L_SUBFR, &acelp_mem->deemph_mem_wsyn);
1016*e5436536SAndroid Build Coastguard Worker 
1017*e5436536SAndroid Build Coastguard Worker     /* Amplitude limiter (saturate at wsyn_rms) */
1018*e5436536SAndroid Build Coastguard Worker     for (i = i_subfr; i < i_subfr + L_SUBFR; i++) {
1019*e5436536SAndroid Build Coastguard Worker       if (ns[i] > tmp) {
1020*e5436536SAndroid Build Coastguard Worker         ns[i] = tmp;
1021*e5436536SAndroid Build Coastguard Worker       } else {
1022*e5436536SAndroid Build Coastguard Worker         if (ns[i] < -tmp) {
1023*e5436536SAndroid Build Coastguard Worker           ns[i] = -tmp;
1024*e5436536SAndroid Build Coastguard Worker         }
1025*e5436536SAndroid Build Coastguard Worker       }
1026*e5436536SAndroid Build Coastguard Worker     }
1027*e5436536SAndroid Build Coastguard Worker 
1028*e5436536SAndroid Build Coastguard Worker     E_UTIL_preemph(&ns[i_subfr], tRes, L_SUBFR);
1029*e5436536SAndroid Build Coastguard Worker 
1030*e5436536SAndroid Build Coastguard Worker     Syn_filt(A,              /* (i) : a[m] prediction coefficients         */
1031*e5436536SAndroid Build Coastguard Worker              A_exp, L_SUBFR, /* (i) : length                               */
1032*e5436536SAndroid Build Coastguard Worker              tRes,           /* (i) : input signal                         */
1033*e5436536SAndroid Build Coastguard Worker              &syn[i_subfr]   /* (i/o) : filter states / output signal      */
1034*e5436536SAndroid Build Coastguard Worker     );
1035*e5436536SAndroid Build Coastguard Worker 
1036*e5436536SAndroid Build Coastguard Worker     FDKmemmove(&synth[i_subfr], &syn[i_subfr], L_SUBFR * sizeof(FIXP_DBL));
1037*e5436536SAndroid Build Coastguard Worker   }
1038*e5436536SAndroid Build Coastguard Worker 
1039*e5436536SAndroid Build Coastguard Worker   /* save old excitation and old synthesis memory for next ACELP frame */
1040*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(acelp_mem->old_exc_mem, exc + lDiv - (PIT_MAX_MAX + L_INTERPOL),
1041*e5436536SAndroid Build Coastguard Worker             sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL));
1042*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + lDiv,
1043*e5436536SAndroid Build Coastguard Worker             sizeof(FIXP_DBL) * M_LP_FILTER_ORDER);
1044*e5436536SAndroid Build Coastguard Worker   acelp_mem->de_emph_mem = acelp_mem->deemph_mem_wsyn;
1045*e5436536SAndroid Build Coastguard Worker 
1046*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV);
1047*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV);
1048*e5436536SAndroid Build Coastguard Worker }
1049*e5436536SAndroid Build Coastguard Worker 
Acelp_PreProcessing(FIXP_DBL * synth_buf,FIXP_DBL * old_synth,INT * pitch,INT * old_T_pf,FIXP_DBL * pit_gain,FIXP_DBL * old_gain_pf,INT samplingRate,INT * i_offset,INT coreCoderFrameLength,INT synSfd,INT nbSubfrSuperfr)1050*e5436536SAndroid Build Coastguard Worker void Acelp_PreProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch,
1051*e5436536SAndroid Build Coastguard Worker                          INT *old_T_pf, FIXP_DBL *pit_gain,
1052*e5436536SAndroid Build Coastguard Worker                          FIXP_DBL *old_gain_pf, INT samplingRate, INT *i_offset,
1053*e5436536SAndroid Build Coastguard Worker                          INT coreCoderFrameLength, INT synSfd,
1054*e5436536SAndroid Build Coastguard Worker                          INT nbSubfrSuperfr) {
1055*e5436536SAndroid Build Coastguard Worker   int n;
1056*e5436536SAndroid Build Coastguard Worker 
1057*e5436536SAndroid Build Coastguard Worker   /* init beginning of synth_buf with old synthesis from previous frame */
1058*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(synth_buf, old_synth, sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY));
1059*e5436536SAndroid Build Coastguard Worker 
1060*e5436536SAndroid Build Coastguard Worker   /* calculate pitch lag offset for ACELP decoder */
1061*e5436536SAndroid Build Coastguard Worker   *i_offset =
1062*e5436536SAndroid Build Coastguard Worker       (samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM -
1063*e5436536SAndroid Build Coastguard Worker       PIT_MIN_12k8;
1064*e5436536SAndroid Build Coastguard Worker 
1065*e5436536SAndroid Build Coastguard Worker   /* for bass postfilter */
1066*e5436536SAndroid Build Coastguard Worker   for (n = 0; n < synSfd; n++) {
1067*e5436536SAndroid Build Coastguard Worker     pitch[n] = old_T_pf[n];
1068*e5436536SAndroid Build Coastguard Worker     pit_gain[n] = old_gain_pf[n];
1069*e5436536SAndroid Build Coastguard Worker   }
1070*e5436536SAndroid Build Coastguard Worker   for (n = 0; n < nbSubfrSuperfr; n++) {
1071*e5436536SAndroid Build Coastguard Worker     pitch[n + synSfd] = L_SUBFR;
1072*e5436536SAndroid Build Coastguard Worker     pit_gain[n + synSfd] = (FIXP_DBL)0;
1073*e5436536SAndroid Build Coastguard Worker   }
1074*e5436536SAndroid Build Coastguard Worker }
1075*e5436536SAndroid Build Coastguard Worker 
Acelp_PostProcessing(FIXP_DBL * synth_buf,FIXP_DBL * old_synth,INT * pitch,INT * old_T_pf,INT coreCoderFrameLength,INT synSfd,INT nbSubfrSuperfr)1076*e5436536SAndroid Build Coastguard Worker void Acelp_PostProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch,
1077*e5436536SAndroid Build Coastguard Worker                           INT *old_T_pf, INT coreCoderFrameLength, INT synSfd,
1078*e5436536SAndroid Build Coastguard Worker                           INT nbSubfrSuperfr) {
1079*e5436536SAndroid Build Coastguard Worker   int n;
1080*e5436536SAndroid Build Coastguard Worker 
1081*e5436536SAndroid Build Coastguard Worker   /* store last part of synth_buf (which is not handled by the IMDCT overlap)
1082*e5436536SAndroid Build Coastguard Worker    * for next frame */
1083*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(old_synth, synth_buf + coreCoderFrameLength,
1084*e5436536SAndroid Build Coastguard Worker             sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY));
1085*e5436536SAndroid Build Coastguard Worker 
1086*e5436536SAndroid Build Coastguard Worker   /* for bass postfilter */
1087*e5436536SAndroid Build Coastguard Worker   for (n = 0; n < synSfd; n++) {
1088*e5436536SAndroid Build Coastguard Worker     old_T_pf[n] = pitch[nbSubfrSuperfr + n];
1089*e5436536SAndroid Build Coastguard Worker   }
1090*e5436536SAndroid Build Coastguard Worker }
1091*e5436536SAndroid Build Coastguard Worker 
1092*e5436536SAndroid Build Coastguard Worker #define L_FAC_ZIR (LFAC)
1093*e5436536SAndroid Build Coastguard Worker 
CLpd_Acelp_Zir(const FIXP_LPC A[],const INT A_exp,CAcelpStaticMem * acelp_mem,const INT length,FIXP_DBL zir[],int doDeemph)1094*e5436536SAndroid Build Coastguard Worker void CLpd_Acelp_Zir(const FIXP_LPC A[], const INT A_exp,
1095*e5436536SAndroid Build Coastguard Worker                     CAcelpStaticMem *acelp_mem, const INT length,
1096*e5436536SAndroid Build Coastguard Worker                     FIXP_DBL zir[], int doDeemph) {
1097*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER);
1098*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(length <= L_FAC_ZIR);
1099*e5436536SAndroid Build Coastguard Worker 
1100*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(tmp_buf, acelp_mem->old_syn_mem,
1101*e5436536SAndroid Build Coastguard Worker             M_LP_FILTER_ORDER * sizeof(FIXP_DBL));
1102*e5436536SAndroid Build Coastguard Worker   FDKmemset(tmp_buf + M_LP_FILTER_ORDER, 0, L_FAC_ZIR * sizeof(FIXP_DBL));
1103*e5436536SAndroid Build Coastguard Worker 
1104*e5436536SAndroid Build Coastguard Worker   Syn_filt(A, A_exp, length, &tmp_buf[M_LP_FILTER_ORDER],
1105*e5436536SAndroid Build Coastguard Worker            &tmp_buf[M_LP_FILTER_ORDER]);
1106*e5436536SAndroid Build Coastguard Worker   if (!doDeemph) {
1107*e5436536SAndroid Build Coastguard Worker     /* if last lpd mode was TD concealment, then bypass deemph */
1108*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(zir, tmp_buf, length * sizeof(*zir));
1109*e5436536SAndroid Build Coastguard Worker   } else {
1110*e5436536SAndroid Build Coastguard Worker     Deemph(&tmp_buf[M_LP_FILTER_ORDER], &zir[0], length,
1111*e5436536SAndroid Build Coastguard Worker            &acelp_mem->de_emph_mem);
1112*e5436536SAndroid Build Coastguard Worker     scaleValues(zir, length, -ACELP_OUTSCALE);
1113*e5436536SAndroid Build Coastguard Worker   }
1114*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER);
1115*e5436536SAndroid Build Coastguard Worker }
1116*e5436536SAndroid Build Coastguard Worker 
CLpd_AcelpPrepareInternalMem(const FIXP_DBL * synth,UCHAR last_lpd_mode,UCHAR last_last_lpd_mode,const FIXP_LPC * A_new,const INT A_new_exp,const FIXP_LPC * A_old,const INT A_old_exp,CAcelpStaticMem * acelp_mem,INT coreCoderFrameLength,INT clearOldExc,UCHAR lpd_mode)1117*e5436536SAndroid Build Coastguard Worker void CLpd_AcelpPrepareInternalMem(const FIXP_DBL *synth, UCHAR last_lpd_mode,
1118*e5436536SAndroid Build Coastguard Worker                                   UCHAR last_last_lpd_mode,
1119*e5436536SAndroid Build Coastguard Worker                                   const FIXP_LPC *A_new, const INT A_new_exp,
1120*e5436536SAndroid Build Coastguard Worker                                   const FIXP_LPC *A_old, const INT A_old_exp,
1121*e5436536SAndroid Build Coastguard Worker                                   CAcelpStaticMem *acelp_mem,
1122*e5436536SAndroid Build Coastguard Worker                                   INT coreCoderFrameLength, INT clearOldExc,
1123*e5436536SAndroid Build Coastguard Worker                                   UCHAR lpd_mode) {
1124*e5436536SAndroid Build Coastguard Worker   int l_div =
1125*e5436536SAndroid Build Coastguard Worker       coreCoderFrameLength / NB_DIV; /* length of one ACELP/TCX20 frame */
1126*e5436536SAndroid Build Coastguard Worker   int l_div_partial;
1127*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *syn, *old_exc_mem;
1128*e5436536SAndroid Build Coastguard Worker 
1129*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_START(synth_buf, FIXP_DBL,
1130*e5436536SAndroid Build Coastguard Worker                         PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER);
1131*e5436536SAndroid Build Coastguard Worker   syn = &synth_buf[M_LP_FILTER_ORDER];
1132*e5436536SAndroid Build Coastguard Worker 
1133*e5436536SAndroid Build Coastguard Worker   l_div_partial = PIT_MAX_MAX + L_INTERPOL - l_div;
1134*e5436536SAndroid Build Coastguard Worker   old_exc_mem = acelp_mem->old_exc_mem;
1135*e5436536SAndroid Build Coastguard Worker 
1136*e5436536SAndroid Build Coastguard Worker   if (lpd_mode == 4) {
1137*e5436536SAndroid Build Coastguard Worker     /* Bypass Domain conversion. TCXTD Concealment does no deemphasis in the
1138*e5436536SAndroid Build Coastguard Worker      * end. */
1139*e5436536SAndroid Build Coastguard Worker     FDKmemcpy(
1140*e5436536SAndroid Build Coastguard Worker         synth_buf, &synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)],
1141*e5436536SAndroid Build Coastguard Worker         (PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER) * sizeof(FIXP_DBL));
1142*e5436536SAndroid Build Coastguard Worker     /* Set deemphasis memory state for TD concealment */
1143*e5436536SAndroid Build Coastguard Worker     acelp_mem->deemph_mem_wsyn = scaleValueSaturate(synth[-1], ACELP_OUTSCALE);
1144*e5436536SAndroid Build Coastguard Worker   } else {
1145*e5436536SAndroid Build Coastguard Worker     /* convert past [PIT_MAX_MAX+L_INTERPOL+M_LP_FILTER_ORDER] synthesis to
1146*e5436536SAndroid Build Coastguard Worker      * preemph domain */
1147*e5436536SAndroid Build Coastguard Worker     E_UTIL_preemph(&synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)],
1148*e5436536SAndroid Build Coastguard Worker                    synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER);
1149*e5436536SAndroid Build Coastguard Worker     scaleValuesSaturate(synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER,
1150*e5436536SAndroid Build Coastguard Worker                         ACELP_OUTSCALE);
1151*e5436536SAndroid Build Coastguard Worker   }
1152*e5436536SAndroid Build Coastguard Worker 
1153*e5436536SAndroid Build Coastguard Worker   /* Set deemphasis memory state */
1154*e5436536SAndroid Build Coastguard Worker   acelp_mem->de_emph_mem = scaleValueSaturate(synth[-1], ACELP_OUTSCALE);
1155*e5436536SAndroid Build Coastguard Worker 
1156*e5436536SAndroid Build Coastguard Worker   /* update acelp synth filter memory */
1157*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(acelp_mem->old_syn_mem,
1158*e5436536SAndroid Build Coastguard Worker             &syn[PIT_MAX_MAX + L_INTERPOL - M_LP_FILTER_ORDER],
1159*e5436536SAndroid Build Coastguard Worker             M_LP_FILTER_ORDER * sizeof(FIXP_DBL));
1160*e5436536SAndroid Build Coastguard Worker 
1161*e5436536SAndroid Build Coastguard Worker   if (clearOldExc) {
1162*e5436536SAndroid Build Coastguard Worker     FDKmemclear(old_exc_mem, (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL));
1163*e5436536SAndroid Build Coastguard Worker     C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL,
1164*e5436536SAndroid Build Coastguard Worker                         PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER);
1165*e5436536SAndroid Build Coastguard Worker     return;
1166*e5436536SAndroid Build Coastguard Worker   }
1167*e5436536SAndroid Build Coastguard Worker 
1168*e5436536SAndroid Build Coastguard Worker   /* update past [PIT_MAX_MAX+L_INTERPOL] samples of exc memory */
1169*e5436536SAndroid Build Coastguard Worker   if (last_lpd_mode == 1) {        /* last frame was TCX20 */
1170*e5436536SAndroid Build Coastguard Worker     if (last_last_lpd_mode == 0) { /* ACELP -> TCX20 -> ACELP transition */
1171*e5436536SAndroid Build Coastguard Worker       /* Delay valid part of excitation buffer (from previous ACELP frame) by
1172*e5436536SAndroid Build Coastguard Worker        * l_div samples */
1173*e5436536SAndroid Build Coastguard Worker       FDKmemmove(old_exc_mem, old_exc_mem + l_div,
1174*e5436536SAndroid Build Coastguard Worker                  sizeof(FIXP_DBL) * l_div_partial);
1175*e5436536SAndroid Build Coastguard Worker     } else if (last_last_lpd_mode > 0) { /* TCX -> TCX20 -> ACELP transition */
1176*e5436536SAndroid Build Coastguard Worker       E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, l_div_partial);
1177*e5436536SAndroid Build Coastguard Worker     }
1178*e5436536SAndroid Build Coastguard Worker     E_UTIL_residu(A_new, A_new_exp, syn + l_div_partial,
1179*e5436536SAndroid Build Coastguard Worker                   old_exc_mem + l_div_partial, l_div);
1180*e5436536SAndroid Build Coastguard Worker   } else { /* prev frame was FD, TCX40 or TCX80 */
1181*e5436536SAndroid Build Coastguard Worker     int exc_A_new_length = (coreCoderFrameLength / 2 > PIT_MAX_MAX + L_INTERPOL)
1182*e5436536SAndroid Build Coastguard Worker                                ? PIT_MAX_MAX + L_INTERPOL
1183*e5436536SAndroid Build Coastguard Worker                                : coreCoderFrameLength / 2;
1184*e5436536SAndroid Build Coastguard Worker     int exc_A_old_length = PIT_MAX_MAX + L_INTERPOL - exc_A_new_length;
1185*e5436536SAndroid Build Coastguard Worker     E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, exc_A_old_length);
1186*e5436536SAndroid Build Coastguard Worker     E_UTIL_residu(A_new, A_new_exp, &syn[exc_A_old_length],
1187*e5436536SAndroid Build Coastguard Worker                   &old_exc_mem[exc_A_old_length], exc_A_new_length);
1188*e5436536SAndroid Build Coastguard Worker   }
1189*e5436536SAndroid Build Coastguard Worker   C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL,
1190*e5436536SAndroid Build Coastguard Worker                       PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER);
1191*e5436536SAndroid Build Coastguard Worker 
1192*e5436536SAndroid Build Coastguard Worker   return;
1193*e5436536SAndroid Build Coastguard Worker }
1194*e5436536SAndroid Build Coastguard Worker 
CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem * acelp_mem,INT length)1195*e5436536SAndroid Build Coastguard Worker FIXP_DBL *CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem *acelp_mem, INT length) {
1196*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(length <= PIT_MAX_MAX + L_INTERPOL);
1197*e5436536SAndroid Build Coastguard Worker   return acelp_mem->old_exc_mem;
1198*e5436536SAndroid Build Coastguard Worker }
1199*e5436536SAndroid Build Coastguard Worker 
CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs,CAcelpChannelData * acelp,INT acelp_core_mode,INT coreCoderFrameLength,INT i_offset)1200*e5436536SAndroid Build Coastguard Worker INT CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs, CAcelpChannelData *acelp,
1201*e5436536SAndroid Build Coastguard Worker                    INT acelp_core_mode, INT coreCoderFrameLength,
1202*e5436536SAndroid Build Coastguard Worker                    INT i_offset) {
1203*e5436536SAndroid Build Coastguard Worker   int nb_subfr = coreCoderFrameLength / L_DIV;
1204*e5436536SAndroid Build Coastguard Worker   const UCHAR *num_acb_index_bits =
1205*e5436536SAndroid Build Coastguard Worker       (nb_subfr == 4) ? num_acb_idx_bits_table[0] : num_acb_idx_bits_table[1];
1206*e5436536SAndroid Build Coastguard Worker   int nbits;
1207*e5436536SAndroid Build Coastguard Worker   int error = 0;
1208*e5436536SAndroid Build Coastguard Worker 
1209*e5436536SAndroid Build Coastguard Worker   const int PIT_MIN = PIT_MIN_12k8 + i_offset;
1210*e5436536SAndroid Build Coastguard Worker   const int PIT_FR2 = PIT_FR2_12k8 - i_offset;
1211*e5436536SAndroid Build Coastguard Worker   const int PIT_FR1 = PIT_FR1_12k8;
1212*e5436536SAndroid Build Coastguard Worker   const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset);
1213*e5436536SAndroid Build Coastguard Worker   int T0, T0_frac, T0_min = 0, T0_max;
1214*e5436536SAndroid Build Coastguard Worker 
1215*e5436536SAndroid Build Coastguard Worker   if (PIT_MAX > PIT_MAX_MAX) {
1216*e5436536SAndroid Build Coastguard Worker     error = AAC_DEC_DECODE_FRAME_ERROR;
1217*e5436536SAndroid Build Coastguard Worker     goto bail;
1218*e5436536SAndroid Build Coastguard Worker   }
1219*e5436536SAndroid Build Coastguard Worker 
1220*e5436536SAndroid Build Coastguard Worker   acelp->acelp_core_mode = acelp_core_mode;
1221*e5436536SAndroid Build Coastguard Worker 
1222*e5436536SAndroid Build Coastguard Worker   nbits = MapCoreMode2NBits(acelp_core_mode);
1223*e5436536SAndroid Build Coastguard Worker 
1224*e5436536SAndroid Build Coastguard Worker   /* decode mean energy with 2 bits : 18, 30, 42 or 54 dB */
1225*e5436536SAndroid Build Coastguard Worker   acelp->mean_energy = FDKreadBits(hBs, 2);
1226*e5436536SAndroid Build Coastguard Worker 
1227*e5436536SAndroid Build Coastguard Worker   for (int sfr = 0; sfr < nb_subfr; sfr++) {
1228*e5436536SAndroid Build Coastguard Worker     /* read ACB index and store T0 and T0_frac for each ACELP subframe. */
1229*e5436536SAndroid Build Coastguard Worker     error = DecodePitchLag(hBs, num_acb_index_bits[sfr], PIT_MIN, PIT_FR2,
1230*e5436536SAndroid Build Coastguard Worker                            PIT_FR1, PIT_MAX, &T0, &T0_frac, &T0_min, &T0_max);
1231*e5436536SAndroid Build Coastguard Worker     if (error) {
1232*e5436536SAndroid Build Coastguard Worker       goto bail;
1233*e5436536SAndroid Build Coastguard Worker     }
1234*e5436536SAndroid Build Coastguard Worker     acelp->T0[sfr] = (USHORT)T0;
1235*e5436536SAndroid Build Coastguard Worker     acelp->T0_frac[sfr] = (UCHAR)T0_frac;
1236*e5436536SAndroid Build Coastguard Worker     acelp->ltp_filtering_flag[sfr] = FDKreadBits(hBs, 1);
1237*e5436536SAndroid Build Coastguard Worker     switch (nbits) {
1238*e5436536SAndroid Build Coastguard Worker       case 12: /* 12 bits AMR-WB codebook is used */
1239*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1);
1240*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5);
1241*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 1);
1242*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5);
1243*e5436536SAndroid Build Coastguard Worker         break;
1244*e5436536SAndroid Build Coastguard Worker       case 16: /* 16 bits AMR-WB codebook is used */
1245*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1);
1246*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5);
1247*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5);
1248*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5);
1249*e5436536SAndroid Build Coastguard Worker         break;
1250*e5436536SAndroid Build Coastguard Worker       case 20: /* 20 bits AMR-WB codebook is used */
1251*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 5);
1252*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5);
1253*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5);
1254*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5);
1255*e5436536SAndroid Build Coastguard Worker         break;
1256*e5436536SAndroid Build Coastguard Worker       case 28: /* 28 bits AMR-WB codebook is used */
1257*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9);
1258*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9);
1259*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5);
1260*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5);
1261*e5436536SAndroid Build Coastguard Worker         break;
1262*e5436536SAndroid Build Coastguard Worker       case 36: /* 36 bits AMR-WB codebook is used */
1263*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9);
1264*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9);
1265*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9);
1266*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9);
1267*e5436536SAndroid Build Coastguard Worker         break;
1268*e5436536SAndroid Build Coastguard Worker       case 44: /* 44 bits AMR-WB codebook is used */
1269*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13);
1270*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13);
1271*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9);
1272*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9);
1273*e5436536SAndroid Build Coastguard Worker         break;
1274*e5436536SAndroid Build Coastguard Worker       case 52: /* 52 bits AMR-WB codebook is used */
1275*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13);
1276*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13);
1277*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 13);
1278*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 13);
1279*e5436536SAndroid Build Coastguard Worker         break;
1280*e5436536SAndroid Build Coastguard Worker       case 64: /* 64 bits AMR-WB codebook is used */
1281*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][0] = FDKreadBits(hBs, 2);
1282*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][1] = FDKreadBits(hBs, 2);
1283*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][2] = FDKreadBits(hBs, 2);
1284*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][3] = FDKreadBits(hBs, 2);
1285*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][4] = FDKreadBits(hBs, 14);
1286*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][5] = FDKreadBits(hBs, 14);
1287*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][6] = FDKreadBits(hBs, 14);
1288*e5436536SAndroid Build Coastguard Worker         acelp->icb_index[sfr][7] = FDKreadBits(hBs, 14);
1289*e5436536SAndroid Build Coastguard Worker         break;
1290*e5436536SAndroid Build Coastguard Worker       default:
1291*e5436536SAndroid Build Coastguard Worker         FDK_ASSERT(0);
1292*e5436536SAndroid Build Coastguard Worker         break;
1293*e5436536SAndroid Build Coastguard Worker     }
1294*e5436536SAndroid Build Coastguard Worker     acelp->gains[sfr] = FDKreadBits(hBs, 7);
1295*e5436536SAndroid Build Coastguard Worker   }
1296*e5436536SAndroid Build Coastguard Worker 
1297*e5436536SAndroid Build Coastguard Worker bail:
1298*e5436536SAndroid Build Coastguard Worker   return error;
1299*e5436536SAndroid Build Coastguard Worker }
1300